OAuth & Authentication
Proxy Smart acts as an OAuth 2.0 / OpenID Connect proxy between SMART apps and Keycloak. All authentication traffic flows through the /auth endpoints, which validate, enrich, and forward requests to the underlying Keycloak realm.
Architecture
SMART App ──► /auth/authorize ──► Keycloak /auth endpoint
│
SMART App ◄── redirect with code ◄────┘
SMART App ──► /auth/token ──► Keycloak /token endpoint
│
SMART App ◄── access_token ◄────────┘
SMART App ──► /proxy-smart/… ──► FHIR Server (with validated token)Endpoints
Discovery
| Endpoint | Description |
|---|---|
GET /auth/.well-known/openid-configuration | Proxies Keycloak's OIDC discovery metadata |
GET /auth/.well-known/oauth-authorization-server | OAuth 2.0 AS Metadata (RFC 8414) |
GET /auth/config | Returns Keycloak connectivity status and realm info |
GET /.well-known/oauth-protected-resource | RFC 9728 Protected Resource Metadata for MCP clients |
GET /.well-known/jwks.json | JSON Web Key Set for token verification |
Authorization Flow
| Endpoint | Description |
|---|---|
GET /auth/authorize | Redirects to Keycloak's authorization endpoint |
GET /auth/login | Simplified login redirect with sensible defaults for UI apps |
GET /auth/logout | Proxies logout to Keycloak with id_token_hint and redirect |
GET /auth/identity-providers | Public list of enabled identity providers for login pages |
Token Operations
| Endpoint | Description |
|---|---|
POST /auth/token | Proxies token requests to Keycloak (authorization code, refresh, client credentials) |
POST /auth/introspect | Token introspection with SMART launch context enrichment |
GET /auth/userinfo | UserInfo endpoint with authorization_details generation |
Dynamic Client Registration
| Endpoint | Description |
|---|---|
POST /auth/register | RFC 7591 Dynamic Client Registration |
Authorization Flow Details
SMART App Launch
App redirects to
/auth/authorizewith standard OAuth parameters plus SMART-specific:aud-- the FHIR server URL the app wants to access (validated against configured servers)scope-- SMART scopes likelaunch/patient patient/*.read openid fhirUserlaunch-- EHR launch token (for EHR launch flow)
Audience validation -- the proxy validates the
audparameter matches a configured FHIR endpoint, preventing token leakage to unauthorized servers (SMART App Launch 2.2.0 requirement).Keycloak handles authentication -- user logs in, consents to scopes, Keycloak redirects back with an authorization code.
App exchanges code at
/auth/token-- the proxy forwards the token request to Keycloak. The response includes SMART launch context claims (patient, encounter, fhirUser) injected by Keycloak scope mappers.
Supported Grant Types
| Grant Type | Use Case |
|---|---|
authorization_code | Standard SMART App Launch (EHR and standalone) |
refresh_token | Token refresh |
client_credentials | Backend Services (with JWT client assertion) |
password | Resource Owner Password (admin tools only) |
| Token Exchange (RFC 8693) | Subject token exchange for delegated access |
Backend Services
For system-to-system access without user interaction:
- Uses
client_credentialsgrant withclient_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer - Client authenticates with a signed JWT containing
system/*.readscopes - No user context -- suitable for bulk data, analytics, and integration engines
Token Introspection
POST /auth/introspect enriches Keycloak's introspection response with SMART-specific fields:
- Generates
authorization_detailsfrom token claims and configured FHIR servers - Includes FHIR server locations, versions, patient context, and granted scopes
- Follows the SMART on FHIR authorization details type (
smart_on_fhir)
UserInfo
GET /auth/userinfo returns the standard OIDC UserInfo response plus authorization_details generated from the token's SMART claims and configured FHIR server endpoints.
Keycloak Unavailability
If Keycloak is unreachable when a user tries to authenticate, the proxy returns a friendly HTML error page (HTTP 503) with a retry button instead of a raw browser connection error. This applies to /auth/authorize and /auth/login.
Environment Variables
| Variable | Description | Default |
|---|---|---|
KEYCLOAK_BASE_URL | Internal Keycloak URL | -- |
KEYCLOAK_PUBLIC_URL | Browser-facing Keycloak URL (if different from internal) | derives from KEYCLOAK_BASE_URL |
KEYCLOAK_REALM | Keycloak realm name | -- |
KEYCLOAK_ADMIN_CLIENT_ID | Service account client ID for admin API calls | -- |
KEYCLOAK_ADMIN_CLIENT_SECRET | Service account client secret | -- |
KEYCLOAK_DOMAIN | Domain override for public URL generation | -- |