SMART on FHIR Explained: App Launch, Scopes and Backend Services
SMART App Launch is how third-party apps plug into EHRs securely. This guide walks through both launch flows, discovery, scopes, PKCE, backend services and how CDS Hooks fits in.
Key takeaways
- SMART App Launch is an HL7 implementation guide that profiles OAuth 2.0 and OpenID Connect so apps can run against any conformant FHIR server without custom integration.
- An EHR launch starts inside the EHR and passes a launch token that carries context; a standalone launch starts from the app and asks the user to pick context such as a patient.
- Apps discover endpoints and capabilities from [base]/.well-known/smart-configuration before starting authorization.
- SMART 2.x requires PKCE with S256, introduces granular scopes, and includes the Backend Services profile for system-to-system access.
- CDS Hooks is a separate HL7 specification that invokes decision support services at points in the clinical workflow and often hands off to SMART apps.
What SMART on FHIR solves
FHIR standardizes the data and the API. It does not, by itself, say how an app proves who it is, how a clinician authorizes it, or how it learns which patient is open in the EHR. Before SMART, every EHR answered those questions differently, so every app needed a custom integration per EHR. SMART App Launch, originally developed by the SMART Health IT project and now maintained as an HL7 implementation guide, standardizes those answers on top of OAuth 2.0 and OpenID Connect.
The result is the closest thing healthcare has to an app platform: a clinician-facing app that implements SMART correctly can, in principle, launch from any EHR that supports it, subject to each EHR's app registration and review process. In the US, ONC certification criteria for standardized API access require SMART support, which is why it is available across major platforms such as Epic and Oracle Health.
Discovery with .well-known/smart-configuration
A SMART client starts by fetching the server's configuration document. It is served relative to the FHIR base URL and lists the authorization and token endpoints, supported scopes, PKCE methods and a list of capabilities.
GET /fhir/r4/.well-known/smart-configuration HTTP/1.1
Host: ehr.example.org
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{
"issuer": "https://auth.example.org",
"authorization_endpoint": "https://auth.example.org/authorize",
"token_endpoint": "https://auth.example.org/token",
"jwks_uri": "https://auth.example.org/.well-known/jwks.json",
"grant_types_supported": ["authorization_code", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["private_key_jwt"],
"scopes_supported": ["openid", "fhirUser", "launch", "launch/patient", "offline_access", "patient/*.rs"],
"capabilities": [
"launch-ehr",
"launch-standalone",
"client-public",
"client-confidential-asymmetric",
"context-ehr-patient",
"context-standalone-patient",
"permission-v2",
"sso-openid-connect"
]
}Read the capabilities array rather than assuming features. For example, permission-v2 indicates support for v2 scope syntax, and context-ehr-patient indicates that patient context is provided during EHR launch.
EHR launch versus standalone launch
| EHR launch | Standalone launch | |
|---|---|---|
| Where it starts | Inside the EHR, e.g. a button or tab in the patient chart | Outside the EHR: a web app, mobile app or patient portal link |
| How context arrives | EHR calls the app's launch URL with iss and an opaque launch parameter | App requests context scopes such as launch/patient and the user selects a patient |
| Typical users | Clinicians in a workflow | Patients using their own apps, or clinicians outside the EHR |
| Required scope | launch | launch/patient, launch/encounter as needed |
In both flows the app then performs an OAuth authorization code flow: it redirects the user to the authorization endpoint with its client_id, redirect_uri, requested scopes, a state value, an aud parameter equal to the FHIR base URL, and a PKCE code_challenge. After the user authenticates and approves, the app exchanges the returned code (plus the PKCE code_verifier) for an access token at the token endpoint.
Launch context in the token response
The token response carries more than the access token. Depending on the scopes granted, it can include patient and encounter ids, an id_token identifying the user (with a fhirUser claim pointing to a Practitioner, Patient or RelatedPerson resource), need_patient_banner to tell the app whether the EHR already shows patient identity, and in SMART 2.x a fhirContext array for additional context resources. The app should use these values rather than asking the user to re-select a patient.
Scopes, PKCE and client types
Scopes describe the access the app wants: clinical data scopes such as patient/Condition.rs, identity scopes such as openid and fhirUser, context scopes such as launch/patient, and offline_access or online_access for refresh tokens. Request the minimum. Many EHRs let users approve a subset, so apps should handle receiving fewer scopes than requested. The FHIR security guide covers scope design in more depth.
- PKCE (Proof Key for Code Exchange) binds the authorization code to the client that requested it. SMART 2.x requires it with the S256 method for all apps.
- Public clients, such as browser-only or native apps, cannot keep a secret and rely on PKCE alone.
- Confidential clients authenticate at the token endpoint. SMART 2.x prefers asymmetric authentication with a signed JWT over a symmetric client secret.
- Validate the state parameter on return and only register exact redirect URIs.
Backend services: SMART without a user
Not every client has a human at the keyboard. Backend Services, included in SMART App Launch 2.x, covers system-to-system access such as nightly analytics loads or Bulk Data exports. The client uses the OAuth client_credentials grant, authenticates with a JWT signed by its registered private key, and requests system/ scopes. Because there is no user consent step, the authorization server relies on pre-registration and policy to decide what each client may access.
Backend services pair naturally with the Bulk Data Access implementation guide, which defines the asynchronous $export operation for population-level extracts. Architecture choices for supporting it are covered in the FHIR server architecture guide.
SMART v1 versus v2
| Area | SMART 1.0 | SMART 2.x |
|---|---|---|
| Scope syntax | .read / .write / .* | .c .r .u .d .s combinations, optional search constraints |
| PKCE | Not required | Required (S256) |
| Client authentication | Client secret common | Asymmetric (private_key_jwt) preferred for confidential clients |
| Backend services | Separate specification | Included in the guide |
| Context | patient, encounter | Adds fhirContext for additional resources |
| Token introspection | Not specified | Defines a SMART profile of token introspection |
Most servers support both during the transition. Apps should read the server's capabilities, prefer v2 where available and degrade gracefully where not.
Common implementation pitfalls
Most SMART projects that slip do so for reasons unrelated to the core OAuth flow. The issues below come up repeatedly when apps move from a sandbox to real EHR environments:
- Hard-coding endpoints. Each EHR customer has its own FHIR base URL and authorization server. Always derive endpoints from the iss value and the discovery document.
- Assuming every requested scope is granted. Inspect the scope value in the token response and disable features gracefully when access is narrower than requested.
- Ignoring token lifetimes. Access tokens are short-lived. Handle refresh, and handle refresh failure by restarting authorization rather than surfacing raw errors to clinicians.
- Embedding in iframes without testing. Some EHRs render apps in embedded browsers with cookie and storage restrictions that break session handling built for normal browsers.
- Skipping production data review. Sandbox data is clean; production data has missing codes, local code systems and unexpected profiles. Build defensively against the resources you actually receive.
For the broader delivery picture, including environments, testing and go-live, see the FHIR implementation guide.
How CDS Hooks relates to SMART
CDS Hooks is a separate HL7 specification for invoking clinical decision support at defined points in the EHR workflow, such as patient-view when a chart opens or order-sign when orders are about to be signed. The EHR calls an external CDS service with context and, optionally, prefetched FHIR data; the service replies with cards containing information, suggestions or links.
The two are complementary. A card can include a link that launches a SMART app with the right context, so a lightweight hook can surface an alert and hand the clinician into a full app for deeper work. The CDS service accesses FHIR data using a token the EHR supplies, following the same OAuth principles.
Building an app?
Specialist SMART on FHIR developers can help with EHR-specific registration, app review and the differences between sandbox and production behaviour.
Frequently asked questions
Is SMART on FHIR the same as FHIR?
No. FHIR defines the data model and API. SMART App Launch is an implementation guide that defines how apps authorize and receive context when calling a FHIR API. Most apps use both together.
Do patient-facing apps use SMART?
Yes. Patient apps typically use a standalone launch, where the patient signs in to a portal-style login, approves scopes, and the app receives patient-scoped access. This is the mechanism behind many patient access APIs.
Why is PKCE required if my app has a client secret?
PKCE protects against authorization code interception, a threat that applies to confidential clients as well as public ones. SMART 2.x requires it for every app so that the protection is consistent.
How does an app know which patient is open in the EHR?
In an EHR launch, the EHR passes an opaque launch parameter. When the app exchanges its authorization code, the token response includes the patient id (and encounter id if requested and available).
Does a SMART app work on every EHR without changes?
The protocol is portable, but each EHR has its own registration process, supported scopes, FHIR resources and data quirks. Expect testing and some per-EHR configuration even for a well-built app.
References
- HL7 SMART App Launch Implementation Guide
- SMART App Launch (current build)
- HL7 Bulk Data Access IG
- CDS Hooks specification
- ONC Inferno test kits
FHIR® is a registered trademark of HL7 International. This guide is independent educational content and is not legal or compliance advice.
Related guides
- FHIR Security Best Practices: Authorization, Audit and API HardeningHow to secure a FHIR API end to end: SMART on FHIR authorization, least-privilege scopes, signed JWT backend authentication, audit logging and the API flaws attackers actually exploit.
- FHIR API Integration: How It Works End to EndA practical walk-through of integrating with a FHIR REST API, from reading the CapabilityStatement to authentication, searching, paging, error handling, rate limits and testing.
- FHIR Implementation: A Phased PlaybookA step-by-step plan for implementing FHIR, from discovery and implementation guide selection through mapping, terminology, testing, go-live and ongoing operations, plus the challenges that derail projects.
- FHIR Resources Explained: Structure, Categories and Key ResourcesA practical tour of FHIR resources: what every resource contains, how they are grouped, the ones you will meet in almost every integration, and how references, maturity levels and profiles fit together.
Related FHIR services
- SMART on FHIRWhat SMART on FHIR development covers: EHR and standalone launch, OAuth scopes, backend services, EHR app marketplace readiness, and how to choose a developer.
- EHR/EMR IntegrationEHR/EMR integration services explained: connecting to Epic, Oracle Health, athenahealth and others via FHIR, HL7 v2 and vendor APIs, and choosing a partner.
- FHIR API DevelopmentHow FHIR API development services design and build compliant FHIR REST APIs: profiles, CapabilityStatements, SMART auth, testing and choosing a capable team.
Find the Right FHIR Integration Partner for Your Healthcare Project
Tell us what you need to build or connect. We review every request and share a short list of relevant vendors from our directory — no obligation.