ARCHIVED from builddistributedsystem.com on 2026-04-28 — URL: https://builddistributedsystem.com/tracks/proxies/tasks/task-21-2-2-auth-gateway
TASK

Implementation

API gateways centralize authentication and authorization logic, securing all backend services without duplicating auth code in each service.

Authentication flow:

1. Client sends request with auth token
   Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

2. Gateway validates token signature and expiration
   - Decode JWT without verifying signature (get header)
   - Verify signature using public key
   - Check expiration (exp claim)
   - Extract user claims (sub, name, roles, permissions)

3. Gateway enforces authorization
   - Check if user has required permissions
   - If authorized: add user context headers, forward to backend
   - If unauthorized: return 401/403 immediately

4. Backend receives request with user context
   X-User-ID: user123
   X-User-Role: admin
   X-User-Permissions: read,write,delete

JWT validation:

function validateJWT(token: string): JWTClaims {
  try {
    // Decode and verify signature
    const claims = jwt.verify(token, publicKey);

    // Check expiration
    if (claims.exp < Date.now() / 1000) {
      throw new Error("Token expired");
    }

    // Check issuer
    if (claims.iss !== "https://auth.example.com") {
      throw new Error("Invalid issuer");
    }

    return claims;
  } catch (error) {
    throw new Error("Invalid token");
  }
}

Example gateway auth:

// Request with valid JWT:
Request:  {"type": "api_request", "msg_id": 1, "method": "GET", "path": "/api/users/123", "headers": {"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs..."}}
Response: {"type": "api_response", "in_reply_to": 1, "status": 200, "service": "users-service", "user_context": {"user_id": "user123", "role": "admin", "permissions": ["read", "write"]}}

// Request with expired token:
Request:  {"type": "api_request", "msg_id": 2, "method": "GET", "path": "/api/users/123", "headers": {"Authorization": "Bearer expired_token..."}}
Response: {"type": "api_response", "in_reply_to": 2, "status": 401, "error": "Token expired"}

// Request without permission:
Request:  {"type": "api_request", "msg_id": 3, "method": "DELETE", "path": "/api/users/123", "headers": {"Authorization": "Bearer user_token..."}, "required_permission": "delete"}
Response: {"type": "api_response", "in_reply_to": 3, "status": 403, "error": "Insufficient permissions: required [delete], have [read]"}

Sample Test Cases

Valid JWT passes through gatewayTimeout: 5000ms
Input
{"src":"client","dest":"gateway","body":{"type":"init","msg_id":1,"jwt_public_key":"public_key_here"}}
{"src":"client","dest":"gateway","body":{"type":"api_request","msg_id":2,"method":"GET","path":"/api/users/123","headers":{"Authorization":"Bearer valid_jwt_here"}}}
Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "init_ok", "in_reply_to": 1}}
Invalid JWT returns 401Timeout: 5000ms
Input
{
  "src": "client",
  "dest": "gateway",
  "body": {
    "type": "api_request",
    "msg_id": 1,
    "method": "GET",
    "path": "/api/users/123",
    "headers": {
      "Authorization": "Bearer invalid_jwt"
    }
  }
}
Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "api_response", "in_reply_to": 1, "status": 401, "error": "Invalid or expired token"}}

Hints

Hint 1
Validate JWT tokens at the gateway before routing to backend
Hint 2
Extract user claims (sub, roles, permissions) from token
Hint 3
Enforce authorization: check permissions before allowing access
Hint 4
Support multiple auth schemes: API keys, JWT, OAuth2 tokens
Hint 5
Add user context headers to downstream requests
OVERVIEW

Theoretical Hub

Concept overview coming soon

Key Concepts

API gateway authenticationJWT validationOAuth2authorizationcentralized securitytoken validation
main.py
python
Implement Authentication and Authorization at Gateway - Proxies | Build Distributed Systems