Securing EHR Integrations: OAuth 2.0, SMART on FHIR Launch, Token Scopes and Audit Logging

An integration with an electronic health record system gives software access to some of the most sensitive data an organization holds. The security design therefore cannot wait until the data mapping is finished. It shapes how the app gets its credentials, what the app may read or write, and what trace remains afterward. This article walks through four building blocks that appear in almost every modern EHR integration built on FHIR: OAuth 2.0, the SMART on FHIR launch, token scopes, and audit logging.
Start with the right framework
FHIR itself is not a security protocol. The R4 specification says so directly: it defines how data is exchanged and leaves security functionality to external protocols. For authentication and authorization, the FHIR security guidance points to OpenID Connect for verifying end-user identity, OAuth 2.0 for authorizing clients and users, and the SMART on FHIR profile of OAuth as the recommended combination.
This division has a practical consequence. A FHIR server can be perfectly standard and still be poorly protected, and a team cannot read a conformance statement as a security review. The security properties come from how the authorization server, the app, and the resource server are configured and used.
See also: Mastering Index Technical Analysis for Consistent Profits in India
OAuth 2.0 and the SMART launch
SMART App Launch builds on OAuth 2.0 and adds what health care needs: a way to discover the server’s endpoints, a way to pass clinical context such as the selected patient, and a vocabulary of scopes tied to FHIR resources.
Discovery comes first. The server publishes a configuration document under the well-known path of its FHIR base URL, and the app reads the authorization and token endpoints from it. Hard-coded endpoints are a maintenance problem and a security smell.
The specification then describes two launch styles. In an EHR launch, the EHR opens the app’s registered launch URL, passing the address of the FHIR server and an opaque launch handle. In a standalone launch, the user starts the app outside the EHR, and the app asks for context, typically the patient, through a scope.
Either way, the app sends the user through the authorization code flow. The SMART App Launch specification sets several requirements that integrations should not skip.
PKCE is required. All SMART apps must support it, servers must support the S256 method and must not support the plain method, and the server checks the code verifier when the app exchanges the code for a token.
The state parameter protects the redirect. The app generates an unpredictable value for each session, with at least 122 bits of entropy according to the specification, and validates it on return. That defends against cross-site request forgery and session fixation.
The audience parameter names the FHIR server the app wants to reach, which prevents a genuine token from being sent to a counterfeit server.
The token response carries cache-control headers that forbid storing it, and the specification recommends that access tokens last no more than one hour. Short lifetimes limit the value of a leaked token.
Scopes: ask for the least that works
Scopes decide what an access token can do. In SMART, they are written as a prefix, a resource type, and a set of permitted interactions. The prefix says whose data is in play: the patient in context, whatever the logged-in user can access, or what a backend system can reach without a user. The permissions are drawn from create, read, update, delete, and search. A scope such as patient/Observation.rs, for example, allows reading and searching observations for the patient in context.
The specification’s guidance is blunt: request only the scopes the app needs, avoid wildcards for convenience, and ask a read-only app for read and search, not all five permissions. It adds a second point that teams often miss. The server may grant fewer or different scopes than requested, so the app has to check what it actually received. Otherwise, a missing permission shows up later as an authorization error in the middle of a workflow.
A scope review is worth doing at the same time as a data-flow review. Each scope should map to a feature, and each feature should map to a scope. If a scope has no feature, remove it.
Refresh tokens deserve a decision of their own. The offline_access scope allows a refresh token to outlive the user’s session, and the online_access scope ties it to the user remaining online. A background sync may need the first. An interactive clinician tool may not need a refresh token at all.
Confidential and public clients
Where the app can keep a secret, it should authenticate to the token endpoint. SMART names asymmetric authentication with a private key JWT as the preferred method because it avoids sending a shared secret over the wire. Browser and mobile apps cannot protect a secret and run as public clients, where PKCE and short token lifetimes carry more of the weight.
Backend integrations that run without a user, such as scheduled data synchronization, use the separate SMART Backend Services profile. Their permissions are assigned out of band, which makes the review of those assignments an important control.
Audit logging
Authorization controls who gets in. Audit logging records what happened afterward. The FHIR security guidance describes two resources for this. AuditEvent captures security-relevant and privacy-relevant events and supports audit reporting and alerting. Provenance records who created or changed a resource.
A usable audit trail answers a few plain questions: which user or system accessed which patient’s data, through which app, at what time, and with what result. It should also record failures, such as denied requests and invalid tokens.
The same guidance warns about the logs themselves. HTTP logs that contain URLs can be as sensitive as the resources because search parameters often carry identifying information. Logging pipelines for an integration should keep patient identifiers out of unprotected logs and restrict who can read the audit store. Retention periods and review procedures come from the organization’s own compliance team and its agreements with the health system, not from the integration team.
Bringing it together
A secure EHR integration is less a product than a set of consistent decisions: discover endpoints instead of hard-coding them, use the authorization code flow with PKCE, validate state, bind tokens to the right audience, request narrow scopes, keep token lifetimes short, and record every access in a trail someone can read. Each decision is small. Skipping one of them is what leaves a gap.
Teams that want engineering help with this layer can look at JetRuby, whose healthcare offer is the engineering side of EHR and EMR integrations, not clinical or insurance expertise. Decisions about regulatory requirements remain with the compliance owners of each product.




