SMART on FHIR
This guide explains how to use Descope as an OAuth 2.0 provider for SMART on FHIR applications. SMART on FHIR is a healthcare industry standard that allows third-party applications to securely access Electronic Health Record (EHR) data.
Descope's Inbound Apps feature enables you to act as an OAuth provider for SMART apps, handling user authentication, consent, and token issuance while your application manages the SMART-specific launch context and FHIR API calls.
Overview
SMART on FHIR provides a standardized way for healthcare applications to:
- Launch from within an EHR system (EHR Launch) or as a standalone application (Standalone Launch)
- Request access to patient data with granular scopes
- Handle user authentication and authorization
- Access FHIR resources on behalf of authenticated users
Descope supports both EHR Launch and Standalone Launch flows through Inbound Apps, which provide:
/authorizeendpoint for user authentication and consent/tokenendpoint for token exchange- JWT templates for customizing access tokens with SMART-specific claims
- Scope management and validation
Architecture
In a SMART on FHIR integration with Descope:
- Your application receives launch requests from the EHR (for EHR Launch) or initiates authentication (for Standalone Launch)
- Descope acts as the OAuth authorization server, handling user authentication and consent
- Your application receives the access token and uses it to call the EHR's FHIR API
The access token issued by Descope includes SMART-specific claims (like patient, encounter) that your application forwards to the EHR's FHIR server.
Launch Types
EHR Launch
The app is launched from within the EHR. The EHR redirects to your app with a launch parameter containing an encrypted launch context token.
Flow:
- User clicks your app in the EHR
- EHR redirects to your app with
iss(EHR issuer URL) andlaunchparameters - Your app extracts launch context and redirects to Descope for authorization
- User authenticates and consents via Descope
- Descope redirects back with authorization code
- Your app exchanges code for access token
- Access token includes launch context (patient ID, encounter ID, etc.)
Standalone Launch
The app is launched independently, without being embedded in the EHR. Users authenticate directly.
Flow:
- User navigates directly to your app
- Your app redirects to Descope for authorization
- User authenticates and consents via Descope
- Descope redirects back with authorization code
- Your app exchanges code for access token
- Access token can be used to access FHIR resources (patient selection may happen later)
Integration Steps
1. Configure Your Inbound App in Descope
-
In the Descope Console, navigate to Inbound Apps. Click + Inbound App.
-
Configure the required scopes for your SMART app. Common SMART scopes include:
patient/*.rs- Read and search any resource for the current patientpatient/*.read- Read any resource for the current patientuser/*.rs- Read and search any resource for the current userlaunch- Required for EHR Launch to receive launch contextopenid- Standard OIDC scopefhirUser- Retrieve information about the current logged-in useroffline_access- Request a refresh token
For a complete list of SMART scopes, refer to the SMART App Launch documentation.
-
Set the redirect URI to your application's callback URL (e.g.,
https://yourapp.com/oauth/callback) -
Optionally customize your consent flow to match your branding
2. Configure JWT Template for SMART Claims
Create a JWT template that includes SMART-specific claims in the access token:
- In the Descope Console, go to Project Settings -> JWT Templates, and create a new template.
- Configure the template with SMART-specific claims:
Some of the key claims that you will need to configure are:
aud- The FHIR server URL (audience). This should match the EHR's FHIR endpointscope- The authorized scopes (automatically included)patient- Patient ID from launch context (for EHR Launch)encounter- Encounter ID from launch context (if available)need_patient_banner- Indicates if the app should display patient contextsmart_style_url- URL for SMART styling resources (optional)
- Under Project Settings -> Session Management, assign this JWT template as the User JWT
The aud claim must match the FHIR server URL where your app will make API calls. For multi-EHR scenarios, you may need to use dynamic values or create separate templates per EHR.
3. Handle Launch Parameters (EHR Launch)
When your app receives a launch request from the EHR, extract the launch context:
4. Build Authorization Request
Construct the authorization request to Descope's /authorize endpoint:
5. Handle OAuth Callback
After user authentication and consent, Descope redirects back to your callback URL:
6. Exchange Authorization Code for Token
Note
The client_secret comes from the Inbound App configuration.
Exchange the authorization code for an access token:
The token response includes:
7. Extract Launch Context from Token
Decode the access token to extract SMART-specific claims:
8. Use Access Token with FHIR API
Use the access token to call the EHR's FHIR API:
Standalone Launch Example
For Standalone Launch, the flow is simpler since there's no launch context:
Handling Launch Context
For EHR Launch, you need to decode the launch parameter to extract patient and encounter IDs. The launch parameter is typically a JWT or encrypted token provided by the EHR.
The exact format of the launch parameter varies by EHR. Some EHRs provide it as a simple identifier that you exchange for launch context via their API, while others provide it as a JWT. Consult your EHR's SMART on FHIR documentation for specifics.
Token Refresh
SMART on FHIR access tokens are typically short-lived. Use the refresh token to obtain a new access token:
Troubleshooting
These are some common issues you might encounter when integrating with SMART on FHIR:
| Issue | Likely Cause | Solution |
|---|---|---|
Invalid launch parameter | Launch context expired or malformed | Ensure launch context is used immediately after receipt |
Missing patient claim in token | Launch context not properly extracted | Verify launch parameter decoding and JWT template configuration |
| FHIR API returns 401 | aud claim doesn't match FHIR server URL | Ensure JWT template aud claim matches the EHR's FHIR endpoint |
| Scope not granted | Scope not configured in Inbound App | Add required scope to Inbound App configuration |
| State mismatch | CSRF protection or session issue | Verify state parameter is properly stored and validated |