cors
auth-jwt capability
auth-jwt adds JWT authentication middleware to your service, validating tokens on protected routes and making claims available to handlers downstream.
Why JWT for API Authentication
Section titled “Why JWT for API Authentication”Server-side sessions require shared state — every instance of your service needs to reach the same session store. That’s a coupling point that complicates horizontal scaling and increases operational overhead. JWTs move that state into the token itself: the token is signed, self-contained, and verifiable by any instance that has the signing key.
This works well for microservices where multiple services need to verify identity independently. Each service validates the token signature locally, extracts the claims it needs (user ID, roles, tenant ID), and proceeds without a network hop to a central session store.
The tradeoff is that JWTs can’t be individually revoked without additional infrastructure (a token denylist, usually backed by Redis). For most APIs this is acceptable — short token lifetimes combined with refresh token rotation cover the majority of revocation needs. If you need per-token revocation with no latency, you want sessions, not JWTs.
What You Get
Section titled “What You Get”- Middleware that validates JWT tokens on protected routes
- Claims extraction into request context (Go) or request object (TypeScript)
signTokenandverifyTokenutility functions- Bearer token extraction from the
Authorizationheader - Route-level opt-in: unprotected routes are unaffected
Go Implementation
Section titled “Go Implementation”The Go capability uses golang-jwt/jwt — the maintained fork of the original dgrijalva/jwt-go package. The scaffold provides an AuthMiddleware function that validates the token signature, checks expiry, and stores claims in the request context.
// Middleware wraps protected route groups.protected := router.Group("/api", middleware.Auth(cfg.JWT.Secret))
// Handlers retrieve claims from context — no need to re-parse the token.claims, ok := middleware.ClaimsFromContext(r.Context())if !ok { http.Error(w, "unauthorized", http.StatusUnauthorized) return}userID := claims.SubjectToken signing is handled by a SignToken function that takes a Claims struct and returns the signed string. The signing algorithm defaults to HS256 — adequate for most services. If you need asymmetric signing (so multiple services can verify without sharing a secret), switch to RS256 by passing an RSA private key.
The middleware distinguishes between an invalid signature (returns 401) and an expired token (returns 401 with a specific error code that clients can use to trigger a refresh).
TypeScript Implementation
Section titled “TypeScript Implementation”The TypeScript capability uses jose — a comprehensive JWT library that implements the JOSE standards (JWS, JWE, JWK, JWT) with full TypeScript types and support for both symmetric and asymmetric algorithms.
The scaffold exports three functions: signToken, verifyToken, and extractBearerToken. These compose into the auth middleware.
import { signToken, verifyToken, extractBearerToken } from './auth/jwt';
// Sign a token at login time.const token = await signToken( { sub: user.id, role: user.role }, { expiresIn: '1h' });
// Middleware extracts and verifies on every protected request.export async function authMiddleware(req: Request, res: Response, next: NextFunction) { const raw = extractBearerToken(req); if (!raw) return res.status(401).json({ error: 'missing token' });
const claims = await verifyToken(raw); if (!claims) return res.status(401).json({ error: 'invalid token' });
req.user = claims; next();}jose uses the Web Crypto API under the hood, which is available natively in Node.js 18+ and all modern runtimes. No native bindings, no build-time issues.
Combining with CORS
Section titled “Combining with CORS”If your API serves browser clients, JWT auth and CORS interact at preflight. The browser sends an OPTIONS request before the actual request — that preflight must succeed without an auth check, or the browser will never send the credentialed request. The scaffold configures CORS to exclude OPTIONS from middleware processing.
For multi-tenant services, extract the tenant ID from JWT claims rather than from request headers. A tenant ID in a header is trivially forged; a tenant ID inside a signed token is not. See multi-tenancy for how this pattern is enforced.
Requirements & Suggestions
Section titled “Requirements & Suggestions”Requires: http-api
Suggests: cors, rate-limiting
Add to Your Service
Section titled “Add to Your Service”verikt new my-service --cap http-api,auth-jwt# or add to an existing service:verikt add auth-jwtRelated Capabilities
Section titled “Related Capabilities”rate-limiting
multi-tenancy
oauth2