UDAP Client Authorization Grants using JSON Web Tokens

DRAFT 2019-05-15

UDAP implements certificate-based client authorization grants using JSON Web Tokens as an extension to the OAuth 2.0 authorization framework defined in RFC 6749, based in part on the profiles defined in RFC 7521 and RFC 7523 for assertion-based authorization. To use this extension, the Client App obtains a digitally signed Authorization Assertion (AzA), and includes this assertion in the Client App’s request to the token endpoint.

There are two general ways in which an App may obtain an Authorization Assertion:

(a)    A resource owner or other authorized party may generate and sign an Authorization Assertion and provide it to a Client App so that the app may then access certain data. For example, this could be used as an alternative to following the authorization_code grant flow when the resource owner is not available in real time to interact with an OAuth Server, but is able to sign an Authorization Assertion in advance to grant a set of scopes to an app. In that case, the assertion would be submitted instead of a conventional authorization code.

(b)   A privileged application or other requesting party may generate and sign an Authorization Assertion to communicate information that the OAuth Server requires in order to determine what data should be accessible. This includes self-signed assertions generated by the application. For example, an application may use an Authorization Assertion to communicate that the requested resources will be used for a specific purpose permitted by a data use agreement or will be made available to a certain class of users, or that the requests will be made on behalf of a particular organization or person.

This authorization protocol is based upon standard public key infrastructure tools and is independent of the protocol used to authenticate the Client App. For example, Authorization Assertions can be used with any OAuth 2.0 client authentication mechanism supported by the token endpoint, including with HTTP Basic authentication, with JWT-based authentication as in the UDAP JWT-Based Client Authentication profile, with other authentication mechanisms supported by the token endpoint, or without client authentication in the case of public clients.

Before granting an access token, the Authorization Server validates the digital signature on the AzA submitted by the Client App and evaluates the trust chain for the Assertion Signer’s X.509 certificate used to make its assertions. An access token is granted by the Authorization Server to a Client App only if the AzA is valid and the Assertion Signer’s certificate is trusted. This protocol MAY be used only in settings where the Assertion Signer is able to protect the private key used to sign AzAs, e.g. confidential clients for self-signed assertions, or digital signing systems using secure key custodians or secure hardware.

The following steps define the workflow:

1. The Client App checks that the Authorization Server supports UDAP federation by retrieving the Authorization Server’s UDAP metadata from a well-known URL.

GET https://resourceholder.example.com/.well-known/udap HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "x5c" : ["{cert1}", "{cert2}", …]
}

If the Authorization Server returns the 404 error code, then the Authorization Server does not advertise support of UDAP Client Authorization Grants protocol. The Authorization Server’s certificates may be discovered as part of this metadata request. The Client App MAY examine the certificates to determine whether the Authorization Server is part of a suitable trust community.

2. The Client App must be registered with the Authorization Server to use signed JWTs as Authorization Assertions. If the Authorization Server supports UDAP Dynamic Client Registration, the Client App MAY register with the AS using that protocol. If the AS does not support dynamic registration, it SHOULD supply another method for Client Apps to register to use this authorization grant mechanism. If the Client App intends to submit Authorization Assertions only for authorization, as in section 5.1, it should register to use the “urn:ietf:params:oauth:grant-type:jwt-bearer” grant type. If it intends to submit self-signed Authorization Assertions for both authorization and authentication, as in section 5.2, it should register to use the “client_credentials” grant type.

3. The Client App obtains or generates an Authorization Assertion (AzA) for inclusion in its request to the AS’s token endpoint. The AzA serves two purposes: it establishes the Assertion Signer’s control of a private key, and it provides the digital certificate needed to validate the signature and establish trust.

The AzA is a signed JWT containing the following claims:

   iss: unique identifying URI of the Client Token Service for the Assertion Signer
   sub: the authorized accessor for which the access token is being requested. In the case of self-signed assertions submitted by a privileged Client App, the value is equal to the client ID assigned to the Client app by the Authorization server. In other cases, this value represents an identifier for the subject recognized by the AS.
   azp: the authorized party, equal to the Client App’s identifying URI (omit for self-signed assertions submitted by a Client App)
   aud: token endpoint URI of the Authorization Server
   exp: expiration time for the authorization expressed as seconds since epoch (should be as short-lived as practical for the use cases supported)
   iat: issued at time expressed as seconds since epoch
   jti: identifier used to identify replay of this assertion
   resources: array of strings, the URIs of specific resources authorized by the Assertion Signer (optional); included when the Assertion Signer wishes to narrow access to a set of specific resources. Note that including a resource in this array does not override any access restrictions imposed by the AS based on the scopes granted, the identity of the Assertion Signer or the Client App, or other policy rules.
   scope: string, space delimited list of scopes that may be requested by the Client App (optional); included when the Assertion Signer wishes to restrict the scopes granted to the set listed. Note that including a scope in this list does not override any other restrictions the AS may impose on the scopes available to the Client App.
   extensions: JSON object, see below (optional)

The JOSE Header for the AzA contains the following key/value pairs:

   alg : "RS256"
   x5c : [cert1, cert2, …] (cert1 is required; remainder of chain is optional)
   x5u : valid URI (optional)

The x5c claim contains the Assertion Signer’s certificate chain as an array of one or more elements, each containing a base64 encoded representation of the DER encoded X.509 certificate. The leaf certificate (cert1) contains the public key corresponding to the private signing key used by the Client App to digitally sign the software statement. The AzA is signed and assembled using JWS compact serialization as per RFC 7515.

4. An Authorization Server MAY support extensions to this protocol using the extensions parameter.  The extension names and their required formats are defined by the Authorization Server and are communicated in an out-of-band manner. An extension value can be any valid JSON entity. For example, an Assertion Signer might include the following extensions parameter in the assertion intended for an AS that requires the following information to process a token request:

   "extensions": {
      "purpose_of_use" : "payment",
      "query_initiator": {"name": "john smith", "user_id": "A98765"}
   }

5. The client requests a token from the Authorization Server’s token endpoint

There are two ways the Client App can use the Authorization Assertion: the assertion can be used for authorization only in conjunction with another authentication scheme as in section 5.1, or an assertion signed by the Client App can be used for both authorization and authentication as in section 5.2.

5.1 Assertion used for Authorization only

The client indicates that an Authorization Assertion will be used by including two parameters: “grant_type” with a value of “urn:ietf:params:oauth:grant-type:jwt-bearer” and “assertion” with a value equal to the JWS compact serialization of the signed AzA constructed in step 4. An additional extension parameter “udap” is also included with a string value of “1” to signal to the AS that version 1 of this protocol is being used. If required by the AS, the Client App MUST also include suitable authentication credentials in the request.

In the following example, the Client App is submitting an assertion as an alternative to using the authorization_code grant type because the user is not available in real time to interact with the Authorization Server’s authorization endpoint for the authorization code flow. Instead, in the request to the token endpoint, the Client App submits an Authorization Assertion obtained separately from the resource owner and uses HTTP Basic authentication to authenticate itself to the Authorization Server. The resource owner first assembles the Authorization Assertion that is valid for one hour, shown here prior to Base64URL encoding and signing by the resource owner’s signing service:

{
   "alg": "RS256",
   "x5c": ["MIIGZjCCBE6gA…remainder of Base64 encoded certificate omitted for brevity…"]
}.{
   "iss": "https://as.example.com/identity-service",
   "sub": "https://as.example.com/identity/TupoJoWnXp1uBlo26A75",
   "azp": "http://appdeveloper.example.com/apps/superapp/v1",
   "aud": "https://as.example.com/token",
   "exp": 1557841184,
   "iat": 1557837584,
   "jti": "1Ly1QFX9vtc-t1m1fV9oz8estCDXQ9mLhFvuxHbZhsM",
   "scope": "read write"
}

The Client App later submits the signed AzA provided by the resource owner in a request to the Authorization Server’s token endpoint:

POST /token HTTP/1.1
Host: as.example.com
Content-type: application/x-www-form-urlencoded
Authorization: Basic bXlDbGllbnRJRDpINDl4LXN0cm9uZy1wYXNzd29yZC1CJDYz

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
  assertion=ewogICAiYWxnIjogIlJT…remainder of AzA omitted for brevity…&
  scope=read+write&
  udap=1

Note that any suitable authentication protocol supported by the Authorization Server could be used instead of HTTP basic, or, as in the case of public clients, authentication might not be required.

5.2 Assertion used for both Authorization and Authentication

In the case where the client credentials grant flow is used by a privileged Client App acting on its own behalf, a single signed JWT can be used as both an Authorization Assertion and Authentication Token (AnT). The client indicates that this single assertion will be used for both purposes by including three parameters: “grant_type” with a value of “client_credentials”, “client_assertion_type” with a value of “urn:ietf:params:oauth:client-assertion-type:jwt-bearer” and “client_assertion” with a value equal to the JWS compact serialization of the signed AzA constructed in step 4. For this special case, the value of the AzA sub claim MUST be set to the client ID issued to the Client App by the AS. An additional extension parameter “udap” is also included with a string value of “1” to signal to the AS that version 1 of this protocol is being used.

Note that this is a special case of the authentication process defined in the UDAP JWT-Based Client Authentication profile. The Authorization Assertion contains all of the required elements of the Authentication Token from that profile, plus the additional elements defined in this profile that are required for authorization.

In the following example, the client app is requesting authorization to access health information from a hospital. The Client App first assembles the Authorization Assertion that is valid for 5 minutes, including additional information that the Authorization Server requires for auditing purposes using an extension defined by the Authorization Server, shown here prior to Base64URL encoding and signing by the Client App:

{
   "alg": "RS256",
   "x5c": ["MIIEczCCA1ugA…remainder of Base64 encoded certificate omitted for brevity…"]
}.{
   "iss": "http://appdeveloper.example.com/apps/superapp/v1",
   "sub": "myClientID",
   "aud": "https://hospital.example.com/token",
   "exp": 1557843252,
   "iat": 1557843852,
   "jti": "Q1E6g2PY91nmj5bSJJ-CZQ",
   "extensions": {
      "originating_organization": "2.16.840.1.113883.19.347473",
      "originating_individual": "2.16.840.1.113883.19.347473.3.284856",
      "purpose_of_use": "treatment"
   }
}

In the example, the hospital’s Authorization Server requires that the client app use the extensions parameter to identify the individual originating the request and the organization represented, using OIDs from a specific arc, and that the app also identify the purpose of the data request. To request an access token, the Client App submits the signed combined AzA/AnT in a request to the Authorization Server’s token endpoint:

POST /token HTTP/1.1
Host: hospital.example.com
Content-type: application/x-www-form-urlencoded

grant_type=client_credentials&
  client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
  client_assertion=ewogICAiYWxnIjogIlJT…remainder of AzA/AnT omitted for brevity…&
  scope=system%2FPatient.read
  udap=1

In the example, the hospital’s Authorization Server also follows the authentication validation procedure from UDAP JWT-Based Client Authentication to authenticate the client app.

6. Authorization Server validates request

This section describes the procedure used by the AS to validate a token endpoint request that contains an Authorization Assertion.

6.1 The AS validates the digital signature on the AzA using the public key extracted from cert1 in the x5c parameter of the JOSE header. If the signature cannot be validated, the request is denied.

6.2 The AS attempts to construct a valid certificate chain from the Assertion Signer’s certificate (cert1) to an anchor certificate trusted by the AS using conventional X.509 chain building techniques and path validation, including certificate validity and revocation status checking. The Assertion Signer SHOULD submit a complete certificate chain in its request. The AS MAY use additional certificates not included by the Assertion Signer to construct a chain (e.g. from its own certificate cache or discovered via the X.509 AIA mechanism). If a trusted chain cannot be built and validated by the AS, the request is denied.

6.3 The AS validates the sub, azp, aud, exp, iat, and jti values within the AzA. The sub value MUST be an identifier for an entity (e.g. an end user or organization) that is recognized by the AS and is permitted by the AS to authorize access using an AzA. If the azp claim is present, then its value MUST match the client ID of the Client App as recognized by the AS. The aud value MUST contain the AS’s base URL, and the AzA MUST be unexpired. A maximum AzA lifetime of 60 minutes is RECOMMENDED. The AS MAY deny a request if the same AzA (as determined by the jti value) has been used in a previous registration request.

6.4 If the extensions parameter is included, then the AS processes the extensions. The AS MAY ignore any extension names that it does not recognize. Alternatively, the AS MAY deny the request and return the error code “invalid_grant” as per section 7.2 if an unrecognized name is encountered. The “invalid_grant” error code SHOULD be used if any of the extension names required by the AS are not included in the AzA.

6.5 If the scope parameter is included, then the AS MUST disallow any scopes requested by the Client App that are not listed in the Authorization Assertion. If a disallowed scope was requested, the AS MAY continue processing of the other requested scopes or it MAY return the error code “invalid_scope” as per section 5.2 of RFC 6749. If the assertion lists an invalid or unknown scope, the AS MAY deny the request and return the error code “invalid_grant” as per section 7.2. Note that for assertions signed by the Client App, the Client App MUST still request scopes in the usual manner required by the OAuth flow in use even if it includes a list of scopes in this assertion.

6.6 The AS validates any other parameters in the request as per the requirements of the authentication mechanism in use, if any. If a parameter is invalid or a required parameter is missing, or if authentication of the Client App is required but is unsuccessful, then the request is denied.

6.7 Support for the resources parameter by an AS is optional. If the assertion includes this parameter but the AS does not support this feature, the AS MUST deny the request and return the error code “invalid_request” as per section 7.2. Otherwise, if the resources parameter is included in the assertion, the AS MUST further narrow the scope of any access token granted to disallow access to resources that are not explicitly included in the list of resource URIs. Each resource URI listed MUST be treated as a fully specified URI, i.e. a listed resource URI does not allow access to resources that are located at subpaths of the listed URI or that contain additional query parameters.

7. Authorization responds to request

7.1 If the request is granted, the Authorization Server returns a token response as per Section 5.1 of RFC 6749. For example:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "access_token": "example_access_token_issued_by_AS",
   "token_type": "Bearer",
   "expires_in": 3600
}

The AS MAY also return a refresh_token in its response. The expiration time of the access token SHOULD NOT significantly exceed the expiration time of the AzA.

7.2 If the request is denied, the AS returns an error as per Section 5.2 of RFC 6749. Denials related to trust validation or invalid AzA signatures SHOULD use the “invalid_grant” code. Section 6 lists required or recommended error codes for other error conditions. The AS SHOULD also include a suitable error_description parameter in its response. For example:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
   "error": "invalid_grant",
   "error_description": "The submitted authorization assertion has expired."
}

8 Authors

Luis C. Maas III, EMR Direct
Julie Maas, EMR Direct

9 Notices

Copyright ©2016-2019 UDAP.org and the persons identified as the document authors. All rights reserved.

UDAP.org grants to any interested party a non-exclusive, royalty-free, worldwide right and license to reproduce, publish, distribute and display this Draft Specification, in full and without modification, solely for the purpose of implementing the technology described in this Draft Specification, provided that attribution is made to UDAP.org as the source of the material and that such attribution does not indicate an endorsement by UDAP.org.

All Draft Specifications and Final Specifications, and the information contained therein, are provided on an “AS IS” basis and the authors, the organizations they represent, and UDAP.org make no (and hereby expressly disclaim any) warranties, express, implied, or otherwise, including but not limited to any warranty that the use of the information therein will not infringe any rights or any implied warranties of merchantability or fitness for a particular purpose, and the entire risk as to implementing this specification is assumed by the implementer. Additionally, UDAP.org takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available, nor does it represent that it has made any independent effort to identify any such rights.