# General Requirements - Security for Scalable Registration, Authentication, and Authorization v3.0.0-ballot

* [**Table of Contents**](toc.md)
* **General Requirements**

## General Requirements

| |
| :--- |
| *Page standards status:*[Trial-use](http://hl7.org/fhir/R4/versions.html#std-process) |

This section contains general requirements applicable to multiple authorization and authentication workflows.

### JSON Web Token (JWT) Requirements

Both the producers and consumers of JWTs specified in this guide **SHALL** conform to the requirements of [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515) and the additional requirements below.

#### General requirements and serialization

All JSON Web Tokens (JWTs) defined in this guide:

1. **SHALL**conform to the mandatory requirements of[RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519).
1. **SHALL**be JSON Web Signatures as defined in[RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515).
1. **SHALL**be serialized using JWS Compact Serialization as per[Section 7.1](https://datatracker.ietf.org/doc/html/rfc7515#section-7.1)of RFC 7515.

#### Signature algorithm identifiers

Signature algorithm identifiers used in this guide are defined in [Section 3.1](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1) of RFC 7518.

| | |
| :--- | :--- |
| `RS256` | Implementers**SHALL**support this algorithm. |
| `ES256` | Implementers**SHOULD**support this algorithm. |
| `RS384` | Implementers**MAY**support this algorithm. |
| `ES384` | Implementers**MAY**support this algorithm. |

While this guide mandates a baseline of support, clients and servers **MAY** support and use additional signature algorithms that meet the security requirements of the use case.

#### JWT headers

All JWTs defined in this guide **SHALL** contain a Javascript Object Signing and Encryption (JOSE) header as defined in [Section 4](https://datatracker.ietf.org/doc/html/rfc7515#section-4) of RFC 7515 that conforms to the following requirements:

| | | |
| :--- | :--- | :--- |
| `alg` | required | A string identifying the signature algorithm used to sign the JWT. For example:`"RS256"` |
| `x5c` | required | An array of one or more strings containing the X.509 certificate or certificate chain, where the leaf certificate corresponds to the key used to digitally sign the JWT. Each string in the array is the base64-encoded DER representation of the corresponding certificate, with the leaf certificate appearing as the first (or only) element of the array.See[Section 4.1.6 of RFC 7515](https://tools.ietf.org/html/rfc7515#section-4.1.6). |

#### JWT Claims

All JWTs defined in this guide contain the `iss`, `exp`, and `jti` claims. The value of the `jti` claim is a nonce string value that uniquely identifies a JWT until the expiration of that JWT, i.e. until the time specified in the `exp` claim of that JWT has passed. Thus, the issuer of a JWT **SHALL NOT** reuse the same `jti` value in a new JWT with the same `iss` value prior to the expiration of the previous JWT. Implementers who track `jti` values to detect the replay of received JWTs **SHALL** allow a `jti` value to be reused after the expiration of any other previously received JWTs containing the same `iss` and `jti` values.

Additional JWT Claim requirements are defined elsewhere in this guide.

#### Normalization of URI values in JWTs

This guide does not require the canonicalization of URIs included in JWTs before making string comparisons. Per Section 2 of [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519), URI values in JWTs are compared as case-sensitive strings with no transformations or canonicalizations applied. The JWT producer **SHOULD** include URI values that are normalized to facilitate successful string matching by the JWT consumer. The JWT consumer is **NOT REQUIRED** to perform any normalization of URI values prior to making comparisons. For example, a JWT producer cannot assume that a JWT consumer will consider `"https://FHIR.example.com:443"` and `"https://fhir.example.com/"` to be equivalent strings when evaluating a JWT.

Note: To ensure interoperability, a URI included as the `iss` value of a JWT should exactly match a URI included in the Subject Alternative Name extension of the JWT producer’s corresponding certificate, including, for example, the case used for the host name and the presence or absence of a port number or trailing slash. Similarly, clients that include a URI provided by a server in its server metadata as the `aud` value of a JWT subsequently submitted to that server should include the URI exactly as it was originally provided by that server.

#### JWT validation

Several workflows described in this guide require validation of JWTs by the JWT consumer. This includes the requirement that the JWT consumer validate that it trusts the corresponding JWT’s producer’s X.509 certificate by constructing a valid certificate chain from the JWT producer’s certificate to an anchor trusted by the JWT consumer, and by verifying that the certificates in the chain have not expired or been revoked. The full validation requirements for each workflow can be found in the UDAP profile sections referenced in Sections [2.3](discovery.md#required-udap-metadata), [3.2.3](registration.md#request-body), [4.2.3](consumer.md#server-processing-of-token-requests), and [5.2.3](b2b.md#server-processing-of-token-requests).

### Authorization code flow

The constraints in the following subsections apply to all workflows utilizing the authorization code flow. Authorization requests submitted by client applications **SHALL** include the following parameters:

| | | |
| :--- | :--- | :--- |
| `response_type` | required | Fixed value:`code` |
| `client_id` | required | The client identifier issued to the client application at registration. |
| `redirect_uri` | conditional | The client application's redirection URI for this session,**REQUIRED**when the client application registered more than one redirection URI. The value**SHALL**match one of the redirection URIs registered by the client. |
| `scope` | required | Space-delimited list of requested scopes of access. |
| `state` | required | An opaque value used by the client to maintain state between the request and callback, as discused further in[Section 7.2.1](#the-state-parameter) |
| `code_challenge` | required | PKCE code challenge, as discussed further in[Section 7.2.2](#proof-key-for-code-exchange-pkce) |
| `code_challenge_method` | required | Fixed value:`S256` |

#### The state parameter

A Client application **SHALL** include the `state` parameter in its authorization request. An Authorization Server **SHALL** return an error code of `invalid_request` as per Section 4.1.2.1 of RFC 6749 if a client application does not include a `state` value in its authorization request.

Servers **SHALL** include the `state` parameter and corresponding value provided by the client application in the authorization response as per RFC 6749. The client application **SHALL NOT** proceed if the `state` parameter is not included in the authorization response or its value does not match the value provided by the client application in the corresponding authorization request.

#### Proof Key for Code Exchange (PKCE)

Client applications and Authorization Servers **SHALL** utilize Proof Key for Code Exchange (PKCE) with `code_challenge_method` of `S256` as defined in RFC 7636. An Authorization Server **SHOULD** return an error as per Section 4.4.1 of RFC 7636 if a client application does not include a `code_challenge` is its authorization request.

The Authorization Server **SHALL** return an error in response to a token request as per Section 4.6 of RFC 7636 if the client included a `code_challenge` in its authorization request but did not include the correct `code_verfier` value in the corresponding token request.

### Scope negotiation

A wildcard scope is a scope that can be alternatively represented as a set of non-wildcard scopes. An example of a wildcard scope is the SMART App Launch v1.0.0 scope `patient/Observation.*` which can expanded to the set of two non-wildcard scopes: `patient/Observation.read` and `patient/Observation.write`. Granting the wildcard scope to a client application is equivalent to granting the corresponding expanded set of non-wildcard scopes.

The constraints enumerated below apply for scope negotiation between client applications and servers. Unless otherwise specified, these constraints apply for both registration requests and access token requests made by client applications, and the corresponding responses returned by servers.

1. Client applications and servers**MAY**support wildcard scopes.
1. The`scopes_supported`metadata**SHALL**be present in the .well-known/udap object and**SHALL**list all scopes supported by the server including all supported wildcard scopes.
1. A client application**MAY**request a wildcard scope only if wildcards are specified in the server’s`scopes_supported`metadata list.
1. If a client application requests a wildcard scope and the server supports wildcards, then the server**SHOULD**return either the wildcard scope or an expanded set of scopes that the client has been granted in its response.
1. If a client application requests a wildcard scope and the server does not support wildcard scopes, then the server**SHOULD**respond with an error of “invalid_client_metadata” for registration requests or an error of “invalid_scope” for token requests.
1. If a server supports scopes defined in other specifications or implementaton guides for a workflow defined in this guide, then the server**SHOULD**include the corresponding scopes in its`scopes_supported`metadata.
1. In registration requests and token requests, an authorization server**MAY**grant all scopes requested by the client or a subset thereof. It**MAY**also grant additional scopes that were not in the set of scopes requested by the client application. For example, the set of scopes granted or not granted by the server could be based on technical or policy guidelines at the responding organization, or, for token requests, based on the application having registered with the server for a different set of scopes.
1. A server**SHALL**include the`scope`parameter in a token response if the set of scopes granted by the server to the client application is not identical to the set of scopes requested by the client application, or if the client application does not include a set of requested scopes in its request.
1. A server**SHOULD**respond with an error of “invalid_scope” for token requests only if a wildcard scope is requested and not supported, or if none of the requested scopes are supported.
1. A server**SHOULD**respond with an error of “invalid_client_metadata” for registration requests if a wildcard scope is requested and not supported, if none of the requested scopes are supported, and/or if the server will not grant any of the requested scopes to the client based on technical or policy guidelines at the responding organization.
1. Client applications**SHOULD**be able to handle a response granting a different set of scopes than the scopes requested. This may be a superset, subset, or entirly different set, as described in items 4 and 6 above.

### Certifications for client applications

As discussed in [UDAP Certifications and Endorsements for Client Applications](https://www.udap.org/udap-certifications-and-endorsements-stu1.html), certifications can be used by client applications or third parties to declare additional information about a client application at the time of registration.

The table in Section 7.4.1 provides a template for UDAP Certification definitions. A trust community **MAY** publish one or more Certification definitions using this template. A Certification definition specifies the values to be used for the `certification_name` and `certification_uris` keys and the allowed `grant_types`. The trust community determines whether or not the optional `scopes` and `extensions` keys will be included in their Certification definition, any restrictions on their allowed values, and whether these keys will be optional, required, or conditionally included when generating a certification. If the `extensions` keys are used, the Certification definition specifies the additional extensions keys to be included in the `extensions` object, as discussed in section 7.4.2.

The trust community also determines who will sign the certification, e.g. the app operator or another party. For example, a certification self-signed by a client app operator can be used to declare the intended use of the application within a trust community, while certifications signed by another party, such as the trust community administrator or an independent accreditor, can be used to assist servers in determining what a client application is authorized to do within a trust community. Note that a trust community could use such a certification to communicate the exchange purposes for which a particular client application operator has been approved.

Using a Certification definition provided by the trust community, a client application or third party **MAY** generate a certification by constructing a signed JWT conforming to requirements of the certification definition and this section. The certification **SHALL** contain the required header elements specified in [Section 7.1.3](general.md#jwt-headers) of this guide and the JWT claims listed in the certification definition. The certification **SHALL** be signed by the client application operator or by a third party, as specified in the certification definition, using the signature algorithm identified in the `alg` header of the certification and with the private key that corresponds to the public key listed in the signer’s X.509 certificate identified in the `x5c` header of the certification.

Recognized Certification JWT claims and server processing rules for Certifications submitted by a client application are detailed in [UDAP Certifications and Endorsements for Client Applications](https://www.udap.org/udap-certifications-and-endorsements-stu1.html).

#### Certification template

| | | |
| :--- | :--- | :--- |
| `iss` | required | Issuer of the JWT -- unique identifying URI of the signing entity. This**SHALL**match the value of a uniformResourceIdentifier entry in the Subject Alternative Name extension of the signer's certificate included in the`x5c`JWT header and**SHALL**uniquely identify a single signing entity over time. |
| `sub` | required | Subject of the JWT -- unique identifying client URI. This**SHALL**match the value of a uniformResourceIdentifier entry in the Subject Alternative Name extension of the client's certificate and**SHALL**uniquely identify a single client app operator and applications over time. For a self-signed certification, this is same as`iss`. |
| `aud` | optional | The "registration URL" of the intended Authorization server(s), i.e. the same URL to which the registration request will be posted. If absent, this certification is intended for all Authorization Servers. The value can be a single string or array of strings. |
| `exp` | required | Expiration time integer for this software statement, expressed in seconds since the "Epoch" (1970-01-01T00:00:00Z UTC). The`exp`time**SHALL**be no more than 3 years after the value of the`iat`claim. |
| `iat` | required | Issued time integer for this software statement, expressed in seconds since the "Epoch" |
| `jti` | required | A nonce string value that uniquely identifies this software statement. See[Section 7.1.4](general.md#jwt-claims)for additional requirements regarding reuse of values. |
| `certification_name` | required | string with fixed value defined by the trust community, e.g. "Example HL7 Client App Certification" |
| `certification_uris` | required | array of one or more string with fixed values defined by the trust community, e.g.["http://community.example.com/certifications/example-certifications"]. |
| `grant_types` | required | Array of strings, each representing a requested grant type, from the following list:`"authorization_code"`,`"refresh_token"`,`"client_credentials"`. The array**SHALL**include either`"authorization_code"`or`"client_credentials"`, but not both. The value`"refresh_token"`**SHALL NOT**be present in the array unless`"authorization_code"`is also present. |
| `response_types` | conditional | Array of strings. If`grant_types`contains`"authorization_code"`, then this element**SHALL**have a fixed value of`["code"]`, and**SHALL**be omitted otherwise |
| `scope` | optional | String containing a space delimited list of scopes that may be requested by the client application in subsequent requests. The Authorization Server**MAY**consider this list when deciding the scopes that it will allow the application to subsequently request. Note for client apps that also support the SMART App Launch framework: certifications for apps requesting the`"client_credentials"`grant type**SHOULD**lisst system scopes; certifications for apps requesting the`"authorization_code"`grant type**SHOULD**list user or patient scopes. |
| `extensions` | optional | A JSON object containing one or more certification extension keys, as discussed in the following section. |

#### Certification extension keys example

When defining a Certification, a trust community **MAY** define one or more extension keys to be included in the `extensions` object of the Certification JWT, the JSON type of the corresponding value, and the conditions under which the key is present, including whether the use of the key is optional, required, etc. The value of each extension key **SHALL** be a JSON value or a JSON object. For example, a Certification definition could specify that the value of a key is a number, an array of strings, or a FHIR [Questionnaire](https://www.hl7.org/fhir/R4/questionnaire.html) resource, as appropriate for its intended use.

Two non-normative examples of extension keys that could be considered for inclusion in a Certification are presented in the table below:

| | |
| :--- | :--- |
| `example_exchange_purposes` | Array of strings, each containing a URI identifying an exchange purpose recognized by the trust community. |
| `example_privacy_disclosures` | A JSON object containing a set of privacy-related keys and acceptable values established by the trust community.For example:1. the key`funding`could be used to express the app's source of funding.2. the key`data_storage`could be used to identify where a patient's data is stored.3. the key`data_access_notification`could be used to indicate whether a user is notified when their data is accessed by someone else.Note: This example extension key is derived from an example Certification previously published by Carequality, which can be viewed[here](https://carequality.org/wp-content/uploads/2020/12/Carequality-Consumer-Facing-App-Certification-Profile.pdf). |

### Using this guide with the SMART App Launch framework

This guide is intended to be compatible and harmonious with client and server use of versions 1 or 2 of the HL7 SMART App Launch IG. Although the use of the SMART App Launch framework is not required to be conformant with this guide, this section provides guidance on how the UDAP and SMART App Launch frameworks can be used together successfully.

The FAST Security project team is working to identify any potential incompatibilities experienced by servers or client applications that support both this IG and the SMART App Launch IG concurrently. Implementers are requested to submit feedback regarding any other potential issues they have identified related to the concurrent use of both IGs so these may be addressed and resolved in future updates.

#### Consistent use of both guides

The question has been raised as to whether this IG can be used for client registration but not used for subsequent authentication. Though adopters of this IG sometimes colloquially refer to its entire workflow as “Dynamic Client Registration”, authentication consistent with this IG is also core to a compliant implementation and the HL7 UDAP FAST Security workgroup recommends that trust communities adopting this IG require the use of this IG for both client registration and authentication, even when SMART is also used, since omitting the UDAP workflow from the authentication step significantly reduces the security benefits to the community.

#### Key Algorithms

JWT-based authentication in version 2 of the SMART IG requires server support for either the RS384 or ES384 signature algorithms, while this IG requires server support for RS256. However, this does not present a compatibility issue because RS256 is permitted as an optional algorithm in the SMART IG, and both RS384 and ES384 are permitted as optional algorithms in this IG. Therefore, using any of these three signature algorithms would be compliant with both IGs. It is also noted that for 2048-bit and 3072-bit RSA keys, for example, RS384 does not provide additional security strength beyond RS256.

#### Public Key Distribution

This guide uses X.509 certificates included inline within JWTs to distribute public keys. The entity generating a JWT includes the corresponding certificate in the `x5c` header of every signed JWT. Therefore, no separate key discovery or retrieval mechanism is required by the party consuming the JWT. The SMART App Launch framework instead prefers that client apps publish their public keys at a publicly available URL using the JWKS format, and submit this JWKS URL during registration. A server will then dereference this URL to obtain the client’s public key. However, this does not present a compatibility issue because the inclusion of the `x5c` header is not prohibited by the SMART IG, and a client can also publish the public keys from its certificate(s) in JWKS format at a JWKS URL or provide the JWKS directly to the server if necessary for strict conformance with the SMART IG. We note that, in practice, the public key in the certificate provided by the client would allow a server to validate the JWT signature without the need to dereference any JWKS URL provided. We also note that the SMART IG makes no stipulation regarding a server registering a key with a client, e.g. for validation of signed server metadata.

#### Discovery

Both this guide and the SMART App Launch framework have requirements regarding the publishing of server metadata at well-known URLs. There is some expected overlap in the UDAP metadata elements defined in [Section 2](discovery.md) of this guide and the metadata required by the SMART IG, e.g. OAuth 2.0 authorization and token endpoints are included in both. This is not a compatibility issue as each guide specifies a different metadata endpoint. Having different metadata endpoints permits servers to return different metadata values for different workflows. For example, a server could operate a different token endpoint to handle token requests from clients conforming to this guide, or use the same endpoint for token requests conforming to both guides. We also note a server can easily identify token requests conforming to this guide by the presence of the extension parameter `udap` with a value of `1` in the request body.

#### Scopes

This guide does not restrict the scopes defined outside this guide that may be supported by a client or server. It is expected that clients that support both this guide and the FHIR resource scopes defined in the SMART App Launch framework will request SMART system-level scopes when using the `"client_credentials"` grant type and either SMART user-level or patient-specific scopes when using the `"authorization_code"` grant type.

#### Authorization Requests

Client applications that support both this guide and the SMART App Launch IG are not required to include a launch scope or launch context requirement scope in an authorization request. However, the capability for a client application to request a launch context from the server is useful in many workflows, e.g. consumer facing workflows. Since this IG does not restrict the inclusion of additional parameters in an authorization request or in the corresponding server response, clients are able initiate either the SMART standalone or EHR launch workflows to request a launch context. For example, a client could initiate the SMART standalone launch by including the `launch/patient` scope in its authorization request to a server that supports this SMART workflow.

#### Token Requests

For clients and servers that also support version 1 of the SMART App Launch IG, the requirement to authenticate using a private key in Section 4.2.1 overrides the requirement for the client to use HTTP Basic Authentication with a client_secret in [Section 7.1.3](http://hl7.org/fhir/smart-app-launch/1.0.0/index.html#step-3-app-exchanges-authorization-code-for-access-token) of the SMART App Launch IG v1.0.0. It is noted that this override is only applicable to version 1, as subsequent versions of the SMART IG no longer requires client to use Basic Authentication.

#### Token Responses

Although this guide does not currently constrain the type or format of access tokens, the SMART App Launch framework, when used together with this guide, may limit the allowed access token types (e.g. Bearer) and/or formats (e.g. JWT). Since this IG does not restrict the server from including additional parameters in the token response, servers can include other parameters specified by the SMART App Launch framework for this purpose, e.g. launch context parameters.

### Experimental workflow alternative using ‘jku’ dereferencing

Since many servers support `jku` dereferencing for certain SMART App Launch workflows, the question has been raised as to whether there may be some advantage to allowing clients and servers to re-use this `jku` mechanism for UDAP workflows, as an alternative to requiring a JWT signer to include their certificate inline in the `x5c` header of the JWT. To facilitate future discussion of this topic, this guide defines the following experimental workflow changes for testing purposes. Implementer feedback is requested to determine whether to expand or remove this option in future versions of this guide.

This sections defines an experimental JWT processing alernative to test the use of `jku` dereferencing for access token request/response workflows. Support for this variation is **OPTIONAL** for both clients and servers, and may be removed in future versions of this guide. This variation overrides the requirement in [Section 7.1.3](general.md#jwt-headers) to include an `x5c` header in a JWT. This section does not apply to registration requests or to JWTs signed by servers.

Alternative workflow:

1. Clients**MAY**omit the`x5c`header from an Authentication JWT and instead include the`jku`header containing their pre-registered JWKS URL and the`kid`header identifying a key in the corresponding JWKS key set. If the`jku`header is included, then the key entry from the JWKS set at this URL matching the`kid`value in the JWT header**SHALL**include an`x5c`parameter populated with the corresponding certificate data in the same manner that the`x5c`JWT header would have been populated if it had been included in the JWT.
1. Servers that receive a JWT in a UDAP worfklow without an`x5c`header**MAY**dereference the`jku`header, attempt to locate the`x5c`parameter from the key entry corresponding to the`kid`value in the JWT, and use the`x5c`value from the JWKS in subsequent processing in the same way as if it had been included directly in the JWT as the value of`x5c`JWT header.
1. Clients intending to utilize this workflow**SHALL**register their JWKS URL by including the`jku`parameter with the JWKS URL value in their signed software statement at the time of registration.

