SMART on FHIR Overview
SMART on FHIR is an open standard for launching healthcare apps securely against FHIR APIs. It defines how apps obtain authorization (scopes) and user context (patient, practitioner) using OAuth 2.0 and OpenID Connect.
Why SMART?
- Standardized app launch flows that work across EHRs and FHIR servers
- Fine-grained permission model using SMART scopes (e.g.,
patient/Observation.rs) - User identity and context via OpenID Connect (
openid,fhirUser,launch/patient) - Security best practices: PKCE, confidential/public clients, redirect URIs
OAuth 2 Flow
┌─────────────┐
│ Client │
│ Application │
└──────┬──────┘
│
│ 1. GET /oauth2/authorize?client_id=X&state=ABC&redirect_uri=...
▼
┌─────────────────────────────────────┐
│ Spring Authorization Server │
│ (Our FHIR Server) │
└─────────────────────────────────────┘
│
│ 2. Check: Is user authenticated?
│ NO → Redirect to /oauth2/login
▼
┌─────────────┐
│ Login Page │ User enters credentials
└──────┬──────┘
│ 3. POST credentials
▼
┌─────────────────────────────────────┐
│ Spring Security Authentication │
│ - Validates credentials │
│ - Creates Authentication object │
│ - Calls SmartOAuthSuccessHandler │
└──────┬──────────────────────────────┘
│
│ 4. SmartOAuthSuccessHandler:
│ - Gets SavedRequest (original /oauth2/authorize URL)
│ - If practitioner + launch/patient → /patient-picker
│ - Otherwise → Redirect to savedUrl (back to /oauth2/authorize)
▼
┌─────────────────────────────────────┐
│ Spring Authorization Server │
│ Processes /oauth2/authorize again │
│ │
│ 5. Check: Is user authenticated? │
│ YES ✓ │
│ │
│ 6. Check: Does client require │
│ consent? │
│ YES → Need consent │
│ │
│ 7. Create OAuth2Authorization with:│
│ - id: random UUID │
│ - state: (consent state) │
│ - Store in OAuth2Authorization │
│ ConsentService │
│ │
│ 8. Redirect to /consent with │
│ state parameter │
└──────┬──────────────────────────────┘
│
▼
┌─────────────┐
│ Consent │ User sees scopes,
│ Page │ clicks "Approve"
└──────┬──────┘
│
│ 9. POST /oauth2/authorize with:
│ - client_id=X
│ - state=ABC (from hidden field)
│ - consent_action=approve
│ - scope=...
▼
┌─────────────────────────────────────┐
│ Spring Authorization Server │
│ Processes consent POST │
│ │
│ 10. Recognize this as consent │
│ approval (has consent_action) │
│ │
│ 11. Look up OAuth2Authorization │
│ by state from step 7 │
│ MATCH FOUND ✓ │
│ │
│ 12. Mark consent as approved │
│ │
│ 13. Generate authorization code │
│ │
│ 14. Redirect to client: │
│ redirect_uri?code=XYZ&state=ABC│
└──────┬──────────────────────────────┘
│
▼
┌─────────────┐
│ Client │ Receives authorization
│ Application │ code, exchanges for token
└─────────────┘
Launch Types
- Patient Standalone: App is launched directly by a patient; scope requests are limited to the patient’s data
- Provider Standalone: App is launched by a clinician; scope requests may include broader access (e.g., all patients)
- EHR Launch (coming soon): App launches within an EHR with additional context (e.g., current patient)
Scopes
- Required baseline scopes:
launch/patient,openid,fhirUser,offline_access - Resource-level read scopes:
patient/<Resource>.rs(e.g.,patient/Observation.rs) - “All Read” convenience:
patient/*.rs
Scopes define what the app can read/write and whether access is constrained to a single patient.
PKCE
- PKCE (Proof Key for Code Exchange) protects public apps (mobile/web) from authorization code interception
- Recommended to keep PKCE enabled with
SHA-256
Clients
- Public clients: no client secret (browser/mobile)
- Confidential clients: client secret required (server-side apps)
Client type influences how tokens are issued and where secrets are stored.
How It Works in Couchbase FHIR CE
- Built-in Spring Authorization Server provides OAuth/OpenID endpoints
- Admin UI includes Client Registration, Patient/Provider Standalone flows, and consent screens
- Registered clients request SMART scopes; users grant consent; tokens carry scopes and user context
Related Pages
- Client Registration: docs/Smart/Client-Registration.mdx
- Inferno SMART Client: docs/Smart/Inferno.mdx
- OAuth Overview: docs/API Tokens/OAuth.mdx