Announcing CIMD support for MCP Client registration
Learn more
API Authentication
Jul 11, 2025

JSON Web Token profile for OAuth 2.0 access tokens (RFC 9068)

Hrishikesh Premkumar
Founding Architect

OAuth 2.0 has become the standard authorization framework for securing APIs. At the heart of OAuth 2.0 are access tokens, credentials that allow an application to access protected resources on behalf of a user or itself.

Typically, access tokens indicate that the client app has been granted permissions to access specific resources, such as user data.

OAuth 2.0 itself doesn't specify a format for access tokens, leading many implementations to adopt proprietary token formats. RFC 9068 addresses this by defining a standardized JSON Web Token (JWT) profile for OAuth 2.0 access tokens, enabling better interoperability and security.

Why JWT access tokens?

Originally, OAuth 2.0 tokens were opaque strings requiring additional calls to authorization servers for validation (token introspection). JWT access tokens eliminate this overhead by embedding structured token information directly into a cryptographically signed JWT, allowing resource servers to independently validate tokens.

For developers, RFC 9068 simplifies token validation by eliminating additional round trips to authorization servers for token introspection.

Practical example: E-commerce API

Consider an e-commerce mobile app that allows customers to view their profile information, manage orders, and check their purchase history. To access these protected resources, the app needs an access token issued by an authorization server after successful user authentication. This access token authorizes the app to interact securely with the e-commerce resource server at https://api.ecommerce.com.

Structure of a JWT access token

JWT access tokens contain standardized claims within their payload. RFC 9068 specifies the following required claims:

iss (Issuer): URL identifying the authorization server.
sub (Subject): Identifier for the customer or client application.
aud (Audience): Identifies the intended resource server.
exp (Expiration): Indicates when the token becomes invalid.
iat (Issued At): Timestamp of token issuance.
jti (JWT ID): Unique identifier to prevent replay attacks.
client_id: Identifier of the OAuth client application.

Here's a sample JWT access token for our e-commerce app:

{ "iss": "https://auth.ecommerce.com/", "sub": "customer-789", "aud": "https://api.ecommerce.com/", "exp": 1735682400, "iat": 1704146400, "jti": "unique-token-id-12345", "client_id": "ecommerce-mobile-app", "scope": "profile orders" }

Requesting a JWT access token

The mobile app explicitly requests JWT access tokens by including a resource parameter and scopes within the authorization request. Here’s an example request:

GET /authorize?response_type=code &client_id=ecommerce-mobile-app &scope=profile%20orders &redirect_uri=ecommerceapp://callback &resource=https://api.ecommerce.com/ HTTP/1.1 Host: auth.ecommerce.com

The resulting JWT token issued upon successful authorization looks like this:

Header:

{ "typ": "at+jwt", "alg": "RS256", "kid": "ecom-key-001" }
  • kid (Key ID): Identifies the specific key used by the authorization server to sign the token.
{ "iss": "https://auth.ecommerce.com/", "sub": "customer-789", "aud": "https://api.ecommerce.com/", "exp": 1735682400, "iat": 1704146400, "jti": "unique-token-id-12345", "client_id": "ecommerce-mobile-app", "scope": "profile orders" }

Validating JWT access tokens

The e-commerce resource server validates JWT access tokens independently by:

  1. Verifying the token's signature using public keys advertised by the authorization server.
  2. Ensuring token claims (iss, aud, exp) match expected values.
  3. Checking that the token type (typ) header explicitly states at+jwt.

Here's a simplified Node.js validation logic example for our e-commerce API:

const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); const client = jwksClient({ jwksUri: 'https://auth.ecommerce.com/.well-known/jwks.json' }); function getKey(header, callback){ client.getSigningKey(header.kid, (err, key) => { callback(null, key.publicKey || key.rsaPublicKey); }); } jwt.verify(token, getKey, { audience: 'https://api.ecommerce.com/', issuer: 'https://auth.ecommerce.com/', algorithms: ['RS256'] }, (err, decoded) => { if (err) { // Handle invalid token console.error("Token validation failed", err); } else { // Token is valid console.log("Token valid:", decoded); } });

💡 Pro tip: Validate the aud claim properly to avoid cross-resource confusion or unauthorized access.

Security considerations

RFC 9068 mandates specific practices to ensure security:

  • JWT access tokens MUST NOT use the none algorithm.
  • Tokens should clearly distinguish themselves from OpenID Connect ID tokens (typ header set to at+jwt).
  • Authorization servers should use distinct identifiers (aud) for different resources to avoid cross-JWT confusion.

Privacy considerations

As JWT tokens carry user information, the e-commerce authorization server must consider privacy implications:

  • Avoid including unnecessary sensitive information.
  • Encrypt tokens or sensitive claims when necessary.
  • Use unique subject (sub) identifiers per resource to prevent tracking across resource servers.

Developer best practices

  • Regularly rotate signing keys and publish them via JWKS endpoint.
  • Ensure clock synchronization (for claim validation like exp and iat).
  • Clearly document the claims used within your JWT tokens for consumer APIs.

Edge cases to watch out for

  • Token reuse across multiple resources causing JWT confusion.
  • Handling token expiration gracefully on resource servers.
  • Ensuring public key availability for JWT signature validation.

When NOT to use this RFC

This RFC can be avoided in highly sensitive environments requiring opaque tokens and frequent token introspection. It’s also best avoided if there is limited support for cryptographic operations.

Conclusion

RFC 9068 brings standardization to JWT access tokens, facilitating secure, efficient, and interoperable OAuth 2.0 implementations. This standardized profile reduces complexity and enhances security by clearly defining token structure, issuance, and validation processes.

By adopting RFC 9068, developers and organizations can ensure their OAuth 2.0 implementations are more secure.

FAQs

Why is RFC 9068 important for modern B2B API security?

RFC 9068 provides a standardized JSON Web Token profile for OAuth 2.0 access tokens. Historically, many implementations used proprietary or opaque formats that required constant communication with authorization servers. By adopting this standard, organizations can ensure interoperability across different vendors and platforms. This approach allows resource servers to validate tokens independently using cryptographic signatures, which significantly reduces latency and improves overall system performance. For technical leaders, this means moving away from vendor lock-in and embracing a robust, industry recognized architecture that simplifies both development and security audits within complex B2B ecosystems.

How does RFC 9068 improve system performance and scalability?

Traditionally, resource servers relied on token introspection, which involved making external network calls to the authorization server for every request. RFC 9068 eliminates this overhead by embedding necessary metadata and permissions directly within a signed JWT. This enables stateless validation at the resource server level. By reducing these round trips, developers can build more responsive applications and handle higher traffic volumes without putting excessive load on the authentication infrastructure. This architectural shift is particularly beneficial for distributed systems and microservices where minimizing network latency is critical for maintaining a seamless user experience across multiple domains.

What specific claims are required in an RFC 9068 token?

The RFC specifies several mandatory claims to ensure security and consistency. These include the issuer URL, the subject identifier, and the intended audience for the token. Additionally, it requires expiration and issuance timestamps to manage token lifecycles, along with a unique JWT identifier to prevent replay attacks. The client identifier of the requesting application must also be present. These standardized claims allow resource servers to perform comprehensive validation checks without needing custom logic. By adhering to these requirements, engineering teams can build more predictable and secure authorization flows that are easy to maintain across different services.

How should resource servers properly validate JWT access tokens?

Effective validation involves multiple critical steps to ensure the integrity and authenticity of the token. First, the resource server must verify the cryptographic signature using the public keys provided by the authorization server via its JWKS endpoint. It is also essential to check the header for a specific type value designated as at plus jwt. Beyond signatures, the server must validate the issuer, audience, and expiration claims to confirm the token is being used correctly. Implementing these checks prevents common vulnerabilities like token substitution or cross resource confusion, ensuring that only authorized agents and users can access protected data.

What are the security risks of using the none algorithm?

RFC 9068 strictly mandates that JWT access tokens must never use the none algorithm. This algorithm would allow a token to be accepted without any cryptographic verification, making it trivial for attackers to forge tokens and gain unauthorized access to protected resources. By requiring strong signing algorithms like RS256, the standard ensures that the identity and permissions within the token cannot be tampered with after issuance. For CISOs and security architects, enforcing this requirement is a fundamental step in protecting the integrity of the authorization framework and preventing serious security breaches across the entire organizational network.

Why should we distinguish between access tokens and ID tokens?

While both use the JWT format, access tokens and ID tokens serve very different purposes in an authentication flow. Access tokens are designed for authorization, granting permissions to access specific resources, whereas ID tokens provide information about the authenticated user identity. RFC 9068 addresses this by requiring a specific header type for access tokens. This distinction prevents a common security flaw where an application might incorrectly accept an ID token as a valid credential for resource access. Maintaining this clear separation ensures that the security context remains accurate and that permissions are handled by the appropriate token type.

How can developers handle privacy when using JWT access tokens?

Privacy is a major concern because JWTs often contain user related claims that are visible to any holder. To mitigate risks, authorization servers should avoid including unnecessary sensitive information in the token payload. When sensitivity is high, tokens can be encrypted to prevent unauthorized parties from reading the contents. Another effective strategy is using unique subject identifiers for different resource servers, which prevents tracking users across multiple platforms. By following these privacy first design principles, engineering teams can comply with data protection regulations while still benefiting from the efficiency and scalability of standardized JWT access tokens in their applications.

When is it better to use opaque tokens instead?

Although RFC 9068 offers many advantages, it might not be suitable for every environment. In highly sensitive scenarios where you need the ability to revoke access instantly, opaque tokens coupled with frequent introspection may be preferable. Opaque tokens also keep internal system details completely hidden from the client side. Furthermore, if your resource servers lack the necessary cryptographic capabilities or libraries to perform local JWT validation, using simpler token formats might be a more practical choice. Architects should evaluate their specific security requirements and infrastructure constraints before deciding which token format best serves their technical and business goals.

What best practices should teams follow for key management?

Robust key management is essential for maintaining the security of a JWT based authorization system. Organizations must regularly rotate their signing keys to minimize the impact if a key is ever compromised. These keys should be published through a secure JWKS endpoint so that resource servers can fetch them dynamically. Additionally, it is important to ensure that clocks are synchronized across all servers to avoid errors during the validation of expiration and issuance timestamps. By automating these processes and clearly documenting the claims used, developers can build a more resilient and secure authentication infrastructure that scales with their business needs.

No items found.
Secure your APIs with OAuth
On this page
Share this article
Secure your APIs with OAuth

Acquire enterprise customers with zero upfront cost

Every feature unlocked. No hidden fees.
Start Free
$0
/ month
1 million Monthly Active Users
100 Monthly Active Organizations
1 SSO connection
1 SCIM connection
10K Connected Accounts
Unlimited Dev & Prod environments