The SMART on FHIR specification is a popular choice for providing 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, and then receive and use that data.
The SMART App Gallery contains many examples of SMART on FHIR apps, and more are being created every day.
In a nutshell, SMART on FHIR can be thought of as three things:
Identity and Access Management: SMART uses the OpenID Connect identity management protocol, which allows applications to request access to clinical data. This access might be simple read-only access to a few records, broad read/write access to an entire EHR, or anything in between. The SMART specifications describe a specific flavour of OpenID Connect that is customized for use in the health context.
Access to Data: SMART uses the FHIR standard for actually reading and/or updating that data. This means that in a SMART on FHIR architecture, a set of FHIR services are available for use by SMART applications. These services are secured using the Identity and Access Management layer described above.
Launch: For web-based applications, SMART describes a consistent URL scheme for portals, EHRs, etc., to use for launching web-based applications with a set of context being passed to the application. This context can include information about the currently selected patient, clinical encounter, styling information, etc.
Applications can take many forms:
Web Apps: Web-based applications are presently the most common type of SMART application found in the gallery. Part of the appeal of the SMART on FHIR specification is that in many cases it is possible to create useful applications without needing to create a backend layer. In other words, a meaningful application can be written in purely HTML + Javascript + CSS using a SMART on FHIR server as the application backend.
Mobile Apps: The technologies used in the SMART on FHIR specification are equally useful for creating rich mobile/mHealth applications, too.
Server / Back Office Apps: Interactive user-facing applications are not the only purpose for the SMART on FHIR specification. By providing a consistent way of authorizing access to data, backend processing applications can be created too.
This section explains how the launch sequence for a SMART on FHIR application actually works.
First, let's clarify a few technologies we are using.
OAuth2 (sometimes called OA2): This is an authorization protocol that is widely used on the Internet. Consumers are often familiar with this protocol, even if they do not know its name, as it is the protocol that powers processes such as "Login using Google" and "Login using Facebook". OAuth2 allows a user to authenticate to Application A using their account credentials in Application B without Application A ever needing to know (or being able to see) those credentials. As a part of the protocol, the application can also request "Scopes", which are permissions to perform specific functions. For example, an application using "Login using Facebook" might request permission to "see my friend list" or "post on my behalf".
OpenID Connect (sometimes called OIDC): This protocol builds on top of OAuth2 by adding identity management functions such as the ability for the application to learn the user's demographic details and other facts. In other words, think of OpenID Connect as "The OAuth2 Protocol with identity management features added on top".
In the SMART on FHIR Authorization process, there are four participants:
The User: This is the person who is actually logging into the application to perform some function. Not all SMART on FHIR flows actually require a user to be present but most do.
The SMART on FHIR Application (referred to as the "SMART App" or "Client" below): This is an application that the user wishes to access to perform some function.
The Authorization Server: This is an OpenID Connect compliant web server that is able to authenticate users and issue Access Tokens. Smile CDR is able to perform this role but other Authorization Servers may also be used.
The Resource Server: This is a FHIR compliant web server that is able to respond to FHIR REST requests using Access Tokens issued by the Authorization Server. Smile CDR is able to perform this role but other Resource Servers may also be used instead (or in combination with Smile CDR).
The following diagram illustrates the sequence of events when a SMART on FHIR application is started.
For web-based applications, the user will generally follow a link to the application. This link includes parameters specifying the "launch context".
For example, suppose a SMART on FHIR application has been created for visualizing the trend of a specific lab test over time. The workflow for this application would involve users working in another system (such as an EMR or a clinical portal) and following a link to the application from within a view that is specific to a particular patient. The link to launch the SMART on FHIR application would include details about which patient was being viewed.
Note that this step is optional, and it is only used when the application is being launched by another application. In other architectures (e.g. mobile applications and standalone web applications), the authorization process might not work this way.
The following SMART on FHIR compliant launch URL shows a launch of the example "MyLabViewer" application:
https://mylabviewer.com/launch.html
Note the URL parameters in the example:
iss
is the base URL for a FHIR server that the application should use to fetch data. In the example above, the issuer is https://try.smilecdr.com:8000/baseR4
, and this is assumed to be the base URL of a FHIR server, meaning that the server's CapabilityStatement
can be loaded at the URL: https://try.smilecdr.com:8000/baseR4/metadata
.launch
is a string of typically random characters that will be 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 will fetch 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://try.smilecdr.com:8000/baseR4/.well-known/smart-configuration
This endpoint returns a JSON document similar to the following:
{
"authorization_endpoint": "https://oidc.example.com/authorize",
"token_endpoint": "https://oidc.example.com/oauth/token",
"capabilities": [
"launch-ehr",
"client-public"
]
}
The discovery document contains two important URLs:
The application directs the user to an OpenID Connect Authorization Server. This process is the same one used in the "Login using Facebook" example above but in this case instead of using Google or Facebook we are using a SMART on FHIR compliant authorization server. The general principle is that the user is passed to a third party website where they are asked to enter credentials (if they aren't already logged in) without the SMART on FHIR application ever knowing what those credentials are.
In the case of web applications, this step generally 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 and include the following examples (note that these are only examples, not an exhaustive list). See SMART on FHIR Scopes for a complete list of scopes defined in the specification, and see Smile CDR Supported Scopes for a list of scopes supported by Smile CDR.
patient/*.read
- The application is requesting access to read any data about a specific Patient in the system.
profile
- The application is requesting access to the user's profile (demographic data such as name and email address).
offline_access
- The application is requesting the ability to continue requesting data even when the user is no longer actively using the application.
Once the user has successfully authenticated with the Authorization Server, they are directed back to the SMART on FHIR application. As a part of this step, the SMART on FHIR application receives an Access Token, which is a long string of characters that will serve as credentials in the steps below.
At a glance, the access token looks like a long string of random letters and numbers. In reality, it is not random at all. Smile CDR produces access tokens using the JSON Web Token (JWT) format. JWTs (pronounced "jots") are basically a small JSON document that has been digitally signed. The document contains a few small pieces of information about where the token was issued and what application requested it.
In addition to the access token, the user may receive two other tokens:
An ID Token may also be supplied by the Authorization Server. This token contains information about the logged on user. Informaton can include demographics such as their name and email address, and may also include a FHIR URL to a resource describing the user. See User Profile Information for more information.
A Refresh Token may also be supplied by the Authorization Server. This token can be used to allow the Application to request additional access tokens when the current one has expired. See Refresh Flow for more information.
The application may now invoke FHIR services by communicating with the Resource Server. A SMART on FHIR Resource Server is a FHIR server that supports a set of FHIR operations, and requires an Access Token as a part of this request.
The request might 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 will be used to determine whether the user has appropriate permission to perform the specific function they are invoking.
A sample HTTP request follows. Note the presence of an Authorization
header whose value is the string Bearer
followed by the access token. For readability, the token has been shortened (real tokens are typically much longer).
GET /Observation?subject=Patient/123
Accept: application/fhir+json
Authorization: Bearer eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
The Resource Server should now validate that the token is acceptable. The token has been digitally signed by the Authorization Server, and by verifying this signature the Resource Server can know that it is legitimate.
The verification uses a public key that can either be provided out-of-band or fetched as required by the Resource Server. This public key matches a private key held by the Authorization Server.
As shown above, the token will take a form similar to the following: eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
(although it will generally be longer than this example). This format is called JWT (JSON Web Token), and libraries are available for most languages that can be used to decode this token. 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. Note the following:
azp
: This is the ID of the client (SMART Application) on whose behalf this token was issued.profile
: This is a FHIR resource URL (i.e. a resource ID) that can be used to fetch a resource corresponding to the user who authenticated and requested this token.iss
: This is the issuer, meaning the base URL of the Authorization Server. According to the OpenID Connect specification, a client can add /.well-known/openid-configuration
to this URL and fetch a metadata statement describing the endpoints and functionality of the Authorization Server.exp
: This is the expiry date of the token, specified as the number of seconds since the unix epoch (not to be confused with the Java Date time format that is the number of milliseconds since the unix epoch). This property is important since the Resource Server can use it to determine whether a token is still valid without needing to talk to the Authorization Server, and because the token is digitally signed the SMART Application is not able to alter this time.The Application may wish to learn more information about the issued tokens. This can include additional details about the user the token was issued for, and information about the token such as its expiration time and associated scopes.
The following example shows a request being made by an Application to an 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 following payload shows an example response. Note that the Authorization Server is indicating that the user has been approved for a SMART Patient read scope and several others.
{
"active": true,
"scope": "patient/*.read online_access openid profile",
"client_id": "growth_chart",
"token_type": "Bearer",
"exp": 1516069149,
"iat": 1516069089,
"iss": "http://localhost:8884"
}
Note that invalid tokens, or tokens that have been revoked, result in a 404 - Not Found
error, along with the following response body:
{
"active": false,
"scope": "",
"client_id": "",
"token_type": "",
"exp": "",
"iat": "",
"iss": ""
}
This was done to meet the RFC OAuth 2.0 Token Introspection Specification.
Assuming that the access token has been verified correctly and the token introspection shows that the user has appropriate permissions to perform the desired functions, the server will now respond to the given FHIR query.
The following example shows a FHIR query using an access token issued by the Authorization Server:
GET /Patient/123
Authorization: Bearer eyJraWQiOiJ1b.o_GAe_P5E-y4GrCl.gTYd4is8zAQ
Accept: application/fhir+json