Your app, one click from the chart
HealthOS is a SMART App Launch 2.2 server. A clinician opens your app from the Apps menu on a person’s chart and it arrives knowing the patient and the encounter. Patients and families can sign in to the same app through HealthOS Connections. Either way, the token reaches only as far as that person’s own access.
In short
- Discovery at
/.well-known/smart-configuration, data at/fhir. - Authorisation code flow with PKCE (S256), and a consent screen the user approves.
- Clinicians sign in with HealthOS. Patients and families sign in with HealthOS Connections.
- An ID token, signed and verifiable against our published keys, says who signed in.
Step by step: Launch a SMART app from the chart and connect a patient or family app, with screenshots of each step.
Registering your app
Each provider registers your app in their own HealthOS, from the admin portal. They need your redirect URIs, the scopes you ask for and, for a launch from the chart, your launch URL. They also choose who signs in: clinicians, patients and families, or both. Registration returns a client id for that organisation.
| Client type | Use it for | How it authenticates |
|---|---|---|
| Public | Browser and mobile apps that can’t keep a secret | PKCE only |
| Confidential, asymmetric | Apps with a back end, and backend services | A JWT signed with your private key, checked against your JWKS URL |
| Confidential, symmetric | Apps with a back end that use a shared secret | A client secret, shown once and rotatable |
A launch URL must be https. A secret is shown once, when it is created or rotated, and is stored only as a hash.
Launching from the chart
The provider’s administrator decides where your app appears: in the chart header, where it opens with the person, in the encounter view, where it opens with the person and the encounter, or both. They can limit it to certain roles and add your logo. Clinicians who may launch apps then see it in the Apps menu.
When a clinician picks your app, HealthOS records the launch context against your app and that clinician, signs them in to the authorisation server, and opens your launch URL in a new tab:
https://app.example.com.au/launch?iss=https://{your HealthOS host}/fhir&launch=8c2f…
Your app reads the SMART configuration from iss and sends the user to authorise, passing the launch value back with the launch scope:
GET /smart/authorize?response_type=code
&client_id={client id}
&redirect_uri=https://app.example.com.au/callback
&scope=launch openid fhirUser patient/Observation.rs patient/Condition.rs
&launch=8c2f…
&state={random}&nonce={random}
&aud=https://{your HealthOS host}/fhir
&code_challenge={S256 challenge}&code_challenge_method=S256
The clinician is already signed in, so they go straight to the consent screen, which shows your app’s name and what it asks for. Only an explicit Allow issues a code. A launch id works once, for your app and that clinician, and aud must name this server’s FHIR base. Every launch is audited: who, which app and which person.
Standalone launch
Without a launch value, ask for launch/patient and the user picks the patient after signing in. A clinician’s picker shows only people in their organisation, and the choice is checked again when the code is issued. Encounter context comes only with a launch from the chart.
Apps for patients and families
Register the app with patients and families as the people who sign in. Start a standalone launch as above. HealthOS sends the user to HealthOS Connections to sign in, then shows a consent screen listing only the people they may act for: themselves, and anyone they hold active access for, such as a parent whose enduring power of attorney they hold. The person they choose comes back as patient in the token response.
- Only
patient/scopes can be granted, withopenid,fhirUser,offline_accessandlaunch/patient. User, system and EHR launch scopes are refused. - When the family’s access is withdrawn, the refresh token stops working.
- Public clients with PKCE work, so a mobile app needs no secret.
Scopes
| Scope | Grants |
|---|---|
patient/… | Reads and writes within the one patient in the launch context, and nothing outside their record |
user/… | Reads and writes limited to what the signed-in clinician can already do in HealthOS |
system/… | Backend services only, through the client credentials grant (see FHIR for systems) |
launch, launch/patient, launch/encounter | Launch context in the token response |
openid, fhirUser | An ID token saying who signed in |
offline_access, online_access | A refresh token |
Both forms work. For reading, patient/Observation.read or patient/Observation.rs. For writing, patient/Observation.write or patient/Observation.cu. A v2 scope can carry a filter, for example patient/Observation.rs?category=vital-signs. Ask for the narrowest scopes your app needs, because the user sees every one of them on the consent screen. How writes land in the record is on the FHIR for systems page.
Tokens
Exchange the code at /smart/token. The response carries the access token, the granted scope, the patient and encounter ids from the launch and, when you asked for openid, an id_token.
- Access tokens last an hour. Refresh tokens last a day.
/smart/revokerevokes a token, and revoking a refresh token ends every access token minted from it.- A SMART token works at
/fhirand nowhere else. It is not a HealthOS session, so it cannot reach the staff API or HealthOS Connections.
Who signed in
Ask for openid fhirUser and the token response includes an OpenID Connect ID token, signed RS256. Verify it against the keys at /smart/jwks.json. The OpenID configuration is at /fhir/.well-known/openid-configuration.
| Claim | Carries |
|---|---|
iss | The FHIR base URL, the same as the launch iss |
sub | A stable id for the person who signed in |
aud | Your client id |
nonce | The nonce you sent to /smart/authorize |
auth_time, iat, exp | When they signed in, when the token was issued, and an expiry an hour later |
fhirUser | A FHIR URL you can read: Practitioner/… for a clinician, Patient/… for a patient, RelatedPerson/… for a carer |
Signing keys rotate on a schedule. The previous key stays published until the tokens it signed have expired, so cache the key set but refetch it when you see a kid you don’t know.
What a token can see
The rules that apply to a person in HealthOS apply to your app. A token is bound to one organisation. A patient token is held to that patient’s record by the server, whatever query your app sends. A user token is held to the clinician’s own access. Every read and write is logged against your app and the person it acted for.
Other routes
Show us your app
We’ll register it in a test organisation so you can launch it from a real chart, and sign in as a family member, with invented people.
