RFC 8707

Resource Indicators for OAuth 2.0

πŸ“… published February 2020, from ietf

Resource Indicators for OAuth 2.0 πŸ¦‹

Okay bestie, this is RFC 8707 πŸ’– It's an IETF document on the Standards Track, so it's a real Internet standard, not just a vibe. It was written by B. Campbell (Ping Identity), J. Bradley (Yubico), and H. Tschofenig (Arm Limited) in February 2020, and its ISSN is 2070-1721 🌸 The title block doesn't list anything it obsoletes or updates, so it's standing on its own.

Abstract ✨

So this is an extension to the OAuth 2.0 Authorization Framework that adds request parameters. They let a client explicitly tell an authorization server which protected resource(s) it wants access to. No guessing, just clear signalling πŸŽ€

Status of This Memo

This is an Internet Standards Track document πŸ”₯ It's a product of the Internet Engineering Task Force (IETF), it represents the consensus of the IETF community, it got public review, and the Internet Engineering Steering Group (IESG) approved it for publication. For more on Internet Standards, see Section 2 of RFC 7841.

For the current status, any errata, and how to send feedback, check https://www.rfc-editor.org/info/rfc8707 πŸ’…

Copyright (c) 2020 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) as in effect on the date of publication. Please read these carefully, because they describe your rights and restrictions for 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 they're provided without warranty as described in the Simplified BSD License πŸ“œ


Table of Contents

   1.  Introduction
     1.1.  Requirements Notation and Conventions
     1.2.  Terminology
   2.  Resource Parameter
     2.1.  Authorization Request
     2.2.  Access Token Request
   3.  Security Considerations
   4.  Privacy Considerations
   5.  IANA Considerations
     5.1.  OAuth Parameters Registration
     5.2.  OAuth Extensions Error Registration
   6.  References
     6.1.  Normative References
     6.2.  Informative References
   Acknowledgements
   Authors' Addresses

1. Introduction ✨

Okay so, OAuth 2.0 has been deployed and implemented for years now [RFC6749], and people kept running into the same need. In some situations, like an authorization server juggling a ton of diverse resources, the client needs a way to explicitly tell the authorization server where it plans to use the access token it's requesting πŸ¦‹

Knowing the protected resource (aka resource server, application, API, etc.) that will process the access token lets the authorization server build the token the way that entity needs. Like, properly encrypting the token (or the stuff inside it) for one particular resource requires knowing which resource will receive and decrypt it πŸ” Different resources also tend to want different data in (or referenced by) the token, so knowing where it'll be used lets the authorization server mint it accordingly.

Knowing the intended recipient(s) of the access token also helps make the token itself more secure πŸ›‘οΈ Bearer tokens are currently the most common type of OAuth access token, and they let anyone holding the token get into the associated resources. To prevent misuse, several important security assumptions must hold, and one of them is that an access token must only be valid for use at a specific protected resource and for a specific scope of access. Section 5.2 of [RFC6750], for example, says to include the token's intended recipients within the token to prevent token redirect. When the authorization server knows which resource will process the token, it can restrict the token's intended audience to that resource so the token can't be used successfully at other resources 🚫

OAuth scope, from Section 3.3 of [RFC6749], is sometimes overloaded to convey the location or identity of the protected resource. Doing so isn't always feasible or desirable, though πŸ’… Scope is usually about what access is being requested rather than where it'll be redeemed. Values like "email", "admin:org", "user_photos", "channels:read", and "channels:write" are a small sample of scope values in the wild, and they only convey the type of access, not the location or identity.

In some circumstances and deployments, a way for the client to signal where it intends to use the access token it's requesting is important and useful 🌈 A bunch of OAuth 2.0 implementations and deployments have already used proprietary parameters to do this. Going forward, this specification aims to provide a standardized and interoperable alternative to those proprietary approaches ⭐

1.1. Requirements Notation and Conventions

Heads up on the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" πŸ“ They're interpreted as described in BCP 14 [RFC2119] [RFC8174], but only when, and only when, they appear in all capitals, exactly as shown here.

1.2. Terminology

This spec 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", all as defined by The OAuth 2.0 Authorization Framework [RFC6749] πŸ“š

2. Resource Parameter πŸ‘‘

When a client sends requests to the authorization server, it MAY indicate the protected resource (aka resource server, application, API, etc.) it's requesting access to by including the following parameter in the request 🎯

  • resource
    • This tells the authorization server the target service or resource that access is being requested for.
    • Its value MUST be an absolute URI, as specified by Section 4.3 of [RFC3986].
    • The URI MUST NOT include a fragment component.
    • It SHOULD NOT include a query component. We know there are cases where a query component is a useful and necessary part of the resource parameter, though, like when one or more query parameters are used to scope requests to an application 🧚
    • The "resource" parameter URI value is an identifier for the identity of the resource. It MAY be a locator that points to a network-addressable location where the target resource is hosted.
    • Multiple "resource" parameters MAY be used to say that the requested token is meant to be used at multiple resources ✨

The parameter value identifies a resource the client is asking to access. It can carry the location of a protected resource, usually as an https URL, or a more abstract identifier. This lets the authorization server apply policy that fits the resource, like deciding what type and content of tokens to issue, whether and how tokens get encrypted, and what audience restrictions to apply 🌸

The client SHOULD provide the most specific URI it can for the complete API or set of resources it plans to access. In practice, a client knows a base URI for the application or resource it interacts with, and that's the right thing to use as the value of the "resource" parameter πŸ“ The client SHOULD use the base URI of the API as the "resource" parameter value, unless specific knowledge of the resource dictates otherwise. For example, https://api.example.com/ would be used for a resource that's the exclusive application on that host. But if the resource is one of many applications on that host, something like https://api.example.com/app/ would be a more specific value. Another example is an API with multiple endpoints, e.g., when System for Cross-domain Identity Management (SCIM) [RFC7644] has endpoints like https://apps.example.com/scim/Users, https://apps.example.com/scim/Groups, and https://apps.example.com/scim/Schemas. The client would use https://apps.example.com/scim/ as the resource, so the issued access token is valid for all the endpoints of the SCIM API 🫢

The following error code is for an authorization server to indicate problems with the requested resource(s) in response to an authorization request or an access token request. It can also tell the client that it has requested an invalid combination of resource and scope πŸ™ˆ

  • invalid_target
    • The requested resource is invalid, missing, unknown, or malformed.

The authorization server SHOULD audience-restrict issued access tokens to the resource(s) indicated by the "resource" parameter πŸ’œ Audience restrictions can be communicated in JSON Web Tokens [RFC7519] with the aud claim, and the top-level member of the same name provides the audience restriction information in a Token Introspection [RFC7662] response. The authorization server may use the exact "resource" value as the audience, or it may map that value to a more general URI or abstract identifier for the given resource πŸ¦‹

2.1. Authorization Request πŸ’–

okay so when the "resource" parameter shows up in an authorization request to the authorization endpoint, it's basically saying "these are the protected resource(s) I want access to" πŸŽ€ If the access token comes straight back from the authorization endpoint through the implicit flow (Section 4.2 of OAuth 2.0 [RFC6749]), the requested resource applies to that access token ✨ In the code flow (Section 4.1 of OAuth 2.0 [RFC6749]), the authorization endpoint hands back an intermediate thing, the authorization code, and the requested resource applies to the full authorization grant πŸ¦‹

For an authorization request sent as a JSON Web Token (JWT), like with the JWT Secured Authorization Request [JWT-SAR], a single "resource" value is a JSON string, and multiple values get wrapped up in an array of strings 🧚

If the client leaves out the "resource" parameter, the authorization server MAY process the request with no specific resource, or it can use a predefined default resource value 🌸 Or the authorization server MAY require clients to name the resource(s) they plan to access, and MAY fail any request that skips the parameter with an "invalid_target" error πŸ™ˆ The server might use this info to tell the user which resources the client is going to touch on their behalf, to apply policy (like refusing the request because the resources are unknown), and to figure out which resources can be used in later access token requests πŸ’…

If the authorization server can't parse the provided value(s), or it doesn't consider the resource(s) acceptable, it should reject the request with an error response. The error code goes in the "error" parameter as "invalid_target", and it can add more context about why using the "error_description" 🫢

An example of an authorization request where the client tells the authorization server it wants an access token for use at "https://api.example.com/app/" is shown in Figure 1 below. Extra line breaks and indentation are just for display πŸ’œ

GET /as/authorization.oauth2?response_type=token
   &client_id=example-client
   &state=XzZaJlcwYew1u0QBrRv_Gw
   &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
   &resource=https%3A%2F%2Fapi.example.com%2Fapp%2F HTTP/1.1
Host: authorization-server.example.com

Figure 1: Implicit Flow Authorization Request

Below in Figure 2 is an example of an authorization request using the "code" response type, where the client wants access to the resource owner's contacts and calendar data at "https://cal.example.com/" and "https://contacts.example.com/". Extra line breaks and indentation are just for display πŸ“…

GET /as/authorization.oauth2?response_type=code
   &client_id=s6BhdRkqt3
   &state=tNwzQ87pC6llebpmac_IDeeq-mCR2wLDYljHUZUAWuI
   &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
   &scope=calendar%20contacts
   &resource=https%3A%2F%2Fcal.example.com%2F
   &resource=https%3A%2F%2Fcontacts.example.com%2F HTTP/1.1
Host: authorization-server.example.com

Figure 2: Code Flow Authorization Request


2.2. Access Token Request 🌈

When the "resource" parameter is used on an access token request sent to the token endpoint, for all grant types, it tells the server which target service or protected resource the client plans to use the requested access token at πŸ¦‹

Which resource value(s) an authorization server accepts for an access token request is totally up to the server, based on its local policy or configuration πŸ‘‘ For a "refresh_token" or "authorization_code" grant type request, that policy may limit the acceptable resources to the ones the resource owner originally granted, or to a subset of them 🧁 In the "authorization_code" case where the requested resources are a subset of the originally granted set, the authorization server will issue an access token based on that subset, but any refresh token that comes back is bound to the full original grant 🌸

When requesting a token, the client can say which target service(s) it wants to use the token at with the "resource" parameter, and it can ask for a scope with the "scope" parameter ✨ The meaning of that request is that the client wants a token with the requested scope that works at all of the requested target services. Basically, the requested access rights of the token are the cartesian product of all the scopes at all the target services 🧠 As far as possible, when issuing access tokens, the authorization server should downscope the scope value on the token to the value each resource can process and needs to know. (Here, "downscope" means giving fewer permissions than the resource owner originally authorized.) This makes privacy better too πŸ”’ A list of scope values hints that the resource owner uses multiple services, so downscoping a token to only what a particular service needs can limit how much of that info gets revealed across services 🫣 As specified in Section 5.1 of [RFC6749], the authorization server must tell the client the access token's effective scope in the "scope" response parameter value whenever it differs from the scope the client asked for πŸ“

Picking up from the code flow request in Figure 2, the examples below show an "authorization_code" grant type access token request (Figure 3) and response (Figure 4), where the client tells the authorization server it wants the access token for use at "https://cal.example.com/". Extra line breaks and indentation are just for display πŸŽ€

POST /as/token.oauth2 HTTP/1.1
Host: authorization-server.example.com
Authorization: Basic czZCaGRSa3F0Mzpoc3FFelFsVW9IQUU5cHg0RlNyNHlJ
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&code=10esc29BWC2qZB0acc9v8zAv9ltc2pko105tQauZ
&resource=https%3A%2F%2Fcal.example.com%2F

Figure 3: Access Token Request

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store

{
   "access_token":"eyJhbGciOiJFUzI1NiIsImtpZCI6Ijc3In0.eyJpc3MiOi
    JodHRwOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuZXhhbXBsZS5jb20iLCJzdWI
    iOiJfX2JfYyIsImV4cCI6MTU4ODQyMDgwMCwic2NvcGUiOiJjYWxlbmRhciIs
    ImF1ZCI6Imh0dHBzOi8vY2FsLmV4YW1wbGUuY29tLyJ9.nNWJ2dXSxaDRdMUK
    lzs-cYIj8MDoM6Gy7pf_sKrLGsAFf1C2bDhB60DQfW1DZL5npdko1_Mmk5sUf
    zkiQNVpYw",
   "token_type":"Bearer",
   "expires_in":3600,
   "refresh_token":"4LTC8lb0acc6Oy4esc1Nk9BWC0imAwH7kic16BDC2",
   "scope":"calendar"
}

Figure 4: Access Token Response

Next up is a follow-up access token request that uses the refresh token, where the client says it wants an access token for use at "https://contacts.example.com/". That's shown in Figure 5 below, with the response in Figure 6. Extra line breaks and indentation are just for display 🌷

POST /as/token.oauth2 HTTP/1.1
Host: authorization-server.example.com
Authorization: Basic czZCaGRSa3F0Mzpoc3FFelFsVW9IQUU5cHg0RlNyNHlJ
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=4LTC8lb0acc6Oy4esc1Nk9BWC0imAwH7kic16BDC2
&resource=https%3A%2F%2Fcontacts.example.com%2F

Figure 5: Access Token Request

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store

{
   "access_token":"eyJhbGciOiJFUzI1NiIsImtpZCI6Ijc3In0.eyJpc3MiOi
    JodHRwOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuZXhhbXBsZS5jb20iLCJzdWI
    iOiJfX2JfYyIsImV4cCI6MTU4ODQyMDgyNiwic2NvcGUiOiJjb250YWN0cyIs
    ImF1ZCI6Imh0dHBzOi8vY29udGFjdHMuZXhhbXBsZS5jb20vIn0.5f4yhqazc
    OSlJw4y94KPeWNEFQqj2cfeO8x4hr3YbHtIl3nQXnBMw5wREY5O1YbZED-GfH
    UowfmtNaA5EikYAw",
   "token_type":"Bearer",
   "expires_in":3600,
   "scope":"contacts"
}

Figure 6: Access Token Response


3. Security Considerations πŸ”

An audience-restricted access token that a resource legitimately receives can't then be taken by that resource and presented elsewhere to get into other resources illegally πŸ›‘οΈ The "resource" parameter lets a client say which protected resources the requested access token will be used at, and that in turn lets the authorization server put the right audience restrictions on the token πŸ’ͺ

Some servers may host user content or be multi-tenant. To avoid attacks where one tenant uses an access token to sneak into resources owned by a different tenant, it's important to use a specific resource URI, including any part of the URI that identifies the tenant, like a path component 🚨 That way the access token gets audience-restricted in a way that identifies the tenant, and it can't be used at resources owned by someone else, because the audience is invalid there πŸ™…β€β™€οΈ

Multiple occurrences of the "resource" parameter may be included in a token request, but using only a single "resource" parameter is encouraged 🫒 If a bearer token has multiple intended recipients (audiences), then the token is valid at more than one protected resource, and any one of those resources can use it to access any of the others. So a high degree of trust between the parties involved is needed when using access tokens with multiple audiences 🀝 Also, an authorization server may be unwilling or unable to fulfill a token request with multiple resources πŸ₯Ί

Whenever feasible, the "resource" parameter should match the network-addressable location of the protected resource. This lets the client check that the resource it's requesting actually controls the matching network location, which lowers the risk of malicious endpoints grabbing tokens meant for other resources πŸ‘€ If the "resource" parameter contains an abstract identifier, it's the client's job to check out of band that any network endpoint the tokens get sent to is the intended audience for that identifier 🫠


4. Privacy Considerations πŸ™ˆ

In typical OAuth deployments, the authorization server is in a position to observe and track a lot of user and client behavior πŸ‘οΈ That's pretty much inherent to how OAuth works, and this document doesn't really change it. In some cases, though, like when access token introspection isn't being used, using the "resource" parameter defined here may allow tracking at a somewhat more granular and specific level than would otherwise be possible without it πŸ“


5. IANA Considerations πŸ“‹

5.1. OAuth Parameters Registration πŸŽ€

This specification updates the following value in the IANA "OAuth Parameters" registry [IANA.OAuth.Parameters] established by [RFC6749].

Parameter name:  resource
Parameter usage location:  authorization request, token request
Change controller:  IESG
Specification document(s):  RFC 8707

5.2. OAuth Extensions Error Registration πŸ’Œ

okay so this bit is the IANA paperwork for one error code πŸ“‹ This spec is updating the invalid_target error in the IANA "OAuth Extensions Error Registry" [IANA.OAuth.Parameters], which [RFC6749] set up. Here's the entry, exactly as it's written in the registry:

Error name:  invalid_target
Error usage location:  implicit grant error response, token error
      response
Related protocol extension:  resource parameter
Change controller:  IESG
Specification document(s):  RFC 8707

the way this error code now has its own home in the registry πŸŽ€

6. References πŸ“š

6.1. Normative References πŸ”₯

bestie, these are the sources this spec needs to be read alongside. Here they are, word for word:

[IANA.OAuth.Parameters]
           IANA, "OAuth Parameters",
           <https://www.iana.org/assignments/oauth-parameters>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, DOI 10.17487/RFC3986, January 2005,
           <https://www.rfc-editor.org/info/rfc3986>.

[RFC6749]  Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
           RFC 6749, DOI 10.17487/RFC6749, October 2012,
           <https://www.rfc-editor.org/info/rfc6749>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

6.2. Informative References πŸ¦‹

these ones are more like bonus reading. Nice to know, not required to know 🧚

[JWT-SAR]  Sakimura, N. and J. Bradley, "The OAuth 2.0 Authorization
           Framework: JWT Secured Authorization Request (JAR)", Work
           in Progress, Internet-Draft, draft-ietf-oauth-jwsreq-20,
           21 October 2019,
           <https://tools.ietf.org/html/draft-ietf-oauth-jwsreq-20>.

[RFC6750]  Jones, M. and D. Hardt, "The OAuth 2.0 Authorization
           Framework: Bearer Token Usage", RFC 6750,
           DOI 10.17487/RFC6750, October 2012,
           <https://www.rfc-editor.org/info/rfc6750>.

[RFC7519]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
           (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
           <https://www.rfc-editor.org/info/rfc7519>.

[RFC7644]  Hunt, P., Ed., Grizzle, K., Ansari, M., Wahlstroem, E.,
           and C. Mortimore, "System for Cross-domain Identity
           Management: Protocol", RFC 7644, DOI 10.17487/RFC7644,
           September 2015, <https://www.rfc-editor.org/info/rfc7644>.

[RFC7662]  Richer, J., Ed., "OAuth 2.0 Token Introspection",
           RFC 7662, DOI 10.17487/RFC7662, October 2015,
           <https://www.rfc-editor.org/info/rfc7662>.

Acknowledgements 🫢

this whole spec was cooked inside the OAuth Working Group, chaired by Hannes Tschofenig and Rifaat Shekh-Yusef πŸ‘‘ Eric Rescorla, Benjamin Kaduk, and Roman Danyliw were the Security Area Directors, so they were in the room for it too πŸ”’ On top of that, these people dropped ideas, feedback, and wording that made the spec better, and they deserve all the flowers πŸ’

Vittorio Bertocci, Sergey Beryozkin, Roman Danyliw, William Denniss, Vladimir Dzhuvinov, George Fletcher, Dick Hardt, Phil Hunt, Michael Jones, Benjamin Kaduk, Barry Leiba, Torsten Lodderstedt, Anthony Nadalin, Justin Richer, Adam Roach, Nat Sakimura, Rifaat Shekh-Yusef, Filip Skokan, Γ‰ric Vyncke, and Hans Zandbelt. 🌈✨

Authors' Addresses πŸŽ€

meet the people who wrote it! Here are their details, copied exactly:

Brian Campbell
Ping Identity

Email: brian.d.campbell@gmail.com


John Bradley
Yubico

Email: ve7jtb@ve7jtb.com


Hannes Tschofenig
Arm Limited

Email: hannes.tschofenig@gmx.net

that's the whole RFC, bestie, we did it πŸ’–πŸ¦‹πŸ‘‘

πŸ“¦ where this page comes from