Bring Your Own Identity
Not yet available — preview specification. Bring Your Own Identity (BYOI) is an early-access capability that has not shipped yet. The POST /link/par endpoint described below is not currently live, and this page is a preview specification subject to change. The endpoint, request shape, and supported credential service providers may change before general availability. To register interest or get notified when BYOI launches, contact partnerships@flexpa.com.
Bring Your Own Identity lets partners that already operate IAL2 identity-proofing infrastructure — for example CLEAR, ID.me, or Persona — reuse that work when launching Flexpa Consent. Instead of redirecting the patient through Flexpa's own identity step, your backend submits the credential service provider's signed ID token to Flexpa over a server-to-server Pushed Authorization Request (RFC 9126) and receives a one-shot request_uri it can launch Consent with. The patient lands inside the flow already identity-proofed and proceeds directly to facility selection.
#How it works
- Your backend proofs the patient with your credential service provider (CSP) and receives an IAL2 ID token. This step is out of scope for Flexpa.
- Your backend POSTs the OAuth parameters and the CSP-issued ID token to
/link/par.
- Flexpa verifies the token signature against the CSP's JWKS, checks the IAL2 claims, and stores the authorization parameters under a single-use
request_uri.
- Your application redirects the patient's browser to
/oauth/authorize with the request_uri returned by Flexpa.
- Flexpa consumes the
request_uri, skips its own identity step, and starts the consent workflow with the patient's verified demographics already populated.
- The patient proceeds through TEFCA discovery, selects a facility, and is redirected back to your
redirect_uri with an authorization code.
- Your backend exchanges the code at
/oauth/token for a Patient Access Token — the same exchange used by any other Consent flow.
The CSP is selected automatically by Flexpa from the iss claim of the submitted ID token. There is no separate idp parameter — submitting a token from a CSP that is not on the server-side allowlist is rejected with invalid_token.
#What you need
- A pair of API Keys from the Flexpa Portal with BYOI enabled on the application. BYOI is gated per-application; contact partnerships@flexpa.com to enable it.
- A TEFCA license on your application.
- An existing relationship with a supported credential service provider — CLEAR, ID.me, or Persona — that can issue an IAL2 ID token for the patient.
- A
redirect_uri registered in the Flexpa Portal.
#The CSP-issued ID token
The ID token your CSP issues for the patient must be a signed JWT and must carry the claims Flexpa needs to assert IAL2 identity proofing. Flexpa runs the same validation here as it does on the standard CLEAR, ID.me, and Persona callbacks.
Required claims
- issstringRequired
The CSP's issuer URL. Used to select the JWKS for signature verification and to route the request. Must be on Flexpa's server-side allowlist.
- substringRequired
The CSP's stable identifier for the patient.
- audstringRequired
The audience the CSP issued the token for. Must equal the healthcare identifier (HCID) assigned to your application by Flexpa.
- acrstringRequired
The Authentication Context Class Reference asserting IAL2. Must contain ial/2.
- auth_timenumberRequired
Unix time at which the patient was authenticated by the CSP. Tokens older than the configured freshness window (30 minutes by default) are rejected.
- given_namestringRequired
The patient's given (first) name.
- family_namestringRequired
The patient's family (last) name.
- birthdatestringRequired
The patient's date of birth in YYYY-MM-DD format.
- jtistring
Unique token identifier. Used by Flexpa for replay protection.
Flexpa accepts the CSP-issued ID token via the standard OpenID Connect id_token_hint parameter. Token signatures are verified against the CSP's published JWKS using RS256 or ES256.
Decoded ID token (example)
{
"iss": "https://idp.clearme.com",
"sub": "auth0|68d2…",
"aud": "hcid_flexpa_application_id",
"acr": "urn:clear:ial/2",
"auth_time": 1719240000,
"jti": "c4f9a1e2-7c4d-4d6e-8f3a-1b2c3d4e5f60",
"given_name": "Jane",
"family_name": "Doe",
"birthdate": "1985-04-12",
"iat": 1719240000,
"exp": 1719243600
}
#Supported credential service providers
Flexpa routes incoming tokens by the iss claim against a server-side allowlist. At launch, BYOI supports the same three CSPs the standard Flexpa Consent identity step uses:
| Issuer | Provider | JWKS |
|---|
https://idp.clearme.com | CLEAR | https://idp.clearme.com/.well-known/jwks.json |
https://api.id.me | ID.me | https://api.id.me/oidc/.well-known/jwks |
https://withpersona.com | Persona | https://withpersona.com/.well-known/jwks.json |
If you operate your own IAL2 proofing pipeline and would like to assert identity with a partner-signed token, contact partnerships@flexpa.com.
#Pushed Authorization Request
Submit the OAuth authorization parameters along with the CSP-issued ID token. Flexpa verifies the token, stores the parameters, and returns a one-shot request_uri you can launch Flexpa Consent with.
The request body is application/x-www-form-urlencoded and follows RFC 9126.
Request headers
- AuthorizationstringRequired
HTTP Basic credentials — your publishable key (pk_*) and secret key (sk_*) concatenated with a colon and base64-encoded. The key pair must belong to the application BYOI is enabled on.
- Content-TypestringRequired
Must be application/x-www-form-urlencoded.
Request body
- client_idstringRequired
Your publishable key. Must match the key used in the Authorization header.
- response_typestringRequired
Must be code for the authorization code flow.
- redirect_uristringRequired
Where Flexpa will redirect the patient after authorization. Must be registered in the Flexpa Portal.
- scopestringRequired
Space-separated OAuth scopes. Must include launch/patient. Add offline_access for MULTIPLE usage.
- code_challengestringRequired
The PKCE code challenge (BASE64URL(SHA256(verifier))) generated by your client. See Generate PKCE.
- code_challenge_methodstringRequired
Must be S256.
- id_token_hintstringRequired
The signed IAL2 ID token issued by your credential service provider. See The CSP-issued ID token.
- flexpa_external_idstringRequired
Your application's user identifier for this patient. Used for tracking and correlating authorizations across your system.
- statestring
Opaque value echoed back on the final redirect. Recommended for CSRF protection.
Response fields
- request_uristring
Single-use authorization handle. Pass this to /oauth/authorize to start the consent flow. Format: urn:ietf:params:oauth:request_uri:<id>.
- expires_innumber
Lifetime of the request_uri in seconds. Defaults to 90 seconds.
The request_uri is single-use and short-lived. Launch the patient promptly — typically within seconds of receiving the response. Re-launching after consumption requires a new PAR call with a fresh ID token.
Pushed Authorization Request
PUBLIC_KEY=pk_live_...
SECRET_KEY=sk_live_...
ID_TOKEN=eyJhbGciOiJSUzI1NiIs...
# Base64 encode the credentials
CREDENTIALS=$(echo -n "${PUBLIC_KEY}:${SECRET_KEY}" | base64)
curl -X POST https://api.flexpa.com/link/par \
-H "Authorization: Basic ${CREDENTIALS}" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${PUBLIC_KEY}" \
--data-urlencode "response_type=code" \
--data-urlencode "redirect_uri=https://example.com/callback" \
--data-urlencode "scope=launch/patient" \
--data-urlencode "code_challenge=${CODE_CHALLENGE}" \
--data-urlencode "code_challenge_method=S256" \
--data-urlencode "state=opaque-csrf" \
--data-urlencode "flexpa_external_id=usr_1234" \
--data-urlencode "id_token_hint=${ID_TOKEN}"
Response — 201 Created
{
"request_uri": "urn:ietf:params:oauth:request_uri:4c7f0f56-2bb4-4b9b-9d6e-9b1a8a7f2d10",
"expires_in": 90
}
#Launch with a request_uri
Once you have a request_uri, redirect the patient's browser to Flexpa Consent's authorization endpoint with request_uri and client_id query parameters. Flexpa consumes the stashed parameters atomically — the same request_uri cannot be reused.
Query parameters
- client_idstringRequired
Your publishable key. Must match the key the request_uri was issued for.
- request_uristringRequired
The request_uri returned from /link/par.
Because the OAuth parameters were already pushed to Flexpa, you do not need to repeat redirect_uri, scope, code_challenge, or state on this redirect. They are read from the stashed PAR record.
The request_uri is consumed on first use. If the patient closes the tab or you need to re-launch, your backend must issue a fresh PAR with a new ID token.
URL
https://api.flexpa.com/oauth/authorize
?client_id=pk_live_...
&request_uri=urn:ietf:params:oauth:request_uri:4c7f0f56-...
JavaScript
const params = new URLSearchParams({
client_id: 'pk_live_...',
request_uri: requestUri,
});
window.location = `https://api.flexpa.com/oauth/authorize?${params}`;
#Errors
Errors on /link/par follow the OAuth 2.0 error response format (RFC 6749 §5.2). The HTTP status code and error field together identify the failure mode; error_description carries a human-readable detail.
Error responses
- invalid_client401
Missing or invalid HTTP Basic credentials, or the keys do not match a known application. Also returned when a test-mode key is paired with a live-mode redirect URI (or vice versa).
- unauthorized_client403
The application exists but does not have BYOI enabled, or does not hold a TEFCA license. Contact partnerships@flexpa.com.
- invalid_request400
One or more OAuth parameters are missing, malformed, or unsupported — for example an unregistered redirect_uri, a missing code_challenge, or a code_challenge_method other than S256.
- invalid_token400
The id_token_hint failed validation. Common causes include an invalid signature, an iss claim that is not on the allowlist, an aud that does not match your application's HCID, an acr that does not assert IAL2, an auth_time older than the freshness window, an expired token, or a payload missing required demographics (given_name, family_name, birthdate).
Issuer not allowlisted
{
"error": "invalid_token",
"error_description": "issuer not allowlisted"
}
Stale auth_time
{
"error": "invalid_token",
"error_description": "auth_time too old"
}
BYOI not enabled
{
"error": "unauthorized_client",
"error_description": "application is not enabled for BYOI"
}
#Sequence diagram
Partner backend Flexpa /link/par Flexpa /oauth/authorize Patient browser
│ │ │ │
│ (1) proof patient with CSP, receive ID token │ │
│ │ │ │
│ (2) POST OAuth + id_token_hint │ │
├───────────────────►│ │ │
│ │ verify JWKS sig, │ │
│ │ check IAL2 claims, │ │
│ │ stash params │ │
│ (3) { request_uri, expires_in: 90 } │ │
│◄───────────────────┤ │ │
│ │ │
│ (4) hand request_uri to your frontend │ │
│─────────────────────────────────────────────────────────────────────►│
│ │ (5) GET /oauth/authorize?request_uri=…
│ │◄───────────────────────┤
│ │ consume PAR record, │
│ │ skip identity step, │
│ │ start TEFCA discovery │
│ │ │
│ │ (6) redirect to redirect_uri?code=…
│◄─────────────────────────────────────────────────────────────────────│
│ │
│ (7) POST /oauth/token (authorization_code grant) │
│ → Patient Access Token │
#How BYOI differs from the standard flow
| Aspect | Standard Consent | Bring Your Own Identity |
|---|
| Identity proofing | Patient redirected to a CSP from inside the Flexpa flow | Performed by the partner before launching Flexpa |
| Authorization launch | Browser redirect to /oauth/authorize with query parameters | Server-to-server POST to /link/par, then browser redirect to /oauth/authorize?request_uri=… |
| Authentication | Public client — client_id only | Confidential client — HTTP Basic with pk_*/sk_* |
| Patient identity step | Always shown | Skipped |
| Supported networks | Payer, provider, and TEFCA (IAL2) | TEFCA (IAL2) only at launch |
| Token usage | ONE_TIME or MULTIPLE (with offline_access) | ONE_TIME or MULTIPLE (with offline_access) |
#Next steps
- Review the OAuth Reference for the rest of the SMART on FHIR flow — exchange, refresh, revoke, and introspection are unchanged.
- See the Network guide for an overview of TEFCA and the nationwide exchanges BYOI is scoped to.
- Contact partnerships@flexpa.com to enable Bring Your Own Identity on your application.