SMART App Launch

This section provides step-by-step guides for implementing SMART authorization flows with Safire.

Available Workflows

Workflow Description
SMART Discovery Fetching and using SMART configuration metadata
Dynamic Client Registration Register a client at runtime using RFC 7591 to obtain a client_id
Public Client Authorization flow for browser-based and mobile applications
Confidential Symmetric Client Authorization flow for server-side applications with client secrets
Confidential Asymmetric Client Authorization flow using private_key_jwt (RSA/EC key pair)
POST-Based Authorization Sending the authorization request as a form POST (authorize-post capability)
Backend Services System-to-system token requests using client_credentials grant; no user interaction

Choosing a Workflow

Does your application require a logged-in user?
        │
        ├── YES → App Launch flow (authorization_code grant)
        │         │
        │         Is your application a server-side web app
        │         that can securely store credentials?
        │         │
        │         ├── YES → Can you use asymmetric key pairs (RSA/EC)?
        │         │         │
        │         │         ├── YES → Confidential Asymmetric Client
        │         │         │         (private_key_jwt with signed JWT assertions)
        │         │         │
        │         │         └── NO  → Confidential Symmetric Client
        │         │                   (client_secret with HTTP Basic auth)
        │         │
        │         └── NO  → Public Client
        │                   (PKCE only, no client secret)
        │
        └── NO  → Backend Services (client_credentials grant)
                  (JWT assertion, no redirect or PKCE)

Common Flow

All SMART authorization flows follow this general pattern. The key differences between client types are in how they authenticate during token exchange and refresh.

sequenceDiagram
    participant App
    participant Safire
    participant FHIR as FHIR Server

    App->>Safire: Client.new(config)
    Note over Safire: No network call yet

    App->>Safire: authorization_url()
    Safire->>FHIR: GET /.well-known/smart-configuration
    FHIR-->>Safire: SmartMetadata (endpoints, capabilities)
    Safire-->>App: { auth_url, state, code_verifier }

    App->>FHIR: Redirect user to auth_url
    FHIR-->>App: Callback with ?code=...&state=...

    App->>Safire: request_access_token(code:, code_verifier:)
    Note over Safire: Auth method varies by client_type:<br/>public → client_id in body<br/>confidential_symmetric → Basic auth header<br/>confidential_asymmetric → JWT assertion in body
    Safire->>FHIR: POST /token
    FHIR-->>Safire: { access_token, refresh_token, expires_in, ... }
    Safire-->>App: token response Hash

    App->>Safire: refresh_token(refresh_token:)
    Safire->>FHIR: POST /token (grant_type=refresh_token)
    FHIR-->>Safire: { access_token, ... }
    Safire-->>App: new token response Hash

Table of contents


Back to Top ↑

This site uses Just the Docs, a documentation theme for Jekyll.