Class EhrLaunchProvider
- All Implemented Interfaces:
SmartAuthProvider
SmartAuthProvider strategy for the SMART App Launch 2.0 EHR launch flow -
the case where an EHR (or an EHR simulator such as ehr.smartforms.io) launches an
app with an opaque or base64-JSON launch token, rather than the app being started
standalone the way FormLoginPkceProvider drives it.
Exposed via three static factories rather than one constructor, because "drive the whole interactive walk" and "an authorization code/token was already obtained out-of-band" are genuinely different call shapes that share the same launch-context decoding logic:
preAuthorizedToken(String)- zero HTTP calls; wrap an already-obtained token response (e.g. captured from a manual browser walk through an EHR launcher, or a debug proxy) and just decode its launch context.#preAuthorizedCode(String, String, String, String, String, String)- one HTTP call (the token POST); exchange an authorizationcodeobtained out-of-band (e.g. captured from the redirect URL right after a human clicks through a login/consent screen once).#fullWalk(String, String, String, String, String, String, AuthorizePageHandler)- the full walk: discovery, authorize, an optional pluggable interactive-step handler (seeAuthorizePageHandler), then token exchange.
Why aud is sent on the authorize request here but not by FormLoginPkceProvider: SMART App Launch's EHR-launch flow mandates
aud=<iss> on the authorize request (audience-binding the auth request to the resource
server). This is a real behavioural difference from FormLoginPkceProvider, not an
oversight to copy - that class drives a standalone launch against a target that
doesn't enforce it.
Deviation from a browser-driven login: fullWalk is deliberately a
best-effort, explicitly-bounded path, not a generic "solve any login page" abstraction -
see AuthorizePageHandler's Javadoc. preAuthorizedToken(String) and
#preAuthorizedCode(String, String, String, String, String, String) are the
primary, always-reliable paths for targets with an interactive authorize screen this
module can't drive; no headless-browser dependency is used or proposed here.
The obtained token (and its launch context) is cached for the lifetime of a provider
instance, the same as FormLoginPkceProvider: obtainAccessToken() only
runs its flow once, on first call. Construct a new instance to force a fresh run.
-
Method Summary
Modifier and TypeMethodDescriptionstatic EhrLaunchProviderfullWalk(String iss, String launch, String clientId, String clientSecret, String redirectUri, String scopes, String codeVerifier, AuthorizePageHandler interactiveHandler) Mode 2: drive the full EHR-launch walk - discovery, authorize, an optional pluggable interactive-step handler, then token exchange.The SMART launch context (patient/encounter/fhirContext/etc.) associated with the obtained token, for strategies that support SMART launch context - seeEhrLaunchProvider, whose EHR-launch flow returns launch-context alongside the access token.Obtain an access token, running whatever flow this strategy implements.static EhrLaunchProviderpreAuthorizedCode(String iss, String code, String clientId, String clientSecret, String redirectUri, String codeVerifier, String tokenEndpointOverride) Mode 1b: exchange an authorizationcodeobtained out-of-band (e.g. captured from the redirect URL immediately after a human clicks through a login/consent screen once - codes are typically short-lived, so this needs to be scripted) for a token.static EhrLaunchProviderpreAuthorizedToken(String tokenResponseJson) Mode 1a: wrap an already-obtained token response and just decode its launch context.static EhrLaunchProviderstandaloneLaunch(String iss, String clientId, String clientSecret, String redirectUri, String scopes, String codeVerifier, AuthorizePageHandler interactiveHandler) Mode 2b: drive a standalone launch - likefullWalk(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.fhirfrog.frog.smart.AuthorizePageHandler), but with nolaunchtoken at all.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.fhirfrog.frog.smart.SmartAuthProvider
asRequestInterceptor
-
Method Details
-
preAuthorizedToken
Mode 1a: wrap an already-obtained token response and just decode its launch context. Makes no HTTP calls at all - the cleanest, always-works path when a human (or an existing tool) has already driven the real browser through an EHR launcher once and captured the resulting token response.- Parameters:
tokenResponseJson- the full JSON body returned by the SMART token endpoint
-
preAuthorizedCode
public static EhrLaunchProvider preAuthorizedCode(String iss, String code, String clientId, String clientSecret, String redirectUri, String codeVerifier, String tokenEndpointOverride) Mode 1b: exchange an authorizationcodeobtained out-of-band (e.g. captured from the redirect URL immediately after a human clicks through a login/consent screen once - codes are typically short-lived, so this needs to be scripted) for a token. Exercises this module's own token-exchange logic end-to-end without ever needing to render or drive a login page.- Parameters:
iss- the SMART server's FHIR base URL (resource server / issuer), used for discovery; may benulliftokenEndpointOverrideis givencode- the authorization code to exchangeclientId- the OAuth2 client id the code was issued toclientSecret- the client secret, for a confidential client - sent as HTTP Basic auth on the token request;nullfor a public/PKCE-only clientredirectUri- the redirect URI the code was issued forcodeVerifier- the PKCE code verifier used to obtain the code, ornullif PKCE wasn't used for ittokenEndpointOverride- the token endpoint to POST to directly, ornullto discover it fromiss's smart-configuration
-
fullWalk
public static EhrLaunchProvider fullWalk(String iss, String launch, String clientId, String clientSecret, String redirectUri, String scopes, String codeVerifier, AuthorizePageHandler interactiveHandler) Mode 2: drive the full EHR-launch walk - discovery, authorize, an optional pluggable interactive-step handler, then token exchange. SeeAuthorizePageHandler's Javadoc for what it can and can't help with.- Parameters:
iss- the SMART server's FHIR base URL (resource server / issuer)launch- the EHR-supplied launch token (opaque or base64-JSON)clientId- the OAuth2 client idclientSecret- the client secret, for a confidential client - sent as HTTP Basic auth on the token request;nullfor a public/PKCE-only clientredirectUri- the redirect URI registered for that clientscopes- space-separated scope string; must includelaunchcodeVerifier- a PKCE code verifier, ornullto generate a random one the same wayFormLoginPkceProviderdoesinteractiveHandler- handles an interactive (200HTML) authorize-page response, ornullif the target auto-approves and never shows one - in which case an interactive response fails fast rather than hanging
-
standaloneLaunch
public static EhrLaunchProvider standaloneLaunch(String iss, String clientId, String clientSecret, String redirectUri, String scopes, String codeVerifier, AuthorizePageHandler interactiveHandler) Mode 2b: drive a standalone launch - likefullWalk(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.fhirfrog.frog.smart.AuthorizePageHandler), but with nolaunchtoken at all. For servers advertising thecontext-standalone-patientcapability (patient context is negotiated during authorize itself, e.g. via a patient-picker or a pre-selected default for the client, rather than being handed to the app up front by an EHR). Aidbox is a concrete example: its smart-configuration lists bothlaunch-ehrandcontext-standalone-patient, and unlike a true EHR-launch, nothing has to mint alaunchid for this path first.- Parameters:
iss- the SMART server's FHIR base URL (resource server / issuer)clientId- the OAuth2 client idclientSecret- the client secret, for a confidential client - sent as HTTP Basic auth on the token request;nullfor a public/PKCE-only clientredirectUri- the redirect URI registered for that clientscopes- space-separated scope string (typically includeslaunch/patientrather thanlaunch)codeVerifier- a PKCE code verifier, ornullto generate a random oneinteractiveHandler- handles an interactive (200HTML) authorize-page response, ornullif the target auto-approves
-
obtainAccessToken
Description copied from interface:SmartAuthProviderObtain an access token, running whatever flow this strategy implements.- Specified by:
obtainAccessTokenin interfaceSmartAuthProvider- Returns:
- the raw access token string (e.g. a JWT), suitable for use as
Authorization: Bearer <token>
-
launchContext
The SMART launch context (patient/encounter/fhirContext/etc.) associated with the obtained token, for strategies that support SMART launch context - seeEhrLaunchProvider, whose EHR-launch flow returns launch-context alongside the access token.A default method rather than an addition to the interface's required contract, so existing strategies that don't carry launch context (
FormLoginPkceProvider,StaticTokenProvider) are unaffected and simply returnOptional.empty().Triggers
obtainAccessToken()if the flow hasn't run yet, since the launch context is decoded from the same token-endpoint response as the access token.- Specified by:
launchContextin interfaceSmartAuthProvider- Returns:
- the launch context, or
Optional.empty()if this strategy doesn't have one
-