What Is an Access Token Service?
An access token service issues short-lived cryptographically signed tokens that authorize access to protected resources. JWTs (JSON Web Tokens) are the dominant format: self-contained, verifiable without a database lookup, and extensible via custom claims. The critical design concerns are algorithm selection for signing, JWKS endpoint exposure for public key distribution, safe key rotation without service interruption, and a flexible claim customization pipeline.
Requirements
Functional Requirements
- Issue signed JWTs with a configurable expiry (default 15 minutes) for authenticated principals.
- Support RS256 (RSA + SHA-256) and ES256 (ECDSA + P-256) signing algorithms.
- Expose a JWKS (JSON Web Key Set) endpoint so resource servers can verify tokens without calling the auth service on every request.
- Rotate signing keys on a schedule (default 30 days) without invalidating tokens issued under the previous key.
- Allow per-client claim customization: inject tenant_id, roles, scopes, and arbitrary metadata.
Non-Functional Requirements
- Token issuance latency under 10 ms at p99.
- JWKS endpoint must be cacheable and available independently of the issuance path.
- Private keys must never appear in logs, error messages, or API responses.
Data Model
Signing Key Record
- kid — Key ID, UUID; included in JWT header so verifiers know which key to use.
- algorithm — RS256 or ES256.
- private_key_ref — reference to encrypted private key in a secrets manager (Vault, AWS KMS); never stored in plaintext in the database.
- public_key_jwk — serialized public key in JWK format; safe to store and serve.
- status — ENUM:
ACTIVE,RETIRING,RETIRED. - created_at, retire_at, delete_at.
Token Issuance Log (optional, for audit)
- jti — JWT ID, unique per token; enables revocation lookup.
- sub, client_id, issued_at, expires_at, kid.
Core Algorithm: Token Issuance
Step 1 — Principal Verification
Receive an authenticated request (valid session cookie, client credentials, or authorization code). Extract the principal identity and client context.
Step 2 — Claim Assembly
Build the standard claims: iss (issuer URL), sub (subject), aud (audience), iat, exp, jti. Invoke the claim customization pipeline: load per-client claim rules from a configuration store, evaluate each rule against the principal context, and merge custom claims (roles, scopes, tenant_id, feature flags) into the payload. Validate that no reserved claims are overwritten by custom rules.
Step 3 — Signing
Retrieve the current ACTIVE signing key. Fetch the private key from the secrets manager (cache the decrypted key object in-process for the key lifetime to avoid per-token KMS calls). Sign the JWT using the selected algorithm. Include kid in the JOSE header. Return the compact serialization.
Key Rotation Algorithm
Key rotation must be seamless: resource servers cache the JWKS with a short TTL (5 minutes) and must be able to verify tokens issued under both the old and new key during the overlap period.
- T-7 days: Generate new key pair. Set status to
ACTIVE. Add to JWKS. Old key moves toRETIRING(still in JWKS, still valid for verification). - T+0 (rotation day): New key becomes the default signing key. All new tokens use the new kid.
- T+max_token_lifetime: Old key moves to
RETIRED. Remove from JWKS. Tokens signed with it are now expired anyway. - delete_at: Remove private key from secrets manager. Retain public key record for audit.
JWKS Endpoint Design
Serve GET /.well-known/jwks.json as a static JSON document containing all ACTIVE and RETIRING public keys. Set Cache-Control: max-age=300, stale-while-revalidate=60. Resource servers should implement a key refresh on encountering an unknown kid rather than hard-failing, enabling zero-downtime rotation. The JWKS document should be served from a CDN or edge cache to handle high verification traffic without hitting the auth service.
API Design
- POST /token — issue an access token; accepts grant_type, client credentials or authorization code.
- GET /.well-known/jwks.json — public key set for token verification.
- GET /.well-known/openid-configuration — discovery document pointing to JWKS and token endpoints.
- POST /token/introspect — active/inactive check for opaque token compatibility (optional).
- POST /admin/keys/rotate — trigger manual key rotation (admin-only, protected by mTLS).
Scalability Considerations
Token issuance is CPU-bound (RSA signing is more expensive than ECDSA; prefer ES256 for high-throughput scenarios). Cache the loaded private key object in-process to eliminate KMS round-trips. Run multiple stateless issuance instances behind a load balancer; all share the same signing key fetched from a central secrets manager. The JWKS endpoint is read-only and cacheable; serve it from a CDN with 5-minute TTL and origin shield to handle millions of verifications per second without load on the auth service.
Summary
An access token service combines secure key management, flexible claim assembly, and cacheable public key distribution. RS256 provides broad compatibility; ES256 offers faster signing for high throughput. Overlap-based key rotation ensures zero-downtime transitions, and a CDN-backed JWKS endpoint decouples token verification scale from issuance capacity.
{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “How do you choose between RS256 and ES256 for JWT signing?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “RS256 (RSA + SHA-256) uses 2048-bit or 4096-bit keys and is universally supported but produces large signatures and is slower to sign. ES256 (ECDSA P-256 + SHA-256) produces compact 64-byte signatures, is faster to sign and verify, and provides equivalent security at much shorter key lengths. Prefer ES256 for new systems unless you need compatibility with legacy verifiers that only support RSA. Both are asymmetric, enabling public JWKS distribution for stateless verification.”
}
},
{
“@type”: “Question”,
“name”: “How should a JWKS endpoint be designed in an access token service?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Expose GET /.well-known/jwks.json returning a JSON object with a keys array of JWK objects. Each JWK includes kty, use: sig, alg, kid, and the public key material (n+e for RSA, x+y+crv for EC). Always include all currently active signing keys (at minimum the current key and any recently rotated key still validating live tokens). Set Cache-Control: max-age=3600 to reduce load; verifiers should re-fetch on unknown kid rather than treating a cache miss as an error.”
}
},
{
“@type”: “Question”,
“name”: “How do you implement rolling key rotation in an access token service?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Generate a new signing key pair before the current key's retirement date. Publish the new public key in JWKS immediately (alongside the old key). Begin signing new tokens with the new key. Continue publishing the old public key in JWKS until all tokens signed with it have expired (i.e., max token TTL after the switch). Remove the old key from JWKS only after that window. This ensures verifiers can always validate tokens in flight during the transition.”
}
},
{
“@type”: “Question”,
“name”: “How do you build an extensible claim customization pipeline in an access token service?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Model claim enrichment as an ordered pipeline of ClaimEnricher plugins, each receiving the current claims map and returning a mutated copy. Standard enrichers handle sub, iat, exp, iss, aud. Custom enrichers add domain claims (roles, tenant_id, feature_flags) by querying internal services. Register enrichers via configuration or dependency injection so new claim types can be added without modifying the core signing path. Cache enricher results with a short TTL to avoid per-token service calls at high throughput.”
}
}
]
}
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering
See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems