SMART App Launch

This functionality is available starting from version 2411. The FHIR Schema Validator Engine should be enabled.

Performing SMART App Launch with Aidbox requires:

Register SMART Client

SMART defines two client (application) types: public and confidential. To determine the correct client type for you, ask: "Can my app protect a secret?"

If the answer is "Yes," use a confidential client.

  • Example: The app operates on a trusted server, ensuring that the secret is only accessed server-side.

  • Example: The app is a native application that employs additional technologies (such as dynamic client registration and universal redirect_uris) to secure the secret.

If the answer is "No," use a public client.

  • Example: The app is an HTML5 or JavaScript application running in a browser (including single-page applications), where the secret would be exposed in user space.

  • Example: The app is a native application that can only distribute a secret in a fixed, unprotected manner.

Client shall be Authorization Code Grant Client with several required values:

Client resource field
Description

auth.authorization_code.token_format

Fixed value - jwt

auth.authorization_code.secret_required

true - for confidential Client false - for public Client

smart.launch_uri

SMART Application launch endpoint

type

Fixed value - smart-app

secret

Only for confidential Client

Example

PUT /Client/my-public-smart-app-client-id
content-type: application/json
accept: application/json

{
  "resourceType": "Client",
  "id": "my-public-smart-app-client-id",
  "active": true,
  "auth": {
    "authorization_code": {
      "redirect_uri": "http://smart-app-uri.com/redirect",
      "refresh_token": true,
      // always shall be jwt
      "token_format": "jwt",
      "access_token_expiration": 3600000,
      "secret_required": false,
      "pkce": true
    }
  },
  // always shall have smart.launch_uri value
  "smart": {
    "launch_uri": "http://smart-app-launch-endpoint/launch.html"
  },
  // always shall be "smart-app" type
  "type": "smart-app",
  "grant_types": [
    "code"
  ]
}

Create AccessPolicy

PUT /AccessPolicy/my-confidential-smart-app-client-id
content-type: application/json
accept: application/json

{
  "resourceType": "AccessPolicy",
  "id": "my-smart-app-client-id-allow",
  "engine": "allow",
  "link": [{
    "id": "my-public-smart-app-client-id",
    "resourceType": "Client"
  }]
}

Launch App

SMART Launch Interaction Diagram:

Standalone launch

In SMART’s standalone launch flow, a user selects an app from outside the EHR (for example, by tapping an app icon on a mobile phone home screen).

The application should start launch by performing authorization code grant flow.

EHR launch

The EHR initiates a “launch sequence” by opening a new browser instance (or iframe) pointing to the app’s registered launch URL and passing some context.

Launch URL structure

http://smart-app-launch-endpoint?iss=<fhir-endpoint>&launch=<jwt-identifier>

Where:

  1. smart-app-launch-endpoint - SMART Application launch endpoint. It shall be equal to Client.smart.launch_uri.

  2. iss - Identifies the EHR's FHIR endpoint.

  3. launch - JWT identifier for this specific launch and context associated with it. It shall be signed with an Aidbox private key.

launch parameter JWT shall contain the following claims:

Claim name
Value type
Description

client *

valueString

Aidbox client ID.

user*

valueString

Aidbox user ID.

exp*

valueInteger

Experation time in seconds

ctx.patient*

valueString

Patient ID

* - required claim

Get launch URI endpoint

Aidbox provides an endpoint to build the correct launch URI:

POST /rpc
content-type: application/json
accept: application/json

{
  "method": "aidbox.smart/get-launch-uri",
  "params": {
    "user": "my-aidbox-user-id",
    "iss": "https://example.edge.aidbox.app/fhir",
    "client": "my-public-smart-app-client-id",
    "ctx": {
      "patient": "my-patient-id"
    }
  }
}

Obtain authorization code

To obtain a token redirect the user to Aidbox /auth/authorize with following parameters:

Parameter
Description

response_type *

Fixed value - code

client_id *

Client resource ID.

redirect_uri *

Client's pre-registered redirect URIs. Must match the Client.auth.authorization_code.redirect_uri value.

scope *

String with scopes separated by space. Must describe the access that the app needs.

state *

An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHALL be used for preventing cross-site request forgery or session fixation attacks. The app SHALL use an unpredictable value for the state parameter with at least 122 bits of entropy (e.g., a properly configured random uuid is suitable).

aud *

URL of the EHR resource server from which the app wishes to retrieve FHIR data. Usually, it is <AIDBOX_BASE_URL>/fhir.

code_challenge

This parameter is generated by the app and used for the code challenge, as specified by PKCE.

code_challenge_method

Fixed value - S256

launch

When using the EHR Launch flow, this must match the launch value received from the EHR (Aidbox). Omitted when using the Standalone Launch.

*- required parameter

Example

Location: https://<AIDBOX_BASE_URL>/auth/authorize?
            response_type=code&
            client_id=my-public-smart-app-client-id&
            redirect_uri=http://smart-app-uri.com/redirect&
            scope=launch%2Fpatient+openid+fhirUser+offline_access+patient%2F*.read&
            state=863c2f71-11e3-4598-913b-930a6aa1593c&
            aud=https%3A%2F%2Fg10test.edge.aidbox.app%2Ffhir&
            code_challenge=E3VWZsn5u_Tiw6HEz8bleXP27hr8TG-Zjpx5CP0lZxA&
            code_challenge_method=S256

Obtain access token

After obtaining an authorization code, the app exchange the code for an access token. To do it send requiest to AIdbox's /auth/token with following parameters:

Parameter
Description

grant_type *

Fixed value - authorization_code

code *

Code that the app received from Aidbox on the previous step.

redirect_uri *

Client's pre-registered redirect URIs. Must match the Client.auth.authorization_code.redirect_uri value.

code_verifier

This parameter is used to verify against the code_challenge parameter previously provided in the authorize request.

client_id

Required for public apps. Omit for confidential apps.

*- required parameter

Example

POST /auth/token
content-type: application/json
accept: application/json

{
  "client_id": "my-public-smart-app-client-id",
  "code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjE3MzQwMzMxMzksInNjb3BlIjpbImxhdW5jaC9wYXRpZW50Iiwib3BlbmlkIiwiZmhpclVzZXIiLCJvZmZsaW5lX2FjY2VzcyIsInBhdGllbnQvUGF0aWVudC5yZWFkIiwicGF0aWVudC9BbGxlcmd5SW50b2xlcmFuY2UucmVhZCIsInBhdGllbnQvQ2FyZVBsYW4ucmVhZCIsInBhdGllbnQvQ2FyZVRlYW0ucmVhZCIsInBhdGllbnQvQ29uZGl0aW9uLnJlYWQiLCJwYXRpZW50L0RldmljZS5yZWFkIiwicGF0aWVudC9EaWFnbm9zdGljUmVwb3J0LnJlYWQiLCJwYXRpZW50L0RvY3VtZW50UmVmZXJlbmNlLnJlYWQiLCJwYXRpZW50L0dvYWwucmVhZCIsInBhdGllbnQvRW5jb3VudGVyLnJlYWQiLCJwYXRpZW50L0ltbXVuaXphdGlvbi5yZWFkIiwicGF0aWVudC9NZWRpY2F0aW9uUmVxdWVzdC5yZWFkIiwicGF0aWVudC9PYnNlcnZhdGlvbi5yZWFkIiwicGF0aWVudC9Qcm9jZWR1cmUucmVhZCIsInBhdGllbnQvUHJvdmVuYW5jZS5yZWFkIiwicGF0aWVudC9QcmFjdGl0aW9uZXIucmVhZCIsInBhdGllbnQvT3JnYW5pemF0aW9uLnJlYWQiLCJwYXRpZW50L0xvY2F0aW9uLnJlYWQiXSwiYmFzZS11cmwiOiJodHRwczovL2cxMHRlc3QuZWRnZS5haWRib3guYXBwL2ZoaXIiLCJqdGkiOiIyWTNFbmxkSjV0M3lpbjN2TGxXTiIsImN0eCI6eyJwYXRpZW50IjoidGVzdC1wdC0xIn0sImNsaSI6ImluZmVybm8tcGF0aWVudC1zbWFydC1hcHAiLCJjb2RlX2NoYWxsZW5nZSI6IlZoNUlEXzdkdEEtTVlRTUtEdmNyZFJZN3dOSU9DWkdTSElUdlpCcU5yeDAiLCJvbi1iZWhhbGYiOnRydWUsImNvZGVfY2hhbGxlbmdlX21ldGhvZCI6IlMyNTYifQ.kyjOQ16BB_gieSKDcUjm9WpuzYtI1xRmVAMottiOOEw",
  "code_verifier": "2ef1d0dc-7659-41f9-abbe-bdec3441bca9-81867d53-46a5-47a6-89df-03872627287f",
  "grant_type": "authorization_code",
  "redirect_uri": "http://smart-app-uri.com/redirect"
} 

Access FHIR API

Use access_token received in the previous step to access Aidbox FHIR API:

GET /fhir/Observation?code=4548-4&_count=2
content-type: application/json
accept: application/json
authorization: "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdHYiOjIsImF1ZCI6Imh0dHBzOi8vZzEwdGVzdC5lZGdlLmFpZGJveC5hcHAvZmhpciIsInN1YiI6InRlc3QtdXNlciIsImlzcyI6Imh0dHBzOi8vZzEwdGVzdC5lZGdlLmFpZGJveC5hcHAiLCJleHAiOjE3MzQwMzQ3MTYsInNjb3BlIjoibGF1bmNoL3BhdGllbnQgb3BlbmlkIGZoaXJVc2VyIG9mZmxpbmVfYWNjZXNzIHBhdGllbnQvUGF0aWVudC5yZWFkIHBhdGllbnQvQWxsZXJneUludG9sZXJhbmNlLnJlYWQgcGF0aWVudC9DYXJlUGxhbi5yZWFkIHBhdGllbnQvQ2FyZVRlYW0ucmVhZCBwYXRpZW50L0NvbmRpdGlvbi5yZWFkIHBhdGllbnQvRGV2aWNlLnJlYWQgcGF0aWVudC9EaWFnbm9zdGljUmVwb3J0LnJlYWQgcGF0aWVudC9Eb2N1bWVudFJlZmVyZW5jZS5yZWFkIHBhdGllbnQvR29hbC5yZWFkIHBhdGllbnQvRW5jb3VudGVyLnJlYWQgcGF0aWVudC9JbW11bml6YXRpb24ucmVhZCBwYXRpZW50L01lZGljYXRpb25SZXF1ZXN0LnJlYWQgcGF0aWVudC9PYnNlcnZhdGlvbi5yZWFkIHBhdGllbnQvUHJvY2VkdXJlLnJlYWQgcGF0aWVudC9Qcm92ZW5hbmNlLnJlYWQgcGF0aWVudC9QcmFjdGl0aW9uZXIucmVhZCBwYXRpZW50L09yZ2FuaXphdGlvbi5yZWFkIHBhdGllbnQvTG9jYXRpb24ucmVhZCIsImp0aSI6IjlmMjUxODU1LWQ1MTAtNDY2Mi1iZTg2LTE5ZTljZDYzN2Y2OCIsImNvbnRleHQiOnsicGF0aWVudCI6InRlc3QtcHQtMSJ9LCJpYXQiOjE3MzQwMzQ0MTZ9.EC815f80x6QJebLLWmS0E9XjzPPee5QpIMYz0Oos9ocR_3b4FOsQalModuG4YMGkyZXJOwE29WUjv0fVVXGovdfb0a1hR3iK9_p28qUUb_OmGHo22Upt6K-smHkV8krGM5xNm6g_YPSFT1u9T4qlWoNMoCpti5UdKlmBjHdcIwXoeLb5yC9BynwkJBUpt5PTtE-_gpC_VIg6WkC1hwe2RrDwJl8qvaFl2VZEPhdLU2it3WnX1R-JR_tkXbmY8pv6UfeuPGABleR1sPweyQ-pz3coK4KmkY0tm_7OsBQGKgX9s7RIBP3ab3-dnx8XBJ_s9lw_zefIcYjCuBqZbZU12w"

Refresh access token

To refresh the access_token send request to Aidbox's /auth/token endpoint with following parameters:

Parameter
Description

grant_type *

Fixed value - refresh_token

refresh_token *

The refresh token from the authorization response.

client_id

Client resource ID.

scope

String with scopes separated by space. Must describe the access that the app needs.

*- required parameter

Example

POST /auth/token
content-type: application/json
accept: application/json

{
  "grant_type": "refresh_token"