SMART App Launch
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:
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
scope
List of scopes this client is authorized to request.
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:
smart-app-launch-endpoint
- SMART Application launch endpoint. It shall be equal toClient.smart.launch_uri
.iss
- Identifies the EHR's FHIR endpoint.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:
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:
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:
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:
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",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2cxMHRlc3QuZWRnZS5haWRib3guYXBwIiwic3ViIjoiaW5mZXJuby1wYXRpZW50LXNtYXJ0LWFwcCIsImp0aSI6IjlmMjUxODU1LWQ1MTAtNDY2Mi1iZTg2LTE5ZTljZDYzN2Y2OCIsInR5cCI6InJlZnJlc2gifQ.iKXaJjfAL5dRqfiduLuCgEJhWu0CIzi_2KPS6d80OEp24LB61M4PWx1_TUUS5qaedzrKUBhkE7-x07fI-6f5FdiBMGxq_aKbfGxTAUJJzh-ki-N20IOSolKFNSqyKILhwIP4V221H0YQZFles5ghXBGxK_O5TW-l9w3QDbcsLXBbhH1fOqetsiKdVac8iy2H278iMVnWq3eD8I_-O3yAuISxh_nOI4ENGnX8Z1KKcdrMDmwN7HNsTxmSLM5zkikPZlqIp02JijcV4y8z3XfVZhR2jaXmegTfz_qEWyVrgPYX1-oQ06MZFkgjnlYCZMswvz_wEPuE0zDPJMgGbiUwjg",
"client_id": "my-public-smart-app-client-id"
}
SMART App Launch using an External Identity Provider
Aidbox enables SMART App Launch with external identity providers. Set up an IdentityProvider in Aidbox to sign in via the provider during the launch. Try it with our pre-configured demo (e.g., Keycloak):
Last updated
Was this helpful?