Tutorial

Express.js Integration

Add AuthMe token validation to your Express.js API in minutes — middleware, protected routes, and user context.

Installation

Terminal
npm install authme-sdk express

Token Validation Middleware

Create a reusable middleware that extracts and validates the Bearer token from every incoming request.

middleware/auth.ts
import { AuthmeClient } from 'authme-sdk';
import type { Request, Response, NextFunction } from 'express';

const authme = new AuthmeClient({
  url: process.env.AUTHME_URL!,
  realm: process.env.AUTHME_REALM!,
});

export async function requireAuth(
  req: Request,
  res: Response,
  next: NextFunction
) {
  const authHeader = req.headers.authorization;

  if (!authHeader?.startsWith('Bearer ')) {
    res.status(401).json({ error: 'Missing token' });
    return;
  }

  const token = authHeader.slice(7);

  try {
    const payload = await authme.verifyToken(token);
    // Attach user info to the request for downstream handlers
    (req as any).user = payload;
    next();
  } catch {
    res.status(401).json({ error: 'Invalid or expired token' });
  }
}

Protecting API Routes

Apply the middleware to individual routes or entire routers.

routes/profile.ts
import { Router } from 'express';
import { requireAuth } from '../middleware/auth';

const router = Router();

// Public route — no auth needed
router.get('/health', (_req, res) => res.json({ ok: true }));

// Protected routes — must have a valid AuthMe token
router.get('/me', requireAuth, (req, res) => {
  const { sub, email, name, roles } = (req as any).user;
  res.json({ id: sub, email, name, roles });
});

router.put('/me/settings', requireAuth, (req, res) => {
  // Only reachable with a valid token
  res.json({ updated: true });
});

export default router;

Role-Based Access

Build a higher-order middleware factory to restrict routes to specific roles.

middleware/roles.ts
import type { Request, Response, NextFunction } from 'express';

export function requireRole(...roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    const userRoles: string[] = (req as any).user?.roles ?? [];
    const hasRole = roles.some((r) => userRoles.includes(r));

    if (!hasRole) {
      res.status(403).json({ error: 'Forbidden' });
      return;
    }
    next();
  };
}

// Usage:
// router.delete('/users/:id', requireAuth, requireRole('admin'), handler);