Retrieve the SMART configuration by fetching {base}/.well-known/smart-configuration (or {base}/metadata) to get the authorization and token endpoint URLs.
Redirect the user to the authorization endpoint with response_type=code, client_id, redirect_uri, scope (e.g. openid fhirUser patient/*.read launch/patient), state, and PKCE parameters (code_challenge, code_challenge_method=S256).
Handle the redirect back to your redirect_uri, validate the returned state parameter, then exchange the authorization code for tokens at the token endpoint using grant_type=authorization_code and the PKCE code_verifier.
Extract the access_token, token_type, expires_in, and the patient context value (patient) from the token response JSON.
Attach the access token as a Bearer token in the Authorization header of subsequent FHIR requests, scoped to the returned patient context.
Implement token refresh using the refresh_token grant before expiry to maintain long-lived sessions without re-prompting the user.
Known gotchas
Scope syntax differs slightly between SMART v1 (patient/*.read) and SMART v2 (patient/*.rs using granular scopes); confirm which version the server implements via the smart-configuration smartCapabilities array.
Public clients must use PKCE; confidential clients should use client_secret or asymmetric JWT client authentication—never embed a client_secret in a browser or mobile app.
Token introspection or server-side validation of the access token is required if your backend accepts tokens from external apps; do not trust token payloads without verification.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp