Register a backend service client with the FHIR authorization server, providing a JWKS (JSON Web Key Set) URL or public key; obtain the client_id assigned by the server
Construct a JWT client assertion signed with the private key corresponding to the registered public key; include iss, sub (both set to client_id), aud (token endpoint URL), jti (unique nonce), and exp claims
POST to the token endpoint with grant_type=client_credentials, client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer, client_assertion={signed JWT}, and scope=system/*.read (or specific resource scopes)
Parse the JSON response for access_token and expires_in; include the token as Authorization: Bearer {token} on all subsequent FHIR API requests
Repeat the client assertion flow to obtain a fresh token before expiry; do not cache tokens beyond their expires_in value
Known gotchas
The JWT jti claim must be unique per request and must not be reused within the token's validity window; reusing a jti causes the authorization server to reject the request as a replay attack
The aud claim must exactly match the token endpoint URL as registered; subtle differences (trailing slash, http vs https) cause assertion validation failures that appear as generic 401 errors
SMART Backend Services requires asymmetric keys (RSA or EC); symmetric HMAC-signed JWTs are not accepted even if the server would otherwise support them for other grant types
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