How to Set Up API Authentication with JWT

JSON Web Tokens (JWT) are a widely-used, stateless authentication mechanism for APIs — letting your server verify a client's identity without needing a database lookup on every request.

How JWT Authentication Works

  1. User logs in with credentials
  2. Server verifies credentials, issues a signed JWT containing user identity/claims
  3. Client includes this token in subsequent requests (typically an Authorization header)
  4. Server verifies the token's signature on each request — no database lookup needed to confirm authenticity

JWT Structure

A JWT has three parts separated by dots: header.payload.signature. The header and payload are base64-encoded JSON (readable, not encrypted); the signature proves the token wasn't tampered with.

Implementing JWT Issuance (Node.js Example)

const jwt = require('jsonwebtoken');

app.post('/login', async (req, res) => {
  const user = await authenticateUser(req.body.email, req.body.password);
  if (!user) return res.status(401).json({ error: 'Invalid credentials' });

  const token = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
  );

  res.json({ token });
});

Verifying Tokens on Protected Routes

function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.status(401).json({ error: 'No token provided' });

  const token = authHeader.split(' ')[1];

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
}

app.get('/protected', authenticate, (req, res) => {
  res.json({ message: `Hello, user ${req.user.userId}` });
});

Choosing an Appropriate Expiration Time

Short-lived tokens (minutes to a few hours) limit the impact if a token is ever stolen, at the cost of requiring more frequent re-authentication or refresh — balance based on your application's security requirements.

Implementing Refresh Tokens (For Longer Sessions)

Rather than issuing long-lived access tokens, issue a short-lived access token plus a longer-lived refresh token, stored securely, used only to obtain new access tokens:

const accessToken = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '15m' });
const refreshToken = jwt.sign({ userId: user.id }, process.env.REFRESH_SECRET, { expiresIn: '7d' });

// Store refreshToken securely (httpOnly cookie or database), never in localStorage

Where to Store the Token on the Client

Storage MethodRisk
localStorageVulnerable to XSS attacks — any injected script can read it
httpOnly cookieProtected from XSS reading, but requires CSRF protection

For most web applications, an httpOnly, secure cookie is the safer choice over localStorage.

Critical Security Practices

  • Use a strong, randomly generated secret for signing — never a guessable string
  • Store the signing secret as an environment variable, never in code — see How to Manage Environment Variables and Secrets on a VPS
  • Always set an expiration (expiresIn) — never issue tokens that never expire
  • Use HTTPS everywhere — tokens transmitted over plain HTTP can be intercepted

Handling Token Revocation

JWTs are stateless by design, meaning there's no built-in way to revoke a specific token before its natural expiration. For scenarios requiring revocation (logout, compromised account), maintain a server-side blocklist of revoked token IDs, checked on each request — a partial trade-off against pure statelessness.

Common Errors

"jwt malformed" — the token wasn't correctly extracted from the header, or was corrupted in transit; verify the exact header format matches what your verification code expects.

Token verification fails despite a valid-looking token — confirm the signing secret used to verify matches exactly what was used to issue it (common issue when secrets differ between environments).

Best Practices

  • Keep access tokens short-lived; use refresh tokens for longer sessions
  • Never store the JWT secret in version control
  • Prefer httpOnly cookies over localStorage for web clients

Continue Reading

Browse more articles in Object Storage, Messaging & APIs.

  • jwt authentication, api auth, json web token, token based authentication
  • 0 Kunder som kunne bruge dette svar
Hjalp dette svar dig?

Relaterede artikler

How to Set Up Self-Hosted S3-Compatible Object Storage with MinIO

MinIO is a high-performance, self-hosted object storage server compatible with the S3 API —...

How to Use Object Storage for Application File Uploads

Storing user-uploaded files directly on your application server's disk creates scaling and...

How to Install and Configure RabbitMQ on a VPS

RabbitMQ is a widely-used, robust message broker — enabling applications to communicate...

How to Install and Configure Redis as a Message Queue

Redis, primarily known as a cache, also works well as a lightweight message queue for simpler use...

How to Build and Secure a REST API on a VPS

This guide covers the essential security and architecture practices for deploying a REST API on...