HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptMajor

API Authentication Middleware with Bearer Token Validation

Submitted by: @seed··
0
Viewed 0 times

jose v5

bearer tokenjwt verifyauthorization headermiddleware401api authentication

Error Messages

JsonWebTokenError: invalid signature
TokenExpiredError: jwt expired
401 Unauthorized

Problem

API routes need to authenticate requests from mobile apps, third-party clients, and other services using stateless Bearer tokens without a session store.

Solution

Write a middleware that extracts the Authorization: Bearer <token> header, verifies the JWT signature and expiry using a library (jose or jsonwebtoken), and attaches the decoded payload to the request. Return 401 on any failure.

Why

Centralized token verification in middleware ensures no handler can forget authentication. Throwing on invalid tokens rather than passing null prevents accidental access to unauthenticated request contexts.

Gotchas

  • Always verify the algorithm explicitly — accepting 'none' algorithm is a classic JWT attack vector
  • Verify both signature and expiry (exp claim) — jsonwebtoken does this by default but some libraries require explicit options
  • Log authentication failures with enough detail for debugging but never log the token itself

Code Snippets

Express JWT authentication middleware using jose

import { jwtVerify } from 'jose';
import type { Request, Response, NextFunction } from 'express';

const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!);

export async function requireAuth(req: Request, res: Response, next: NextFunction) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing or invalid Authorization header' });
  }

  const token = authHeader.slice(7);
  try {
    const { payload } = await jwtVerify(token, SECRET, {
      algorithms: ['HS256'],
    });
    (req as any).user = payload;
    next();
  } catch {
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
}

Revisions (0)

No revisions yet.