Skip to content
Ashish.
All posts
Diagram comparing JWT self-contained structure with opaque token reference architecture.
6 min readDevelopmentBackend Developers#jwt#opaque-tokens#authentication#security#backend#token-design#introspection

JWT vs Opaque Tokens: The Architecture of Trust

An examination of JWT and opaque token architectures, comparing introspection, revocation, and security trade-offs for backend systems.

By Ashish Kumar

When designing authentication systems, backend developers often face a binary choice between two token formats: JSON Web Tokens (JWT) and opaque reference tokens. While both serve to validate identity, they operate on fundamentally different mechanisms regarding state, revocation, and security boundaries. Understanding these mechanisms is critical for selecting the right architecture for your backend systems.

The Core Mechanism: Self-Contained vs. Reference

The primary difference lies in where the identity information resides and how it is validated.

JWT: The Self-Contained Assertion

A JWT is a self-contained, signed JSON object as defined in RFC 7519. It contains claims (data about the user) directly within the token payload. Validation is stateless: the server verifies the cryptographic signature using a shared secret (HMAC) or a public key (RSA/ECDSA). If the signature is valid and the token has not expired, the server trusts the claims inside.

Mechanism:

  1. Client Request: Sends Authorization: Bearer <jwt_token>.
  2. Server Validation:
    • Decodes the header to find the algorithm (alg) and key ID (kid).
    • Retrieves the corresponding public key or secret.
    • Cryptographically verifies the signature over the header.payload portion.
    • Checks standard claims like exp (expiration) and iss (issuer).
  3. Outcome: If valid, the server extracts the user ID from the payload and proceeds. No database lookup is required for identity validation.
// Example JWT Payload (base64url decoded)
{
  "sub": "user_123",
  "name": "Alice",
  "iat": 1678886400,
  "exp": 1678890000
}

Opaque Token: The Reference Pointer

An opaque token is a random string with no inherent meaning or structure. It acts as a pointer or reference to user data stored securely in the authorization server’s backend (e.g., Redis, SQL database). Validation is stateful: the server must look up the token to verify its validity and retrieve associated claims, typically via an introspection endpoint as specified in RFC 7662.

Mechanism:

  1. Client Request: Sends Authorization: Bearer <opaque_token>.
  2. Server Validation:
    • Sends the token to an introspection endpoint (or looks it up locally if the resource server shares the store).
    • The Authorization Server checks if the token exists, is active, and has not expired.
    • Returns the associated claims (e.g., active: true, scope: "read:users", sub: "user_123").
  3. Outcome: The resource server trusts the introspection response. The actual user data never leaves the secure boundary of the Authorization Server.
POST /oauth2/introspect HTTP/1.1
Content-Type: application/x-www-form-urlencoded
 
token=<opaque_token_value>&token_type_hint=access_token

Revocation: The State Management Dilemma

Revocation is where the architectural trade-offs become most apparent.

JWT Revocation: The Blocklist Problem

Since JWTs are self-contained and stateless, there is no built-in way to "delete" a token once issued. To revoke a JWT, you must implement external state management.

  1. Blocklist Approach: Maintain a list of revoked JWT JTI (JWT ID) values in a fast key-value store like Redis. On every request, check if the JWT’s JTI is in the blocklist. This adds latency to every request and requires cleanup jobs to remove old entries. The JTI claim is defined in RFC 7519 specifically to support such scenarios, though the mechanism for checking it is left to the implementation.
  2. Short-Lived Tokens: Issue JWTs with very short lifespans (e.g., 5-15 minutes). This reduces the window of opportunity for an attacker but increases the complexity of token refresh flows.

Opaque Token Revocation: Immediate Invalidation

Opaque tokens simplify revocation because the token is merely a key to a database record.

  1. Deletion: To revoke a token, simply delete the corresponding record from the database or Redis.
  2. Immediate Effect: The next time the client presents the token, the introspection lookup fails, and access is denied. No blocklist checks are needed during validation.

This makes opaque tokens preferable for applications requiring strict security compliance where immediate session termination is critical (e.g., banking, healthcare).

Security and Privacy Trade-offs

Data Exposure

  • JWT: The payload is base64-encoded, not encrypted (unless JWE is used). Any party with the token can read the claims. This is safe for non-sensitive data (user ID, roles) but dangerous for sensitive data (email, SSN) unless the transport layer (TLS) is trusted and the payload is encrypted using RFC 7516 (JSON Web Encryption).
  • Opaque Tokens: The payload never travels to the client. Sensitive data remains on the Authorization Server. The client only holds a random string. This minimizes the attack surface for data leakage via logs, browser history, or XSS attacks.

Attack Surface

  • JWT: The resource server must have access to the signing key (or public key). If the resource server is compromised, attackers can forge valid tokens. The validation logic is complex and prone to implementation errors, such as the critical vulnerability of accepting alg: none which bypasses signature verification entirely.
  • Opaque Tokens: The introspection endpoint is a new attack vector. If the Authorization Server is down, resource servers cannot validate tokens. This introduces a single point of failure and additional network latency for every authenticated request.

Choosing the Right Design

FeatureJWT (Self-Contained)Opaque Token (Reference)
ValidationStateless, cryptographicStateful, database lookup
RevocationComplex (blocklist/short TTL)Simple (delete record)
PayloadVisible to client (signed)Hidden from client
LatencyLow (no DB call)Higher (introspection call)
Best ForMicroservices, high scale, public APIsEnterprise apps, strict security, internal services

Conclusion

There is no universally superior choice. Use JWTs when you need high performance, low latency, and decentralized validation across many microservices, and when you can tolerate the complexity of revocation. Use opaque tokens when security, privacy, and immediate revocation are paramount, and you can absorb the latency of introspection calls.

Many modern systems adopt a hybrid approach: use short-lived opaque tokens for the initial handshake, then issue JWTs for subsequent requests within the same session. This balances the security benefits of opaque tokens with the performance benefits of JWTs.

Common Pitfalls

When implementing either architecture, developers frequently make critical errors that compromise security or performance.

  1. Storing Sensitive Data in JWTs: Never store PII (Personally Identifiable Information), passwords, or secrets in JWT payloads. Even with signatures, the data is readable by anyone who intercepts the token unless encrypted via JWE.
  2. Failing to Rotate Signing Keys: If a private key is compromised, an attacker can forge valid tokens signed with it. Implement key rotation strategies and ensure resource servers can handle multiple active public keys during transition periods.
  3. Ignoring Introspection Endpoint Failures: In opaque token systems, treating the introspection call as optional or caching invalid tokens leads to security holes. Always handle timeouts and failures gracefully, typically by denying access rather than falling back to a cached or assumed-valid state.
  4. Algorithm Confusion Attacks: When validating JWTs, strictly enforce the expected alg header value. Do not rely on the client to specify the algorithm, as this can lead to signature bypass vulnerabilities.

Practical Takeaways

  • Decide on State First: If your system requires immediate revocation or strict auditability of active sessions, start with opaque tokens.
  • Evaluate Latency Tolerance: If your microservices architecture cannot afford the network overhead of an introspection call per request, JWTs provide necessary performance gains.
  • Minimize Payload Size: For JWTs, keep claims minimal. Store complex user data in the database and reference it via the JWT's sub or jti claim.
  • Implement Key Rotation: Regardless of token type, have a plan for rotating signing keys or revoking compromised credentials.
  • Secure Transport: Always use TLS for token transmission. For JWTs, consider JWE if tokens traverse untrusted networks or are stored in client-side storage.

Related posts