Adherence to the SMART on FHIR specification is required by Opala. The specification provides a consistent approach to security and data requirements for health applications. SMART on FHIR defines a workflow that an application can use to securely request access to data, then receive and use that data.
You can think of SMART on FHIR as having three different attributes:
The SMART technology platform enables healthcare organizations to plug third-party medical applications into their clinical data systems. These applications can take several forms:
The following illustrates the sequence of events that occurs when a SMART on FHIR web-based application is started.
For web-based applications, the user generally follows a link to the application. This link includes parameters specifying the launch context. For example:
https://myapp.com/launch.html?iss=https://app-url.com:8000/baseR4&launch=wd9833
The launch context includes the following parameters:
iss |
This parameter provides the base URL for the FHIR server the application should use to fetch data. |
launch |
Typically the parameter is a string of random characters that are passed back to the authorization server in order to associate this particular instance of the launch flow across the various steps. |
In the first step of the launch sequence, the SMART Application fetches the FHIR Server’s SMART Discovery Document. This document is a small JSON document hosted at a predictable URL behind the FHIR server that the SMART Application can use to learn more about the authorization requirements of the FHIR server.
To fetch the discovery document, the application appends /.well-known/smart-configuration
to the base URL of the FHIR endpoint. For example:
https://app-rul.com:8000/baseR4/.well-known/smart-configuration
The discovery document contains two important URLs:
Generally, the user is passed to a third-party website where they are asked to enter credentials (if they aren’s already logged in) without the SMART on FHIR application ever knowing what those credentials are. In the case of web applications, this step usually works by having the user follow a link that temporarily takes the user to the third-party authorization server. In the case of mobile applications, a web browser window is temporarily opened on the user’s device in order to allow the user to access the authorization server.
When the SMART on FHIR Application directs the user to the authorization server, it also requests a set of OAuth2 Scopes. These scopes are defined in the SMART on FHIR specification. See SMART on FHIR Scopes and Launch Context for a complete list of scopes defined in the specification.
As a part of this step, the SMART on FHIR application receives an access token. An access token is a long string of characters that contain the security identity of a process and serve as credentials. Opala uses access tokens in the JSON Web Token (JWT) format. JWTs are small JSON documents that have been digitally signed. These documents contain information about where a token was issued and what application requested it.
The user may also receive two additional tokens:
The ID Token contains information about the logged-on user, including name and email address, and may also include a FHIR URL to a resource describing the user. For example:
{ "jti":"155bf20e-5caf-415f-8078-5c896350c828", "iat":1615563526, "exp":1615563586, "aud":"my-client-id", "sub":"user123", "iss":"http:\/\/example.com\/issuer", "given_name":"GIVEN_NAME", "family_name":"FAMILY_NAME", "profile":"http:\/\/example.com\/issuer\/fhir\/RelatedPerson\/123", "nonce":"idihrgy", "auth_time":1615563526, "at_hash":"GMPkjip0n0mGmMaOs8HA3w" }
The request could be a FHIR search
operation for discovering data, or a FHIR create
operation for uploading newly created data. The scopes that were requested and granted by the authorization server are used to determine whether the user has the appropriate permission to perform the specific function they are invoking. For example:
GET /Observation?subject=Patient/123
Accept: application/fhir+json
Authorization: Bearer eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
Notice that the call contains an authorization
header whose value is the string Bearer
followed by the access token. For readability, the token has been shortened (real tokens are much longer).
As shown in step 4, the token takes a form similar to the following: eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
. The format of the token is called JWT (JSON Web Token), and libraries are available that can be used to decode this token for most languages. Decoding the token results in a JSON document similar to the following:
{ "azp":"my-client-id", "profile":"http:\/\/example.org:8884\/fhir\/RelatedPerson\/999", "iss":"http:\/\/example.org:8884", "exp":1516069149, "iat":1516069089, "jti":"95d12878-dd09-4d61-9930-d4b3cf077ec2" }
Each key in this payload is called a claim, and the claims are defined by the JWT, OAuth2, and OpenID Connect specifications.
azp |
The ID of the client (SMART application) on whose behalf the token was issued. |
profile |
The FHIR resource URL (i.e., a resource ID) that can be used to fetch a resource corresponding to the user who authenticated and requested the token. |
iss |
The base URL of the authorization server. According to the OpenID Connect specification, a client can add /.well-known/openid-configuration to this URL to fetch a metadata statement describing the endpoints and functionality of the authorization server. |
exp |
The expiry date of the token, specified as the number of seconds since the Unix epoch. The Resource Server can use this claim to determine whether a token is still valid without needing to talk to the authorization server. Because the token is digitally signed, the SMART application is not able to alter this time. |
iat |
The time at which the JWT was issued. This claim can be used to determine the age of the token. |
jti |
(optional) A unique identifier used to prevent the JWT from being replayed (i.e., this claim allows a token to be used only once). |
For example, an application sends the following request to the authorization server:
POST /oauth/token/introspect
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic [client_id and client_secret]
token=eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
The server sends back the following response, including (in the scope
claim) that the user has been approved for a SMART Patient read scope:
{ "active": true, "scope": "patient/*.read online_access openid profile", "client_id": "growth_chart", "token_type": "Bearer", "exp": 1516069149, "iss": "http://localhost:8884" }
An app can launch from within an existing EHR or Patient Portal session, known as an EHR launch, or it can launch as a standalone app.
When an app receives a launch request, it requests authorization to access a FHIR resource. It does this by causing the browser to navigate to the EHR’s authorization endpoint. Based on pre-defined rules and possibly end-user authorization, the EHR authorization server either grants the request by returning an authorization code to the app’s redirect URL or denies the request. The app then exchanges the authorization code for an access token, which the app presents to the EHR’s resource server to access requested FHIR resources.
Note: If a refresh token is returned with the access token, the app may use this to request a new access token with the same scope once the current access token expires.
Both the iss
and launch
parameters are required when requesting an access token. For access tokens, the iss
parameter identifies the EHR’s FHIR endpoint, which the app can use to obtain additional details about the EHR, including its authorization URL; the launch
parameter (an opaque identifier for this specific launch and any EHR context associated with it) passes a launch
parameter back to the EHR at authorization time.