Skip to main content

SMART on FHIR

SMART on FHIR is a standard that enables healthcare applications to securely access patient data across different EHR systems. It builds upon OAuth 2.0 and OpenID Connect to provide healthcare-specific authentication and authorization.

Overview​

SMART on FHIR is an open standard developed by the SMART Health IT project in collaboration with HL7. It allows third-party applications to launch from within EHR systems or standalone, while maintaining consistent security and user experience across different healthcare platforms.

Key Features:

  • EHR Integration: Applications can launch directly from within EHR systems
  • Standardized Scopes: Healthcare-specific permissions using FHIR resource types
  • Patient Context: Applications receive context about which patient's data to access
  • User Context: Applications know which user (patient, practitioner) is authenticated
  • Interoperability: Same app works across different EHR vendors (Epic, Cerner, etc.)

SMART Launch Flows​

SMART on FHIR supports two primary launch patterns:

1. EHR Launch (Contextual Launch)​

EHR Launch is not yet supported in Haste Health

This feature is not yet supported in Haste Health. The following is for informational purposes only.

The application is launched from within an EHR system, automatically receiving context about the patient and user.

Launch URL Format:

https://app.example.com/launch?
iss=https://api.haste.health/w/{tenant}/{project}/api/v1/fhir
&launch=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Authorization Request:

GET /w/{tenant}/{project}/api/v1/oidc/auth/authorize?
response_type=code&
client_id=smart-app-id&
redirect_uri=https://app.example.com/callback&
scope=launch patient/*.read&
state=random-state&
aud=https://api.haste.health/w/{tenant}/{project}/api/v1/fhir&
launch=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

2. Standalone Launch​

The application launches independently, and the user selects which patient's data to access.

SMART Scopes​

SMART on FHIR defines a structured scope syntax that combines permissions with FHIR resource types.

Scope Syntax​

<context>/<resource>.<permission>

Components:

  • Context: Who is accessing the data (patient, user, system)
  • Resource: FHIR resource type (Patient, Observation, etc.) or * for all
  • Permission: Access level (read, write, or * for both)

Scope Categories​

1. Clinical Scopes (Patient Context)​

Access data for the currently selected patient:

patient/* scopes are not currently enforced

The server rejects any request whose best-matching scope is patient-level, with "Patient-level SMART scopes are not supported for this request." The scopes below are documented for completeness with the SMART spec — use the user-level scopes for a working client today.

ScopeDescription
patient/*.readRead all patient compartment resources
patient/*.writeWrite all patient compartment resources
patient/*.*Full read/write access to patient compartment
patient/Patient.readRead Patient demographics
patient/Observation.readRead Observations (labs, vitals, etc.)
patient/Condition.readRead Conditions (diagnoses)
patient/MedicationRequest.readRead medication orders
patient/AllergyIntolerance.readRead allergies
patient/Immunization.readRead immunization history
patient/DiagnosticReport.readRead diagnostic reports
patient/Procedure.readRead procedures
patient/DocumentReference.readRead clinical documents
patient/CarePlan.readRead care plans
patient/Goal.readRead patient goals
patient/Encounter.readRead encounter history

2. User-Level Scopes​

Access data across all patients the user has access to:

ScopeDescription
user/*.readRead all resources the user can access
user/*.writeWrite all resources the user can access
user/*.*Full read/write access for the user
user/Patient.readRead all patients user can access
user/Observation.readRead all observations user can access
user/Practitioner.readRead practitioner information
user/Organization.readRead organization information

3. System-Level Scopes​

Access for backend services (Client Credentials flow):

ScopeDescription
system/*.readRead all resources (backend access)
system/*.writeWrite all resources (backend access)
system/*.*Full read/write system access
system/Patient.readRead all patients (no user context)
system/Observation.readRead all observations (no user context)

4. Launch Scopes​

Control launch context and behavior:

ScopeDescription
launchRequired for EHR launch flow
launch/patientRequest patient picker for standalone launch
launch/encounterRequest encounter context
online_accessRequest refresh token for long-term access
offline_accessRequest refresh token for offline/background access

5. OpenID Connect Scopes​

Standard OIDC scopes for user identity:

ScopeDescription
openidRequired for OIDC authentication
profileUser's name, picture, etc.
emailUser's email address
fhirUserFHIR resource representing the user (Patient, Practitioner, etc.)

Token Response with Context​

When using SMART on FHIR, the token response includes additional context information:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "patient/Patient.read patient/Observation.read",
"patient": "Patient/123",
"encounter": "Encounter/456",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Context Parameters:

ParameterDescriptionExample
patientFHIR Patient resource IDPatient/123
encounterCurrent encounter contextEncounter/456
fhirUserFHIR resource for authenticated userPractitioner/789 or Patient/123
tenantTenant identifier (if multi-tenant)org-acme-health
need_patient_bannerWhether to show patient bannertrue
intentLaunch intent (reconcile-medications, etc.)reconcile-medications

SMART Configuration Discovery​

Applications discover SMART capabilities via the .well-known endpoint, scoped to a tenant and project:

Request:

GET /w/{tenant}/{project}/api/v1/fhir/.well-known/smart-configuration HTTP/1.1
Host: api.haste.health

Response:

{
"issuer": "https://api.haste.health",
"authorization_endpoint": "https://api.haste.health/w/{tenant}/{project}/api/v1/oidc/auth/authorize",
"token_endpoint": "https://api.haste.health/w/{tenant}/{project}/api/v1/oidc/auth/token",
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"scopes_supported": [
"openid",
"profile",
"email",
"offline_access",
"fhirUser",
"user/*.cruds",
"system/*.cruds"
],
"response_types_supported": [
"code",
"id_token",
"id_token token"
],
"capabilities": [
"sso-openid-connect",
"client-confidential-symmetric",
"launch-standalone",
"permission-user",
"permission-v2"
],
"code_challenge_methods_supported": [
"S256"
],
"grant_types_supported": [
"authorization_code",
"client_credentials"
]
}

registration_endpoint is omitted entirely (dynamic client registration isn't supported — register a ClientApplication resource directly instead; see Client Registration).

SMART Capabilities​

Supported Capabilities​

Haste Health currently advertises exactly these five SMART capabilities — no others are included in capabilities, even ones a SMART server commonly supports:

CapabilityDescriptionSupported
sso-openid-connectOpenID Connect on top of OAuth 2.0✅ Yes
client-confidential-symmetricConfidential clients with a shared secret✅ Yes
launch-standaloneStandalone launch✅ Yes
permission-useruser/* scopes✅ Yes
permission-v2SMART v2 scope syntax✅ Yes

Not currently advertised or supported: launch-ehr (see the caution box above), client-public, context-ehr-*, context-standalone-*, permission-patient, and permission-offline. If your app depends on any of these, confirm it against the live discovery document for your server rather than assuming.

Common Use Cases​

Patient Portal​

// Patient viewing their own data
scope: 'openid profile patient/Patient.read patient/Observation.read patient/Condition.read patient/MedicationRequest.read online_access'

Clinical Decision Support​

// CDS app launched from EHR
scope: 'launch patient/Patient.read patient/Observation.read patient/Condition.read patient/MedicationRequest.read patient/AllergyIntolerance.read'

Population Health​

// Analytics dashboard for clinicians
scope: 'openid profile user/Patient.read user/Observation.read user/Condition.read user/Encounter.read'

Research Data Export​

// Backend system for de-identified data
scope: 'system/Patient.read system/Observation.read system/Condition.read system/Procedure.read'

Resources​