JWT Structure & Validation

Comprehensive guide to AuthOS JSON Web Tokens, including structure, signing, and backend validation code examples.

Updated Dec 29, 2025 Edit this page

JWT Structure & Validation

AuthOS uses JSON Web Tokens (JWT) for stateless, secure authentication. This guide details the token structure, signing mechanism, and how to validate tokens in your backend services.

JWT Overview

A JWT consists of three parts separated by dots (.):

  1. Header: Algorithm and token type
  2. Payload: User data and claims
  3. Signature: Cryptographic proof of integrity
aaaaa.bbbbb.ccccc
Header.Payload.Signature

Signing Algorithm

All JWTs are signed using RS256 (RSA Signature with SHA-256).

  • Asymmetric: Uses a Private Key (held by AuthOS) to sign, and a Public Key (exposed via JWKS) to verify.
  • Security: You do not need any secrets to validate tokens.

Token Structure

1. Header

The header typically contains:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "sso-key-2025-01-01"
}
  • alg: Algorithm used (RS256)
  • typ: Token type (JWT)
  • kid: Key ID, essential for identifying which public key to use for validation.

2. Payload (Claims)

The payload contains statements about the user and authentication context (Claims).

{
  "sub": "user_123456789",
  "email": "user@example.com",
  "org": "acme-corp",
  "service": "billing-app",
  "plan": "enterprise",
  "features": ["audit-logs", "sso"],
  "iat": 1704067200,
  "exp": 1704068100,
  "iss": "https://sso.example.com",
  "aud": "billing-app"
}

Standard Claims

  • sub (Subject): Unique user identifier.
  • iss (Issuer): URL of the AuthOS instance.
  • aud (Audience): The service or client the token is intended for.
  • exp (Expiration Time): Unix timestamp when the token expires.
  • iat (Issued At): Unix timestamp when the token was created.

Custom Claims

  • org: Organization slug (if authenticated in org context).
  • service: Service slug (if authenticated for a specific service).
  • plan: Subscription tier active for this user/org.
  • features: Array of enabled feature flags.
  • is_platform_owner: Boolean indicating super-admin status.

Token Validation

Your backend must validate every token before granting access.

JWKS Endpoint

Public keys are exposed at: GET /.well-known/jwks.json

Response:

{
  "keys": [
    {
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "kid": "sso-key-2025-01-01",
      "n": "base64-modulus...",
      "e": "AQAB"
    }
  ]
}

Validation Steps

  1. Extract Token: Get from Authorization: Bearer <token> header.
  2. Decode Header: Read the kid from the JWT header.
  3. Fetch Key: Look up the kid in the JWKS (cache this!).
  4. Verify Signature: Check that the signature matches the payload using the public key.
  5. Validate Claims: Ensure exp is in the future and iss/aud match expectations.

Code Examples

Node.js (Express)

Using express-jwt and jwks-rsa:

import { expressjwt } from 'express-jwt';
import jwksRsa from 'jwks-rsa';

const checkJwt = expressjwt({
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: 'https://sso.example.com/.well-known/jwks.json'
  }),
  audience: 'your-service-slug',
  issuer: 'https://sso.example.com',
  algorithms: ['RS256']
});

app.get('/api/private', checkJwt, (req, res) => {
  res.send(`Hello ${req.auth.email}!`);
});

Python (Flask)

Using pyjwt:

import jwt
from jwt import PyJWKClient

url = "https://sso.example.com/.well-known/jwks.json"
jwks_client = PyJWKClient(url)

def validate_token(token):
    signing_key = jwks_client.get_signing_key_from_jwt(token)
    data = jwt.decode(
        token,
        signing_key.key,
        algorithms=["RS256"],
        audience="your-service-slug",
        issuer="https://sso.example.com"
    )
    return data

Best Practices

  1. Cache JWKS: Don’t fetch keys on every request. Cache them.
  2. Rate Limit: Limit calls to the JWKS endpoint to prevent DOS.
  3. Check Scope/Context: Just because a token is valid doesn’t mean the user has access. Check org and features claims.
  4. Handle Rotation: Keys rotate periodically. Ensure your cache invalidates or refreshes when it encounters an unknown kid.