Skip to main content

Authentication & Authorization

Overview

  • SMART® on FHIR® authorization framework is used to protect the Cerner’s implementation of the HL7® FHIR® Standard.
  • SMART® on FHIR® defines a profile of the OAuth 2 framework for obtaining authorization to act on behalf of users.

Registration

  • In order for your client application to utilize any protected resources, your client application must first be registered.
  • A Cerner Care account is required to register applications.
  • Obtaining a Cerner Care account is free and requires nothing but an email address.
  • If registering an application that is using the public app profile and requires access only when the user is online, your client application must first register using code Console.
  • If you are a Cerner client developing an application, please see this document about how to make your self-developed app available in your domain.
  • If registering a confidential client application (and/or access on behalf of a system), follow the directions in the Registering a System Account section.
  • Check the respective FHIR® implementation documentation to determine availability.
  • Once registered, the client identifier will be provided for use with the Cerner Authorization Server.
  • As a registered client, Cerner organizations may then ask for your client application to be enabled, which is necessary in order to gain access to their protected resources.

Registering a System Account

If an application will be a confidential client, or accessing data on behalf of a system, it will need to maintain a secret. Currently, our implementation provides management and rotation functionality for this workflow in our System Accounts application. In order to register one of these applications, you must first request a system account, and then register that as a SMART or FHIR application in our code Console.

Request a system account by following these steps:

  • Login to the Cerner Central System Accounts application:
https://cernercentral.com/system-accounts
  • If you are a Cerner client developing their own application, you may have a customized URL for Cerner Central that can be used instead. For example:
https://yourcompanynamegoeshere.cernercentral.com/system-accounts

Fill out the fields as follows:

  • Description: App Name - SMART/FHIR application - short description/purpose of the App
  • Production System: No
  • Cerner Client: No, unless you are a Cerner Client developing their own application.

If you are a client:

  • Client Name: Your organization. For example: My Health System
  • Client Number: Only fill out if you know this, it is not required.
  • Client Mnemonic: Only fill out if you know this, it is not required.
  • Millennium System: No
  • Once the account is created, take the id from that account and use it in the GUID field when you register the application as a SMART or FHIR application in the code Console.
  • Without this step, your application will not be recognized as an authorized application for FHIR.
  • Note that requests for system accounts currently undergo manual approval, and therefore it may take a few business days for the system account to be created.
  • Remember to protect the secret received via this process.
  • Don’t post this secret or email it in insecure fashion.
  • Don’t include this secret or credentials requests for the authorization server in any posts requesting help.
  • If you do compromise the secret, you can rotate the credentials using the system accounts application above.

Requesting Authorization on Behalf of a User

To access Cerner’s FHIR® services on behalf of a user, your client application must make an authorization request through a user agent on the user’s device.

This involves the following steps:

  • Discover the authorization and token endpoint URLs.
  • Construct an authorization grant request URL.
  • Invoking a browser with the authorization grant request URL.
  • Receive the OAuth callback.
  • Exchange the received grant for a token.
  • Close the browser.
  • Handle any exceptions encountered.
  • Utilizing “refresh” tokens.

Discovering Authorization URLs

  • Each instance of Cerner’s FHIR® services advertise the URL of its respective authorization server within its FHIR® conformance document.
  • The FHIR® Conformance resource can be retrieved by performing an HTTP GET against the resource located at the relative path of ./metadata from the FHIR® base URL.
  • Examples of this call can be found on the Conformance documentation for Millennium or Soarian.

Within the structure of this document, three important URLs are advertised in an extension to Conformance.rest.security, identified via the URL

http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris.

First URL

The first URL is the location of the authorization endpoint, which is further identified by the sub-extension URL “authorize”.

Second URL

The second URL of importance is the location of the authorization server’s token endpoint, which is further identified by the sub-extension URL “token”.

Third URL

  • The third URL of importance is the location of the authorization server’s user-facing authorization management workflow entry point, which is further identified by the sub-extension URL “manage”.
  • This sub-extension is advertised from user-facing instances of Cerner’s FHIR® server.

Construct the Authorization Request URL

An authorization request takes the form of an x-www-form-urlencoded query string, appended to the authorization endpoint’s URL (as discovered from the previous section.) The base specification for the structure of this request is defined in section 4.1 “Authorization Code Grant” of RFC6749.

At minimum, the following parameters are included in the authorization request; each are documented in the following sections:

  • Requested “scopes” for services to access.
  • A “state” parameter to prevent certain classes of malicious attacks.
  • The target “audience” server URL.
  • (Optional) a “redirect_uri” of the application.
  • (Optional) a launch code, when supporting application launches from external sources.

Scopes

During the authorization process, client applications should identify at runtime:

  • The specific FHIR® resources that will be needed to accomplish the workflow.
  • The type of access needed to the given FHIR® resource (read, write).
  • If access should be constrained to a single patient, as selected by the user.
  • The duration for which access is needed.
  • Each of the above pieces of information are presented in the authorization request to the server in the form of “scopes”. Per the OAUTH specification, the scope of a request is “…a list of space-delimited, case-sensitive strings.
  • The strings are defined by the authorization server.” With SMART® on FHIR®, access to FHIR® resources is controlled by scopes with the following format:
scope-name            = resource-context "/" resource-type "." modification-rights
resource-context = ("user" / "patient" / "system")
resource-type = (Name)
modification-rights = ("read" / "write");

Examples of scopes include:

user/Observation.read (Read all values from the Observation resource that the user has access to.)
patient/MedicationOrder.read (Read medications for a specific patient.)
user/Appointment.write (Create appointments.)

The “resource context” represents one of three possible choices:

  • user: Access to the resource is only constrained by the access of the user.
  • patient: Access to the resource is constrained within context of a single patient.
  • system: Used in system-based authorization workflows, as described in “Requesting Authorization on Behalf of a System”.

Processing the Authorization Grant Response

  • The authorization grant response comes in the form of a x-www-form-urlencoded query string, appended to your redirection URI.

  • The base specification for the structure of this response is defined in section 4.1 “Authorization Code Grant” of RFC6749 (the OAuth2 Framework).

  • The following is an example:

https://example.com/callback?code=0c8b259b-d716-4712-ad6a-1d22d92523fa&state=a4c16a46-2c46-482c-8d66-4cc4a2990bda
  • Within a successful response, a “code” parameter will be present, and a “state” parameter will be present if your application included “state” as part of the initial request.
  • First, validate that the “state” parameter matches that of a request that was initiated by the current device / user agent. Next, exchange the code for a token per section 4.1 of the RFC6749 (the OAuth2 Framework). The following are example requests / responses:

Request:

POST /tenants/ec2458f2-1e24-41c8-b71b-0e701af7583d/protocols/oauth2/profiles/smart-v1/token HTTP/1.1
Host: authorization.cerner.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Content-Length: 161
Connection: close
grant_type=authorization_code&code=0c8b259b-d716-4712-ad6a-1d22d92523fa&client_id=bb318a62-fa61-49ae-b692-7d99214f0ec7&state=a4c16a46-2c46-482c-8d66-4cc4a2990bda

Response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json
Content-Length: 1462
Date: Tue, 01 Nov 2016 19:20:25 GMT

{
"access_token": "eyJraWQiOiIyMDIwLTA3LTI4VDE3OjM2OjA5LjAwNC5lYyIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJwb3J0YWwiLCJ1cm46Y29tOmNlcm5lcjphdXRob3JpemF0aW9uOmNsYWltcyI6eyJ2ZXIiOiIxLjAiLCJ0bnQiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QiLCJhenMiOiJ1c2VyXC9PYnNlcnZhdGlvbi5yZWFkIn0sImF6cCI6ImZoaXItbG9jYWwiLCJpc3MiOiJodHRwczpcL1wvYXV0aG9yaXphdGlvbi5jZXJuZXIuY29tXC8iLCJleHAiOjE1OTYwNTYwNjEsImlhdCI6MTU5NjA1NTQ2MSwianRpIjoiYmMwMzIwYTMtN2E3Yi00MmVkLTgzZDAtMWMxMTVlMjBkMDQzIiwidXJuOmNlcm5lcjphdXRob3JpemF0aW9uOmNsYWltczp2ZXJzaW9uOjEiOnsidmVyIjoiMS4wIiwicHJvZmlsZXMiOnsic21hcnQtdjEiOnsiYXpzIjoidXNlclwvT2JzZXJ2YXRpb24ucmVhZCJ9fSwiY2xpZW50Ijp7Im5hbWUiOiJGSElSIExvY2FsIFRlc3QgQ2xpZW50IiwiaWQiOiJmaGlyLWxvY2FsIn0sInVzZXIiOnsicHJpbmNpcGFsIjoicG9ydGFsIiwicGVyc29uYSI6InByb3ZpZGVyIiwiaWRzcCI6ImVjMjQ1OGYyLTFlMjQtNDFjOC1iNzFiLTBlNzAxYWY3NTgzZCIsInNlc3Npb25JZCI6IjFiYmEyOGQ0LTUwM2YtNDgyNi04OTE3LTJhOTIzMzczZjE2YyIsInByaW5jaXBhbFR5cGUiOiJ1c2VybmFtZSIsInByaW5jaXBhbFVyaSI6Imh0dHBzOlwvXC9taWxsZW5uaWEuY2VybmVyLmNvbVwvaW5zdGFuY2VcL2VjMjQ1OGYyLTFlMjQtNDFjOC1iNzFiLTBlNzAxYWY3NTgzZFwvcHJpbmNpcGFsXC8wMDAwLjAwMDAuMDBDMi42REI1IiwiaWRzcFVyaSI6Imh0dHBzOlwvXC9taWxsZW5uaWEuY2VybmVyLmNvbVwvYWNjb3VudHNcL2MxOTQxLmNlcm5fYWJjbi5jZXJuZXJhc3AuY29tXC9lYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2RcL2xvZ2luIn0sInRlbmFudCI6ImVjMjQ1OGYyLTFlMjQtNDFjOC1iNzFiLTBlNzAxYWY3NTgzZCJ9fQ.AruMhr4eaG3QHb794wzavhcD8NQAnao5sZWAe4cFbX4-oSd3pUwomoZ-zR8stSKhnaodS0l5bKGkd72goX0PNQ",
"scope": "user/Observation.read",
"token_type": "Bearer",
"expires_in": 570
}

Three elements of the response should be evaluated:

  • access_token: This is the secret content to send to a FHIR® service to prove authorization for acting on behalf of a user.
  • scope: This is the space-delimited list of scopes that were authorized for use. This list may differ from the list of scopes included in the initial request. In some circumstances, the server may redact scopes - in others, users may have the capacity to redact scopes.
  • expires_in: The number of seconds before the token expires. If access is required for longer than the expiration of the token, consider requesting online_access or offline_access, as needed.

The following additional elements may be returned:

  • patient: The FHIR® id of a Patient resource in context of the current “launch”.
  • encounter: The FHIR® id of an Encounter resource in context of the current “launch”.
  • refresh_token: A token that be exchanged at the token endpoint for new access tokens.
  • id_token: An OpenID Connect identity token that can be used as “authentication” to your application.

Closing the Grant Interaction

  • Once the authorization grant response has been received, the separate window / user agent for the facilitating the grant interaction should be automatically closed, where possible (an example of this for web-based applications is included earlier in this document.).
  • In the event this step is either not successful or not possible, content is provided by the authorization server to inform the user if it is safe to close the additional window.
  • The authorization server itself will not attempt to self-close the window, as this generally results in a prompt from the browser asking for permission.

Utilizing Refresh Tokens

If your application is designed to interact with a user over periods of time longer than that of a single access token, it will be necessary to utilize “refresh” tokens. A refresh token is an additional secret value, returned as part of the initial access token response, that can be used to obtain additional access tokens. Two forms of access exist, each are requested as a special scope in the authorization grant request:

Online_access:

Grants a refresh token that can be used for duration of a user’s authenticated “session”. Such refresh tokens are valid until either the user explicitly logs out, the session is terminated by an administrator, or other risk mechanisms (timeouts, etc.) require a user to be re-authenticated.

Offline_access:

Grants a refresh token that can be utilized until it is revoked by a user, administrator or revoked automatically if access is unused for more than three months.

  • As access tokens are valid for periods that are less than ten minutes, it is recommended to retrieve and cache new tokens in advance of the previous token expiring.
  • Doing so out-of-band of a user interaction will reduce the user’s perception of application latency.
  • Refresh attempts at intervals lower than one minute may result in throttling.
  • It is not recommended to utilize tokens that are near the precipice of expiry as latency could result in token rejection.

Access Token Request / Response The following are examples of the request/response mechanism defined in section 6 “Refreshing an Access Token” of the OAuth2 Framework.

Request:

POST /tenants/ec2458f2-1e24-41c8-b71b-0e701af7583d/protocols/oauth2/profiles/smart-v1/token HTTP/1.1
Host: authorization.cerner.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Content-Length: 75
Connection: close

grant_type=refresh_token&refresh_token=b30911a8-9278-45aa-bbd9-aa05244faf3b

Response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json
Content-Length: 1514
Date: Tue, 01 Nov 2016 20:48:32 GMT

{
"access_token": "eyJraWQiOiIyMDIwLTA3LTI4VDE3OjM2OjA5LjAwNC5lYyIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJwb3J0YWwiLCJ1cm46Y29tOmNlcm5lcjphdXRob3JpemF0aW9uOmNsYWltcyI6eyJ2ZXIiOiIxLjAiLCJ0bnQiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QiLCJhenMiOiJvbmxpbmVfYWNjZXNzIHVzZXJcL09ic2VydmF0aW9uLnJlYWQifSwiYXpwIjoiZmhpci1sb2NhbCIsImlzcyI6Imh0dHBzOlwvXC9hdXRob3JpemF0aW9uLmNlcm5lci5jb21cLyIsImV4cCI6MTU5NjA1NjIyOCwiaWF0IjoxNTk2MDU1NjI4LCJqdGkiOiI4YzdjNDBlMy00NDA0LTQ4MmMtYjY2MC0xOTFhNWQ1M2ViNjAiLCJ1cm46Y2VybmVyOmF1dGhvcml6YXRpb246Y2xhaW1zOnZlcnNpb246MSI6eyJ2ZXIiOiIxLjAiLCJwcm9maWxlcyI6eyJzbWFydC12MSI6eyJhenMiOiJvbmxpbmVfYWNjZXNzIHVzZXJcL09ic2VydmF0aW9uLnJlYWQifX0sImNsaWVudCI6eyJuYW1lIjoiRkhJUiBMb2NhbCBUZXN0IENsaWVudCIsImlkIjoiZmhpci1sb2NhbCJ9LCJ1c2VyIjp7InByaW5jaXBhbCI6InBvcnRhbCIsInBlcnNvbmEiOiJwcm92aWRlciIsImlkc3AiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QiLCJzZXNzaW9uSWQiOiIxYmJhMjhkNC01MDNmLTQ4MjYtODkxNy0yYTkyMzM3M2YxNmMiLCJwcmluY2lwYWxUeXBlIjoidXNlcm5hbWUiLCJwcmluY2lwYWxVcmkiOiJodHRwczpcL1wvbWlsbGVubmlhLmNlcm5lci5jb21cL2luc3RhbmNlXC9lYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2RcL3ByaW5jaXBhbFwvMDAwMC4wMDAwLjAwQzIuNkRCNSIsImlkc3BVcmkiOiJodHRwczpcL1wvbWlsbGVubmlhLmNlcm5lci5jb21cL2FjY291bnRzXC9jMTk0MS5jZXJuX2FiY24uY2VybmVyYXNwLmNvbVwvZWMyNDU4ZjItMWUyNC00MWM4LWI3MWItMGU3MDFhZjc1ODNkXC9sb2dpbiJ9LCJ0ZW5hbnQiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QifX0.e0fhw5QGS_Nf2GQw5zdPOr79j-NQkk5pWQKuvXgo_jMW3Nwqi47KKrMF2eUkAtf9-_hyHEU_R6Ri8Je5FRfjoA",
"scope": "user/Observation.read online_access",
"token_type": "Bearer",
"expires_in": 570
}

NOTE: The token response from a refresh will not contain a new refresh token. The original refresh token from the initial grant response must be retained.

Utilizing Authorization

To utilize access Cerner FHIR® resources utilizing an access token, include a “bearer” authorization header in your HTTP request per RFC 6750 as follows:

Authorization: Bearer eyJraWQiOiIyMDIwLTA3LTI4VDE3OjM2OjA5LjAwNC5lYyIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJwb3J0YWwiLCJ1cm46Y29tOmNlcm5lcjphdXRob3JpemF0aW9uOmNsYWltcyI6eyJ2ZXIiOiIxLjAiLCJ0bnQiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QiLCJhenMiOiJvbmxpbmVfYWNjZXNzIHVzZXJcL09ic2VydmF0aW9uLnJlYWQifSwiYXpwIjoiZmhpci1sb2NhbCIsImlzcyI6Imh0dHBzOlwvXC9hdXRob3JpemF0aW9uLmNlcm5lci5jb21cLyIsImV4cCI6MTU5NjA1NjIyOCwiaWF0IjoxNTk2MDU1NjI4LCJqdGkiOiI4YzdjNDBlMy00NDA0LTQ4MmMtYjY2MC0xOTFhNWQ1M2ViNjAiLCJ1cm46Y2VybmVyOmF1dGhvcml6YXRpb246Y2xhaW1zOnZlcnNpb246MSI6eyJ2ZXIiOiIxLjAiLCJwcm9maWxlcyI6eyJzbWFydC12MSI6eyJhenMiOiJvbmxpbmVfYWNjZXNzIHVzZXJcL09ic2VydmF0aW9uLnJlYWQifX0sImNsaWVudCI6eyJuYW1lIjoiRkhJUiBMb2NhbCBUZXN0IENsaWVudCIsImlkIjoiZmhpci1sb2NhbCJ9LCJ1c2VyIjp7InByaW5jaXBhbCI6InBvcnRhbCIsInBlcnNvbmEiOiJwcm92aWRlciIsImlkc3AiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QiLCJzZXNzaW9uSWQiOiIxYmJhMjhkNC01MDNmLTQ4MjYtODkxNy0yYTkyMzM3M2YxNmMiLCJwcmluY2lwYWxUeXBlIjoidXNlcm5hbWUiLCJwcmluY2lwYWxVcmkiOiJodHRwczpcL1wvbWlsbGVubmlhLmNlcm5lci5jb21cL2luc3RhbmNlXC9lYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2RcL3ByaW5jaXBhbFwvMDAwMC4wMDAwLjAwQzIuNkRCNSIsImlkc3BVcmkiOiJodHRwczpcL1wvbWlsbGVubmlhLmNlcm5lci5jb21cL2FjY291bnRzXC9jMTk0MS5jZXJuX2FiY24uY2VybmVyYXNwLmNvbVwvZWMyNDU4ZjItMWUyNC00MWM4LWI3MWItMGU3MDFhZjc1ODNkXC9sb2dpbiJ9LCJ0ZW5hbnQiOiJlYzI0NThmMi0xZTI0LTQxYzgtYjcxYi0wZTcwMWFmNzU4M2QifX0.e0fhw5QGS_Nf2GQw5zdPOr79j-NQkk5pWQKuvXgo_jMW3Nwqi47KKrMF2eUkAtf9-_hyHEU_R6Ri8Je5FRfjoA

If the access token is invalid, the FHIR® resource will return a “WWW-Authenticate” header in the response with additional details per RFC 6750.

Requesting Authorization on Behalf of a System

  • Certain types of applications and automated processes do not act on behalf of end users.
  • Such access is generally utilized by a covered entity itself, or another entity covered under a business associate agreement.
  • Some FHIR® APIs support this model, allowing a client application to directly authenticate for access using a system account issued via Cerner Central System Account Management.
  • See the Registering a System Account section for more information on how to register these applications.

Note: This access model is only supported on resources where explicitly indicated in their respective FHIR® API resource documentation.

Basic Authentication

  • A client performs this request utilizing the “client credentials” flow of OAuth2 to request an access token, using the Basic authentication scheme for passing credentials.
  • The credentials to use to perform this request will be based on the system account.
  • The access token should be created using the system account’s id and secret, and encoded using the Base64 encoding scheme.
  • Then, it can be used as the Basic Authorization for a request.
  • The following is an example of an access token using the Basic authentication scheme:
System account id / Client id: bb318a62-fa61-49ae-b692-7d99214f0ec7
Secret: secret

Base64 encode "clientid:secret":
"bb318a62-fa61-49ae-b692-7d99214f0ec7:secret" => YmIzMThhNjItZmE2MS00OWFlLWI2OTItN2Q5OTIxNGYwZWM3OnNlY3JldA==

Use this value in Authorization header:
Authorization: Basic YmIzMThhNjItZmE2MS00OWFlLWI2OTItN2Q5OTIxNGYwZWM3OnNlY3JldA==
  • The following is a non-normative example of a request made using the system account credentials:

Request:

POST /tenants/ec2458f2-1e24-41c8-b71b-0e701af7583d/protocols/oauth2/profiles/smart-v1/token HTTP/1.1
Host: authorization.cerner.com
Authorization: Basic YmIzMThhNjItZmE2MS00OWFlLWI2OTItN2Q5OTIxNGYwZWM3OnNlY3JldA==
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Content-Length: 61
Connection: close
grant_type=client_credentials&scope=system%2FObservation.read%20system%2FPatient.read

As an example, here is how the token may be requested via cURL:

export SYSTEM_ACCOUNT_CLIENT_ID="bb318a62-fa61-49ae-b692-7d99214f0ec7"
export SYSTEM_ACCOUNT_CLIENT_SECRET="secret"

curl -X POST 'https://authorization.cerner.com/tenants/ec2458f2-1e24-41c8-b71b-0e701af7583d/protocols/oauth2/profiles/smart-v1/token' \
-H 'Accept: application/json' \
-H "Authorization: Basic $(echo -n $SYSTEM_ACCOUNT_CLIENT_ID:$SYSTEM_ACCOUNT_CLIENT_SECRET | base64)" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'cache-control: no-cache' \
-d 'grant_type=client_credentials&scope=system%2FObservation.read%20system%2FPatient.read'

JWT Authentication

  • Alternatively, clients may authenticate themselves using signed JSON Web Tokens (JWTs).
  • This process is similar to the above, but uses Authorization: Bearer instead.
  • This is the preferred mode of authentication for Bulk Data clients.
  • For complete details, see Java Web Token (JWT) and JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants.

Note that clients leveraging this type of authentication must also pre-register their JSON Web Key Sets (JWKS) using Cerner Central System Account Management. For complete details, see Managing JSON Web Key Sets in System Account Management.

References:

https://fhir.cerner.com/authorization/