SMART on FHIR

SMART App Launch Framework

Adherence to the SMART on FHIR specification is required to connect to Opala’s FHIR APIs that use authorization: Opala’s Patient Access API (member-initiated, interactive launches) uses the Authorization Code flow (PKCE recommended), while Opala’s Member Attribution API (system-to-system integrations) uses SMART Backend Services (client credentials with a signed JWT).  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:

  1. 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 flavor of OpenID Connect that is customized for use in the context of healthcare.

  2. Access to Data: SMART uses the FHIR standard for reading and/or updating 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.

  3. 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 values that determines the context being passed to the application. This context can include information about the currently selected patient, clinical encounter, styling information, etc.

Platforms

The SMART technology platform enables healthcare organizations to plug third-party medical applications into their clinical data systems. These applications can take several forms:

  • Web Apps: Web-based applications are presently the most common type of SMART application. 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.
  • Backend Services (Server or 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 (SMART Backend Services) can also be created using the specification.

The Web App Launch Process

The following describes the sequence of events that occurs when a SMART on FHIR web-based application is started.

  1. Application Launch. The user starts the application. For web-based applications, the user generally follows a link to the application. This link includes parameters specifying the launch context.
    For example:
    https://mysmartapp.example/launch?iss=https://{baseurl}&launch=wd9833
    The {baseurl} is the FHIR server base endpoint. For example, an application launch against Opala’s Patient Access API might look like:

    https://mysmartapp.example/launch?iss=https://opala.tech/patient-access/premera/v1/fhir-r4&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://{baseurl}/.well-known/smart-configuration
    Along with exposing the issuer and supported interactions, the discovery document contains two important URLs:

    • The Authorization Endpoint – The URL that the user will be directed to in order to actually log in.

    • The Token Endpoint – A service endpoint that the SMART on FHIR Application may communicate with in order to exchange data with the authorization server.
  2. Request Access. The application directs the user to an OpenID Connect authorization server. Generally, 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. For web apps, this usually works via a redirect to the authorization server; for mobile apps, a browser window temporarily opens.

    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.

  3. Receive Tokens. 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. 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:

    {
        "jti": "155bf20e-5caf-415f-8078-5c896350c828",
        "iat": 1615563526,
        "exp": 1615563586,
        "aud": "client-id",
        "sub": "user123",
        "iss": "https://{baseurl}",
        "given_name": "GIVEN_NAME",
        "family_name": "FAMILY_NAME",
        "profile": "https://{baseurl}RelatedPerson/123",
        "nonce": "idihrgy",
        "auth_time": 1615563526,
        "at_hash": "GMPkjip0n0mGmMaOs8HA3w"
    }


    The user may also receive:

    • ID Token – Contains information about the logged-on user (e.g., name, email, profile).

    • Refresh Token – Allows requesting new access tokens after expiration.
  4. Client Request to Access or Modify Clinical Data. The application is now able to 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. If authorized, 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
    Headers:
    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).
  5. Validate Token. The Resource Server now validates that the token is acceptable by verifying the digital signature. The token has been digitally signed by the authorization server. 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 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": "https://{baseurl}/RelatedPerson/999",
        "iss": "https://{baseurl}",
        "exp": 1516069149,
        "iat": 1516069089,
        "jti": "95d12878-dd09-4d61-9930-d4b3cf077ec2"
    }


    Definitions:

    • 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).
  6. Introspect Token and Request (optional). The application may require more information about the issued tokens. This can include additional details about the user the token was issued for, and information about the token itself, such as its expiration time and associated scopes.

    For example, an application sends the following request to the authorization server:
    POST /oauth/token/introspect
    Headers:
    Accept: application/json
    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic [client_id and client_secret]
    Body:
    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:

    Response:
    {
        "active": true,
        "scope": "patient/*.read online_access openid profile",
        "client_id": "growth_chart_smart_app",
        "token_type": "Bearer",
        "exp": 1516069149,
        "iss": "https://{baseurl}"
    }
  7. Server Response to Access or Modify Clinical Data. 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 responds to the given FHIR query.

Authorization

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.

Additional Resources