Observance Solutions
Interoperability

FHIR OAuth 2.0 for Backend Systems: SMART Backend Services Explained

Observance Solutions Engineering7 min read

System-to-system FHIR access — no user in the loop — uses a different OAuth flow than patient- or provider-facing apps. Here's how SMART Backend Services authentication actually works.

Why backend systems need a different auth flow

Most FHIR authentication guides describe the SMART App Launch flow: a user (patient or provider) logs in, is redirected through an authorization screen, and an app receives a token scoped to that user's session. That model doesn't work for backend, system-to-system integration — a scheduled job or an automated agent that needs to read FHIR data has no user to redirect and no browser to complete a login in.

SMART Backend Services (part of the SMART App Launch IG) defines an OAuth 2.0 flow designed for exactly this case, based on the JWT Bearer grant from RFC 7523. Instead of a user consenting interactively, the app proves its identity cryptographically using a private key it holds, and the authorization server (Epic, Oracle Health, etc.) issues an access token directly.

How the flow works

The app registers with the EHR vendor ahead of time and provides a public key (or a URL hosting a JWKS — JSON Web Key Set — document containing that public key). The vendor's authorization server stores this and associates it with a client ID.

To get an access token, the app builds a signed JWT (the 'client assertion') containing standard claims — issuer and subject both set to the client ID, audience set to the token endpoint URL, a unique JWT ID, and a short expiration — and signs it with its private key. This JWT is POSTed to the token endpoint along with `grant_type=client_credentials` and `client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer`.

The authorization server verifies the signature using the public key it has on file (fetching it live from the JWKS URL, if that's how the app registered), checks the claims and expiration, and — if everything validates — returns a standard OAuth access token. That token is then used as a normal Bearer token on subsequent FHIR API calls, scoped to whatever permissions were granted during app registration.

Raw public key vs. hosting a JWKS endpoint

EHR vendors typically support two ways to register your public key: pasting the raw JWK directly into the app registration, or providing a URL that serves a JWKS document. Hosting a JWKS endpoint is generally the better long-term choice — it lets you rotate keys without a manual re-registration step (you update what the endpoint serves, and the vendor picks up the new key on its next fetch), and it's straightforward to implement as a simple unauthenticated GET endpoint that derives the public JWK from your private key at request time.

Mistakes that cause hard-to-debug auth failures

A mismatched `kid` (key ID) between the JWT header and the JWKS document is one of the most common causes of a token request failing — the authorization server can't match the signature to a known key. The `kid` in your signed JWT's header must exactly match the `kid` on the corresponding key in your published JWKS.

Client assertion JWTs typically must expire quickly — Epic, for example, enforces a maximum assertion lifetime of a few minutes. Generating the assertion too far in advance of use, or reusing an old one, produces an opaque 'invalid_client' error rather than a clear expiration message.

Sandbox propagation delay is worth budgeting for: after registering an app or changing its configuration (client ID, JWKS URL), it can take up to roughly an hour for the change to propagate through a vendor's sandbox environment. An 'invalid_client' error immediately after registration is often this, not a configuration bug — worth re-testing before assuming something is wrong with your implementation.

FAQ

Quick answers

System-to-system FHIR access where no user is present to complete an interactive login — scheduled jobs, backend integration services, and automated agents that need to read or write FHIR data on a recurring or event-triggered basis, rather than in response to a logged-in user's session.

Have a project like this in mind?

Tell us what you're building. A senior healthcare technologist — not a salesperson — will get back to you within one business day.