Version: | 2.0 |
Date: | 2017-3-12 |
Editor: | Eve Maler, ForgeRock |
Contributors: | Maciej Machulak, Self |
Justin Richer, Bespoke Engineering |
This specification defines a method for an OAuth 2.0 resource server to register resources with an authorization server to put them under protection.
This document is a draft technical specification produced by the User-Managed Access Work Group. See the Kantara Initiative Operating Procedures for more information.
Copyright © 2017 Kantara Initiative and the persons identified as the document authors. All rights reserved.
This document is subject to the Kantara IPR Policy - Option Patent & Copyright: Reciprocal Royalty Free with Opt-Out to Reasonable And Non discriminatory (RAND) (HTML version).
This specification defines a method for an OAuth 2.0 [RFC6749] resource server to register resources with an authorization server to put them under protection.
There are various circumstances under which a resource server may need to communicate information about its resources to its authorization server:
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 [RFC2119].
Unless otherwise noted, all protocol properties and values are case sensitive. JSON [RFC7159] data structures defined by this specification MAY contain extension properties that are not defined in this specification. Any entity receiving or retrieving a JSON data structure SHOULD ignore extension properties it is unable to understand. Extension names that are unprotected from collisions are outside the scope of this specification.
This specification introduces the following new terms and enhancements of OAuth term definitions.
If the authorization server declares its endpoints and any other configuration information in a machine-readable form, it SHOULD convey its resource registration endpoint in this fashion as well.
This specification defines a resource registration API. The authorization server MUST use TLS protection over this endpoint, as governed by [BCP195], which discusses deployment and adoption characteristics of different TLS versions. The endpoint for this API SHOULD require some form of authentication to access this endpoint, such as Client Authentication as described in [RFC6749] or a separate OAuth access token. The methods of managing and validating these authentication credentials are out of scope of this specification.
The resource server MAY register for protection a single resource that, from its perspective, has multiple parts, or has dynamic elements such as the capacity for querying or filtering, or otherwise has internal complexity. Note: The resource server alone is responsible for maintaining the necessary mappings between any such complexity (which might result, for example, in different requests coming from the client) and a single resource identifier known to the authorization server.
Note: When a client attempts access to a presumptively protected resource without an access token, as occurs in [UMA], the resource server needs to derive the authorization server and resource identifier associated with that resource from some other aspect of the client's request. This effectively means that the resource server’s API needs to be structured in such a way that the client's request without an access token uniquely identifies the resource. In practice, this information likely needs to be passed through the URI, headers, or body of the request.
A resource description is a JSON document that describes the characteristics of a resource sufficiently for an authorization server to protect it. A resource description has the following properties:
The resource server MAY encode human-readable strings using the pattern described in Section 2.2 of [RFC7591] for representing multiple languages and scripts, where language tags are added delimited by a "#" character. It is OPTIONAL for the authorization server to make use of this pattern, if present in registered resources, for run-time dynamic string display effects.
For example, this description characterizes a resource (a photo album) that can potentially be viewed or printed; the scope URI points to a scope description as defined in Section 2.1.1:
{ "name":"Photo Album", "icon_uri":"http://www.example.com/icons/flower.png", "scopes":[ "view", "http://photoz.example.com/dev/scopes/print" ], "type":"http://www.example.com/rsrcs/photoalbum" }
See Section 2.2 for how the resource server registers resource descriptions with the authorization server in order to put resources under protection. See Section 7 for a long-form example of resource descriptions used in resource registration.
A scope description is a JSON document that describes the characteristics of a scope sufficiently for an authorization server to protect the resource with this scope. A scope description has the following properties:
The resource server MAY encode human-readable strings using the pattern described in Section 2.2 of [RFC7591] for representing multiple languages and scripts, where language tags are added delimited by a "#" character. It is OPTIONAL for the authorization server to make use of this pattern, if present in registered scopes, for run-time dynamic string display effects.
For example, this scope description characterizes a scope that involves viewing (vs., say, creating or editing in some fashion):
{ "name":"View", "icon_uri":"http://www.example.com/icons/reading-glasses" }
See Section 7 for a long-form example of scope descriptions used in resource registration.
The resource server uses a RESTful API at the authorization server's resource registration endpoint to create, read, update, and delete resource descriptions, along with retrieving lists of such descriptions.
Note carefully the similar but distinct senses in which the word "resource" is used in this section. The resource descriptions are themselves managed as web resources at the authorization server through this API. The initial registration process results in a unique identifier for the web resource that the resource server can later use for managing its description over time and for mapping .
The authorization server MUST present an API for registering resource descriptions as a set of URIs whose first set of path components is the authorization server's resource registration endpoint.
The authorization server is REQUIRED to support the following five registration options; any other operations are undefined by this specification. Here, rreguri stands for the resource registration endpoint and _id stands for the authorization server-assigned identifier for the web resource corresponding to the resource at the time it was created, included within the URL returned in the Location header. Each operation is defined in its own section below.
Within the JSON body of a successful response, the authorization server includes common properties, possibly in addition to method-specific properties, as follows:
If the request to the resource registration endpoint is incorrect, then the authorization server instead responds with an error message by including one of the following error codes with the response (see Section 3):
Adds a new resource description to the authorization server using the POST method. If the request is successful, the resource is thereby registered and the authorization server MUST respond with a status message that includes an _id property.
Form of a create request, with an access token in the header:
POST /rs/ HTTP/1.1 Content-Type: application/json Authorization: Bearer MHg3OUZEQkZBMjcx ... { "name":"Tweedl Social Service", "icon_uri":"http://www.example.com/icons/sharesocial.png", "scopes":[ "read-public", "post-updates", "read-private", "http://www.example.com/scopes/all" ], "type":"http://www.example.com/rsrcs/socialstream/140-compatible" }
Form of a successful response:
HTTP/1.1 201 Created Content-Type: application/json Location: /rs/KX3A-39WE ... { "_id":"KX3A-39WE", "user_access_policy_uri":"http://as.example.com/rs/222/resource/KX3A-39WE/policy" }
Reads a previously registered resource description using the GET method. If the request is successful, the authorization server MUST respond with a status message that includes a body containing the referenced resource description, along with an _id property.
Form of a read request, with an access token in the header:
GET /rs/KX3A-39WE HTTP/1.1 Authorization: Bearer MHg3OUZEQkZBMjcx ...
Form of a successful response:
HTTP/1.1 200 OK Content-Type: application/json ... { "_id":"KX3A-39WE", "name":"Tweedl Social Service", "icon_uri":"http://www.example.com/icons/sharesocial.png", "scopes":[ "read-public", "post-updates", "read-private", "http://www.example.com/scopes/all" ], "type":"http://www.example.com/rsrcs/socialstream/140-compatible" }
If the referenced resource does not exist, the authorization server MUST produce an error response with an error property value of not_found, as defined in Section 2.2.
Updates a previously registered resource description, by means of a complete replacement of the previous resource description, using the PUT method. If the request is successful, the authorization server MUST respond with a status message that includes an _id property.
Form of an update request, with an access token in the header:
PUT /rs/9UQU-DUWW HTTP/1.1 Content-Type: application/json Authorization: Bearer 204c69636b6c69 ... { "name":"Photo Album", "icon_uri":"http://www.example.com/icons/sky.png", "scopes":[ "http://photoz.example.com/dev/scopes/view", "public-read" ], "type":"http://www.example.com/rsrcs/photoalbum" }
Form of a successful response:
HTTP/1.1 200 OK ... { "_id":"9UQU-DUWW" }
Deletes a previously registered resource description using the DELETE method. If the request is successful, the resource is thereby deregistered.
Form of a delete request, with an access token in the header:
DELETE /rs/9UQU-DUWW Authorization: Bearer 204c69636b6c69 ...
Form of a successful response:
HTTP/1.1 204 No content ...
If the referenced resource does not exist, the authorization server MUST produce an error response with an error property value of not_found, as defined in Section 2.2.
Lists all previously registered resource identifiers for this resource owner using the GET method. The authorization server MUST return the list in the form of a JSON array of {_id} string values.
The resource server uses this method as a first step in checking whether its understanding of protected resources is in full synchronization with the authorization server's understanding.
Form of a list request, with an access token in the header:
GET /rs/ HTTP/1.1 Authorization: Bearer 204c69636b6c69 ...
Form of a successful response:
HTTP/1.1 200 OK ... [ "KX3A-39WE", "9UQU-DUWW" ]
When a resource server attempts to access the resource registration endpoint at the authorization server, if the request is successfully authenticated, but is invalid for another reason, the authorization server produces an error response by adding the following properties to the entity body of the HTTP response:
This specification largely relies on the base API security method, such as OAuth, for API security and shares its security and vulnerability considerations.
Some form of trust relationship between the authorization server and resource server is presumed. However, where this pairwise trust relationship is weak or loosely coupled, for example, if dynamic client registration is supported for resource servers as OAuth clients of the resource registration API, the authorization server must be extremely careful with any information supplied during resource registration that may be displayed to a resource owner in a user interface or be used to drive authorization server-based workflows.
For example, a rogue resource server could register a resource or scope with a reference to a drive-by download in icons returned by the icon_uri, enticing the resource owner to click on the icon during the policy setting process. The authorization server SHOULD check to see if all URIs defined in the icon_uri resolve to valid web pages. Since these are URI values that are intended to be displayed to the resource owner in a policy-setting interface, the authorization server SHOULD protect the resource owner from malicious content hosted at the URIs where possible.
The authorization server SHOULD also sanitize any display input sourced from resource description documents and scope description documents to mitigate cross-site scripting risks. One approach is to use existing libraries that clean HTML and other types of text fragments.
Additionally, a rogue resource server could supply misleading names for a resource or scope, or mislabel the type of a resource, leading a resource owner to set policy incorrectly.
One approach to mitigating the threat of bad URIs is that, before presenting clickable icons, the authorization server could download the content hosted at the linked URIs, check the content against a malware scanner and blacklist filter, determine whether or not there is mixed secure and non-secure content at the URL, and other possible server-side mitigations. Note that the content in these URIs can change at any time and the authorization server cannot provide complete confidence in the safety of the URIs, but these practices could help. To further mitigate this kind of threat, the authorization server can also warn the user that the links have been provided by a third party, should be treated with caution, and are not hosted by the authorization server itself. For instance, instead of providing the links directly in an HTML anchor, the authorization server can direct the user to an interstitial warning page before allowing the user to continue to the target URI.
An alternative approach may be available in deployment ecosystems where trust relationships with resource servers may be weak but APIs, resource semantics, and scopes have been standardized. A resource server could potentially increase the likelihood of an authorization server trusting the URIs it registers by using well-known and third-party-standardized URIs. This may benefit resource type values as well, if these are represented as URIs.
In many ways, the resource server depends more heavily on elements of the pairwise trust relationship than does the authorization server. Since the resource server needs to outsource a variety of resource protection-related processes to the authorization server, a rogue or impersonated authorization server would present great risk. Using OAuth with its attendant channel security requirements for API authentication would mitigate the risk of impersonation.
A small example of the risk posed by a rogue authorization server is the user_access_policy_uri property, which is the one case of a URI passed from authorization server to resource server rather than the reverse. The resource server, in taking advantage of this URI, could redirect a resource owner to a third-party web page infected with malware or similar. To mitigate this specific risk, the resource server could check that the URI is fully qualified and matches the host and scheme of the authorization server.
The communication between the authorization server and resource server may expose personally identifiable information of a resource owner. The context in which this API is used SHOULD account for its own unique privacy considerations.
This document makes no request of IANA.
The following non-normative example illustrates the intent and usage of resource descriptions and scope descriptions as part of resource registration in the context of [UMA].
This example contains some steps that are exclusively in the realm of user experience rather than web protocol, to achieve realistic illustration. These steps are labeled "user experience only". Some other steps are exclusively internal to the operation of the entity being discussed. These are labeled "internal only".
This example also does not contain any information regarding the mechanism that is used to authenticate the resource server at the authorization server, and mechanisms such as OAuth can be used for this purpose.
A resource owner, Alice Adams, has just uploaded a photo of her new puppy to a resource server, Photoz.example.com, and wants to ensure that this specific photo is not publicly accessible.
Alice has already introduced this resource server to her authorization server, CopMonkey.example.com. However, Alice has not previously instructed Photoz to use CopMonkey to protect any photos of hers.
CopMonkey has a "default-deny" setup, so until such time as Alice maps some other more permissive policies to any resources registered by Photoz, the policy is not to share them. Policies she may eventually map to particular photos or albums might be "Share only with husband@email.example.net" or "Share only with people in my 'family' group".
Photoz has a publicly documented application-specific API that offers two dozen different methods that apply to single photos, such as addTags and getSizes, but rolls them up into two photo-related scopes of access: "view" (consisting of various read-only operations) and "print" (consisting of various printing operations). It defines two scope descriptions that represent these scopes, which it is able to reuse for all of its users (not just Alice), and ensures that these scope description documents are available through HTTP GET requests that may be made by authorization servers.
Photoz constructs scope description documents for the scopes in order to provide data that will help them be displayed in user interfaces. (This means that any scope strings it supplies in resource registration descriptions will need to be URIs referring to these documents. The alternative would have been simple scope strings without the additional user interface data.)
The "name" property values in the scope descriptions are intended to be seen by Alice when she maps authorization constraints to specific resources and scopes while visiting CopMonkey, such that Alice would see the strings "View Photo and Related Info" and "Print Photo", likely accompanied by the referenced icons, in the CopMonkey interface. (Other users of Photoz might similarly see the same labels at CopMonkey or whatever other authorization server they use. Photoz could distinguish natural-language labels per user if it wishes, by pointing to scopes with differently translated names.)
Example of the viewing-related scope description document available at http://photoz.example.com/dev/scopes/view:
{ "name":"View Photo and Related Info", "icon_uri":"http://www.example.com/icons/reading-glasses.png" }
Example of the scope description document available at http://photoz.example.com/dev/scopes/print:
{ "name":"Print Photo", "icon_uri":"http://www.example.com/icons/printer.png" }
While visiting Photoz, Alice selects a link or button that instructs the site to "Protect" or "Share" this single photo (user experience only; Photoz could have made this a default or preference setting).
As a result, Photoz defines for itself a resource that represents this photo (internal only; Photoz is the only application that knows how to map a particular photo to a particular resource). Photoz also prepares the following resource description, which is specific to Alice and her photo. The "name" property value is intended to be seen by Alice in mapping authorization policies to specific resources and scopes when she visits CopMonkey. Alice would see the string "Steve the puppy!", likely accompanied by the referenced icon, in the CopMonkey interface. The possible scopes of access on this resource are indicated with URI references to the scope descriptions, as shown just above.
{ "name":"Steve the puppy!", "icon_uri":"http://www.example.com/icons/flower.png", "scopes":[ "http://photoz.example.com/dev/scopes/view", "http://photoz.example.com/dev/scopes/print" ] }
Photoz uses the Create method of CopMonkey's standard OAuth resource registration API, presenting its Alice-specific access token to use the API to register and assign an identifier to the resource description.
POST /rs/ HTTP/1.1 Content-Type: application/json ... { "name":"Steve the puppy!", "icon_uri":"http://www.example.com/icons/flower.png", "scopes":[ "http://photoz.example.com/dev/scopes/view", "http://photoz.example.com/dev/scopes/print" ] }
If the registration attempt succeeds, CopMonkey responds in the following fashion.
HTTP/1.1 201 Created Content-Type: application/json ... { "_id":"112210f47de98100", "user_access_policy_uri":"http://as.example.com/rs/222/resource/112210f47de98100/policy" }
At the time Alice indicates she would like this photo protected, Photoz can choose to redirect Alice to CopMonkey for further policy setting, access auditing, and other authorization server-related tasks (user experience only).
Once it has successfully registered this description, Photoz is responsible for outsourcing protection to CopMonkey for access attempts made to this photo.
Over time, as Alice uploads other photos and creates and organizes photo albums, Photoz can use additional methods of the resource registration API to ensure that CopMonkey's understanding of Alice's protected resources matches its own.
For example, if Photoz suspects that somehow its understanding of the resource has gotten out of sync with CopMonkey's, it can ask to read the resource description as follows.
GET /rs/112210f47de98100 HTTP/1.1 Host: as.example.com ...
CopMonkey responds with the full content of the resource description, including its _id, as follows:
Example of an HTTP response to a "read resource description" request, containing a resource description from the authorization server:
HTTP/1.1 200 OK Content-Type: application/json ... { "_id":"112210f47de98100", "name":"Steve the puppy!", "icon_uri":"http://www.example.com/icons/flower.png", "scopes":[ "http://photoz.example.com/dev/scopes/view", "http://photoz.example.com/dev/scopes/print" ] }
If for some reason Photoz and CopMonkey have gotten dramatically out of sync, Photoz can ask for the list of resource identifiers CopMonkey currently knows about:
GET /rs/ HTTP/1.1 Host: as.example.com ...
CopMonkey's response might look as follows:
HTTP/1.1 200 OK ... [ "112210f47de98100", "34234df47eL95300" ]
If Alice later changes the photo's title (user experience only) on Photoz from "Steve the puppy!" to "Steve on October 14, 2011", Photoz would use the Update method to ensure that Alice's experience of policy-setting at CopMonkey remains consistent with what she sees at Photoz. Following is an example of this request. Note that the entire updated resource description has to be included in the PUT request.
PUT /rs/112210f47de98100 HTTP/1.1 Content-Type: application/json Host: as.example.com ... { "name":"Steve on October 14, 2011", "icon_uri":"http://www.example.com/icons/flower.png", "scopes":[ "http://photoz.example.com/dev/scopes/view", "http://photoz.example.com/dev/scopes/print" ] }
CopMonkey would respond as follows.
HTTP/1.1 201 Created Content-Type: application/json ... { "_id":"112210f47de98100" }
There are other reasons Photoz might want to update resource descriptions, having nothing to do with Alice's actions or wishes. For example, it might extend its API to include new features such as photo resizing, and want to add new scopes to all of Alice's and other users' resource descriptions.
if Alice later decides to entirely remove sharing protection (user experience only) on this photo while visiting Photoz, ensuring that the public can get access without any protection, Photoz is responsible for deleting the relevant resource registration, as follows:
DELETE /rs/112210f47de98100 HTTP/1.1 Host: as.example.com ...
CopMonkey would respond as follows.
HTTP/1.1 204 No content ...
The following people made significant text contributions to the specification:
Additional contributors to this specification include the Kantara UMA Work Group participants, a list of whom can be found at [UMAnitarians].
[BCP195] | Sheffer, Y., “Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)”, May 2015, <https://tools.ietf.org/html/bcp195>. |
[RFC2119] | Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>. |
[RFC6749] | Hardt, D., Ed., “The OAuth 2.0 Authorization Framework”, RFC 6749, DOI 10.17487/RFC6749, October 2012, <http://www.rfc-editor.org/info/rfc6749>. |
[RFC7159] | Bray, T., Ed., “The JavaScript Object Notation (JSON) Data Interchange Format”, RFC 7159, DOI 10.17487/RFC7159, March 2014, <http://www.rfc-editor.org/info/rfc7159>. |
[RFC7591] | Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and P. Hunt, “OAuth 2.0 Dynamic Client Registration Protocol”, RFC 7591, DOI 10.17487/RFC7591, July 2015, <http://www.rfc-editor.org/info/rfc7591>. |
[OpenIDConnect] | Sakimura, N., “OpenID Connect Core 1.0 incorporating errata set 1”, November 2014, <http://openid.net/specs/openid-connect-core-1_0.html>. |
[UMA] | Maler, E., “User-Managed Access (UMA) Profile of OAuth 2.0”, March 2017, <http://docs.kantarainitiative.org/uma/wg/uma-core-2.0-20.html>. |
[UMAnitarians] | Maler, E., “UMA Participant Roster”, 2017, <https://kantarainitiative.org/confluence/display/uma/Participant+Roster>. |
Eve Maler
(editor)
ForgeRock
EMail: eve.maler@forgerock.com
Maciej Machulak
Self
EMail: maciej.machulak@gmail.com
Justin Richer
Bespoke Engineering
EMail: justin@bspk.io