OAuth Working Group | V. Bertocci |
Internet-Draft | Auth0 |
Intended status: Standards Track | March 24, 2019 |
Expires: September 25, 2019 |
JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens
draft-bertocci-oauth-access-token-jwt-00
This specification defines a profile for issuing OAuth2 access tokens in JSON web token (JWT) format. Authorization servers and resource servers from different vendors can leverage this profile to issue and consume access tokens in interoperable manner.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on September 25, 2019.
Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
The original OAuth 2.0 Authorization Framework specification does not mandate any specific format for access tokens. While that remains perfectly appropriate for many important scenario, in-market use has shown that many commercial OAuth2 implementations elected to issue access tokens using a format that can be parsed and validated by resource servers directly, without further authorization server involvement. The approach is particularly common in topologies where the authorization server and resource server are not co-located, are not ran by the same entity, or are otherwise separated by some boundary. All of the known commercial implementations known at this time leverage the JSON Web Tokens(JWT) format.
Most vendor specific JWT access tokens share the same functional layout, including information in forms of claims meant to support the same scenarios: token validation, transporting authorization information in forms of scopes and entitlements, carrying identity information about the subject, and so on. The differences are mostly confined to the claim names and syntax used to represent the same entities, suggesting that interoperability could be easily achieved by standardizing on a common set of claims and validation rules.
The assumption that access tokens are associated to specific information doesn't appear only in commercial implementations. Various specifications in the OAuth2 family (such as resource indicators, bearer token usage and others) postulate the presence in access tokens of scoping mechanisms, such as an audience. The family of specifications associated to introspection also indirectly suggest a fundamental set of information access tokens are expected to carry or at least be associated with.
This specification aims to provide a standardized and interoperable profile as an alternative to the proprietary JWT access tokens layouts going forward. Besides defining a common set of mandatory and optional claims, the profile provides clear indications on how authorization requests parameters determine the content of the issued JWT access token, how an authorization server can publish metadata relevant to the JWT access tokens it issues, and how a resource server should validate incoming JWT access tokens.
Finally, this specification provides security and privacy considerations meant to prevent common mistakes and anti patterns that are likely to occur in naive use of the JWT format to represent access tokens.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This specification uses the terms "access token", "refresh token", "authorization server", "resource server", "authorization endpoint", "authorization request", "authorization response", "token endpoint", "grant type", "access token request", "access token response", and "client" defined by The OAuth 2.0 Authorization Framework.
JWT access tokens are regular JWT tokens complying with the requirements described in this section.
Although JWT access tokens can use any signing algorithm, use of asymmetric algorithms is RECOMMENDED as it simplifies the process of acquiring validation information for resource servers (see Section 4).
The typ header parameter for a JWT access token MUST be at+jwt. See the security considerations section for details on the importance of preventing JWT access tokens to be interpreted as id_tokens.
The following claims are used in the JWT access token data structure.
Commercial authorization servers will often include resource owner attributes directly in access tokens, so that resource servers can consume them directly for authorization or other purposes without any further roudtrips to introspection ([RFC7662]) or userinfo ([OpenID.Core]) endpoints.
This profile does not introduce any mechanism for a client to directly request the presence of specific claims in JWT access tokens, as the authorization server can determine what additional claims are required by a particular resource server by taking in consideration the client_id of the client, the scope and the resource parameters included in the request.
Any additional attributes whose semantic is well described by the attributes description found in section 5.1 of [OpenID.Core] SHOULD be codified in JWT access tokens via the corresponding claim names in that section of the OpenID Connect specification.
Authorization servers including resource owner attributes in JWT access tokens should exercise care and verify that all privacy requirements are met, as discussed in Section 6.
If an authorization request includes a scope parameter, the corresponding issued JWT access token MUST include a scope claim as defined in section 4.2 of [TokenExchange].
All the individual scopes strings in the scope claim MUST have meaning for the resource indicated in the aud claim.
Many authorization servers embed in the access tokens they issue authorization attributes that go beyond the delegated scenarios described by [RFC7519]. Typical examples include resource owner memberships in roles and groups that are relevant to the resource being accessed, entitlements assigned to the resource owner for the targeted resource that the authorization server knows about, and so on.
An authorization server wanting to include such attributes in a JWT access token SHOULD use as claim types the attributes described by section 4.1.2 of SCIM Core ([RFC7643]) and in particular roles, groups and entitlements. As in their original definition in [RFC7643] , this profile does not provide a specific vocabulary for those entities.
[[note 1 some commercial authorization server include claims indicating whether the client authenticated with the authorization server as a confidential client, for the purpose of determining whether the client_id can be used as a reliable indicator of the identity of the caller (and take thatinto account for authorization decisions). Discussions at OSW2019 on how to achieve this were inconclusive hence this was punted for further discussion]]
[[note 2 some commercial authorization server include claims indicating whether the resource owner authenticated with a federated identity provider rather than directly with the authorization server. During discussions at OSW2019 there were lukewarm reactions. One proposed line of investigation was to examine what https://tools.ietf.org/html/draft-ietf-secevent-token-13#page-10 does with the sub structure and see whether some mechanisms can be applicable here; however for this early draft no further investigation was made and no info is provided beyond this note]]
An authorization server can issue a JWT access token in response to any authorization grant defined by [RFC6749] and subsequent extensions meant to result in an access token.
Every JWT access token MUST include an aud claim (see Section 2.2).
If the request includes a resource parameter (as defined in [ResourceIndicators]), the resulting JWT access token aud claim MUST have the same value as the resource parameter in the request.
Example request below:
GET /as/authorization.oauth2?response_type=token &client_id=s6BhdRkqt3&state=laeb &scope=openid%20profile%20reademail &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb &resource=https%3A%2F%2Frs.example.com%2F HTTP/1.1 Host: authorization-server.example.com
Figure 1: Authorization Request with Resource and Scope Parameters
Once redeemed, the code obtained from the request above will result in a JWT access token in the form shown below:
{"typ":"at+JWT","alg":"RS256","kid":"RjEwOwOA"} { "iss": "https://authorization-server.example.com/", "sub": " 5ba552d67", "aud": "https://rs.example.com/", "exp": 1544645174, "client_id": "s6BhdRkqt3_", "scope": "openid profile reademail" }
Figure 2: A JWT Access Token
If it receives a request for an access token containing more than one resource parameter, an authorization server issuing JWT access tokens MUST reject the request and fail with [[TODO: select appropriate error code]]. See Section 2.2 and Section 5 for more details on how this measure ensures there's no confusion on to what resource the access token granted scopes apply.
If the request does not include a resource parameter, the authorization server MUST use in the aud claim a default resource indicator. If a scope parameter is present in the request, the authorization server SHOULD use it to infer the value of the default resource indicator to be used in the aud claim. The mechanism through which scopes are associated to default resource indicator values is outside the scope of this specification. If the values in the scope parameter refer to different default resource indicator values, the authorization server SHOULD reject the request with [[TODO: select appropriate error code]].
For the purpose of facilitating validation data retrieval, it is RECOMMENDED that authorization servers sign JWT access tokens with an asymmetric algorithm.
Authorization servers SHOULD implement OAuth 2.0 Authorization Server Metadata to advertise to resource servers its signing keys via jwks_uri and what iss claim value to expect via the issuer metadata value. Alternatively, authorization servers implementing OpenID connect MAY use the Openid connect discovery document for the same purpose. If an authorization server supports both AS metadata and Openid discovery, the values provided MUST be consistent across the two publication methods.
An authorization server MAY elect to use different keys to sign id_tokens and JWT access tokens.
When invoked as described in OAuth2 bearer token usage, resource servers receiving a JWT access token MUST validate it in the following manner.
[[Note: I would like to express the requirement that the resource server should not ignore authorization information when present in the JWT access token. I don't know if this belongs here or elsewhere. Here's some possible language: If the JWT access token includes authorization claims as described in the authorization claims section, the resource server SHOULD use them in combination with any other contextual information available to determine whether the current call should be authorized or rejected. Details about how a resource server performs those checks is beyond the scope of this profile specification.]]
The JWT access token data layout described here is very similar to the one of the id_token as defined by [OpenID.Core]. Without the explicit typing required in this profile, in line with the recommendations in [JWT.BestPractices] there would be the risk of attackers using JWT access tokens in lieu of id_tokens.
This profile explicitly forbids the use of multi value aud claim when the individual values refer to different resources, as that would introduce confusion about what scopes apply to which resource- possibly opening up avenues for elevation of delegated privileges attacks. Alternative techniques to prevent scope confusion include "scope stuffing", imposing to every individual scope string to include a reference to the resource they are meant to be applied to, but its application is problematic (scope opacity violations, size inflation, more error conditions become possible when the combination of requested scopes and resource indicators is invalid) and the observed frequency of the scenario doesn't warrant complicating the more common cases.
[[todo: expand on Audience, issuer and expiration validation checks serve the usual purposes. What else?]]
As JWT access tokens carry information by value, it now becomes possible for requestors and receivers to directly peek inside the token claims collection.
In scenarios in which JWT access tokens are accessible to the end user, it should be evaluated whether the information can be accessed without privacy violations (for example, if an end user would simply access his or her own personal information) or if the token should be encrypted.
In every scenario, the content of the JWT access token will eventually be accessible to the resource server. It's important to evaluate whether the resource server gained the proper entitlement to have access to any content received in form of claims, for example through user consent in some form, policies and agreements with the organization running the authorization servers, and so on.
[[TODO: MIME type registration for at+jwt ]]
[RFC6750] | Jones, M. and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", RFC 6750, DOI 10.17487/RFC6750, October 2012. |
[RFC7519] | Jones, M., Bradley, J. and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015. |
[RFC7644] | Hunt, P., Grizzle, K., Ansari, M., Wahlstroem, E. and C. Mortimore, "System for Cross-domain Identity Management: Protocol", RFC 7644, DOI 10.17487/RFC7644, September 2015. |
[RFC7662] | Richer, J., "OAuth 2.0 Token Introspection", RFC 7662, DOI 10.17487/RFC7662, October 2015. |
The initial set of requirements informing this specification was extracted by numerous examples of access tokens issued in JWT format by production systems. Thanks to Dominick Bauer (IdentityServer), Brian Campbell (PingIdentity), Daniel Dobalian (Microsoft), Karl Guinness (Okta) for providing sample tokens issued by their products and services. Brian Campbell and Filip Skokan provided early feedback that shaped the direction of the specification. This profile was discussed at lenght during the OAuth Security Workshop 2019, with several individuals contributing ideas and feedback. The author would like to acknowledge the contributions of:
John Bradley, Brian Campbell Vladimir Dzhuvinov, Torsten Lodderstedt, Nat Sakimura, Hannes Tschofenig and everyone who actively participated in the unconference discussions.
[[ to be removed by the RFC Editor before publication as an RFC ]]
draft-bertocci-oauth-access-token-jwt-00