> ## Documentation Index
> Fetch the complete documentation index at: https://docs.connect.fastenhealth.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bring Your Own Identity

> Use your own AAL2 authentication and CSP identity-proofing flow with Fasten Connect and TEFCA IAS.

<Danger>There are additional fees involved with TEFCA IAS in `live` mode. Please contact [support@fastenhealth.com](mailto:support@fastenhealth.com) or your [Account Representative](https://calendly.com/jason-kulatunga/30min) for more information.</Danger>

## Overview

Bring Your Own Identity (BYOI) lets your application authenticate the patient at Authenticator Assurance Level 2 (AAL2)
and perform identity proofing with your own supported Credential Service Provider (CSP).

In the standard [TEFCA IAS flow](/guides/tefca-ias), Fasten sends the patient to a CSP such as CLEAR or ID.me and receives
the verified ID Token directly. In BYOI mode, your application owns that CSP experience. Your backend sends a stable
`patient_id` to Fasten's Identity service and receives a short-lived `request_uri` that can be passed into Fasten Stitch so
the patient can complete consent and provider selection.

Fasten uses the `patient_id` as the subject of a short-lived, Fasten-signed client assertion JWT and sends that JWT to your
registered Token Exchange endpoint. Your backend validates the assertion, uses the patient's active CSP authorization
grant to obtain a fresh CSP ID Token, and returns the ID Token to Fasten. Fasten can repeat this exchange when another CSP
ID Token is required during a long-running or later data collection request.

<Note>
  BYOI is intended for organizations that have completed TEFCA subparticipant onboarding and have a CSP configured to issue
  ID Tokens with the organization's HCID in the `aud` claim. If you do not have that setup yet, use the standard
  [TEFCA IAS flow](/guides/tefca-ias).
</Note>

## How It Works

1. **Your application authenticates the patient (AAL2)** - The patient logs into their account within your product.
2. **Your application starts identity proofing** - Your product verifies their identity with your CSP.
3. **Your backend stores the CSP authorization grant** - Keep the patient's CSP ID Token and refresh token on your backend.
4. **Your backend creates a Pushed Authorization Request** - Call Fasten's Identity service with your stable `patient_id`.
5. **Fasten calls your preregistered Token Exchange endpoint** - Fasten sends a signed client assertion whose `sub` is the `patient_id`.
6. **Your endpoint validates the assertion and exchanges the active CSP grant** for a fresh CSP ID Token.
7. **Fasten validates the CSP ID Token** - The signature, issuer, expiration, audience, CSP, and environment must be valid.
8. **Fasten returns a `request_uri`** - The value is single-use, short-lived, and tied to your Fasten client.
9. **Your frontend launches Stitch** - You pass the `request_uri` into the Fasten SDK.
10. **Fasten collects patient consent** - The patient reviews your application and authorizes access.
11. **The patient selects providers** - Fasten searches the TEFCA network and guides the patient through selecting the healthcare organizations they want to share.
12. **Fasten repeats the Token Exchange when necessary** - Fasten may require a newly minted CSP ID Token to retrieve records from the TEFCA Network.

The initial exchange establishes the patient's CSP identity. Every CSP ID Token returned by a later exchange must contain
the same CSP `iss` and `sub` values. Within your organization, each `patient_id` must always identify the same patient and
must not be reassigned.

## Supported CSPs

The `idp` value in your Token Exchange response identifies the CSP that issued the returned ID Token.

| CSP     | `idp` value   |
| ------- | ------------- |
| CLEAR   | `clear_csp`   |
| ID.me   | `idme_csp`    |
| Persona | `persona_csp` |

The CSP must issue an unexpired OpenID Connect ID Token that Fasten can verify. The token audience must include your organization’s pre-configured HCID.

<Tip>
  Use `test` credentials with synthetic CSP users and `live` credentials with real patient identities. Test mode rejects
  non-synthetic email addresses.
</Tip>

## Prerequisites

Before you build the BYOI flow, make sure you have:

* Registered as a [TEFCA subparticipant](/guides/tefca-subparticipant) under Fasten with our QHIN.
* Authenticated the patient at AAL2 before submitting a Pushed Authorization Request.
* An [authorized CSP](https://rce.sequoiaproject.org/csp-approval-organizations/) that can complete IAL2 identity proofing.
* A CSP integration that can issue ID Tokens with `aud` set to your organization's HCID.
* Provided your organization's HCID to Fasten.
* Provided your HTTPS Token Exchange endpoint to Fasten.
* TEFCA IAS enabled for the Fasten API mode you are using.
* Generated a `public_*` ID and matching `private_*` key from the [Fasten Developer Portal](https://portal.connect.fastenhealth.com).

Keep your `private_*` key and CSP credentials on your backend only.

## Stable Patient Identifier

The `patient_id` is your stable, opaque identifier for the patient. Fasten places it in the `sub` claim of every client
assertion sent to your Token Exchange endpoint, allowing your backend to locate the correct CSP authorization grant.

The value must:

* Be stable and unique within your organization.
* Resolve to exactly one patient and one active CSP authorization grant.
* Never be reassigned to another patient.
* Be safe to use as an opaque identifier; do not put an email address, name, or other patient data in it.

Fasten enforces a one-to-one mapping between your organization's `patient_id` and the patient's Fasten identity. A PAR
request fails if a `patient_id` is already associated with a different patient or if that patient is already associated
with a different `patient_id` for your organization.

<Warning>
  Keep the `patient_id`, CSP tokens, Fasten private key, and CSP refresh credentials on backend systems. Do not send CSP or
  Fasten credentials to browser or mobile client code.
</Warning>

## Developer Flow

### 1. Authenticate And Proof The Patient

Authenticate the patient at AAL2 and complete your CSP identity-proofing flow. Store the CSP authorization grant (ID Token
and refresh token) securely on your backend, indexed by the stable `patient_id` you send to Fasten. Your Token Exchange
endpoint uses this grant to obtain a new CSP ID Token whenever Fasten requests one.

You are responsible for managing the lifetime of the CSP ID Token and refresh token. If the underlying grant expires or
is revoked, the patient must authenticate again at AAL2 and complete any CSP authorization required to establish a new grant.

### 2. Create A Pushed Authorization Request

Call `POST https://identity.fastenhealth.com/oauth2/par` from your backend. Send an
`application/x-www-form-urlencoded` request using HTTP Basic authentication with your Fasten public ID and private key.

```bash theme={null}
curl -X POST https://identity.fastenhealth.com/oauth2/par \
  -u "public_test_xxxxxxxxxx:private_test_xxxxxxxxxx" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "scope=openid profile email" \
  --data-urlencode "response_type=code" \
  --data-urlencode "prompt=consent" \
  --data-urlencode "redirect_uri=https://customer.example.com/callback" \
  --data-urlencode "patient_id=patient_01JAZ6Y3G2M4Q8K1V7N9"
```

#### Parameters

| Parameter       | Required | Description                                                          |
| --------------- | -------- | -------------------------------------------------------------------- |
| `scope`         | Yes      | Must be `openid profile email`.                                      |
| `response_type` | Yes      | Must be `code`.                                                      |
| `prompt`        | Yes      | Must be `consent`.                                                   |
| `redirect_uri`  | Yes      | Must exactly match a redirect URI registered for your Fasten client. |
| `patient_id`    | Yes      | Your stable, opaque identifier for the patient.                      |

After validating the PAR request, Fasten immediately calls your registered Token Exchange endpoint. PAR fails if the
exchange cannot be completed or the returned CSP ID Token does not pass validation.

#### Response

A successful request returns `201 Created`.

```json theme={null}
{
  "request_uri": "urn:ietf:params:oauth:request_uri:4c7f0f56-9302-4217-98d3-3b4d1e5f98ad",
  "expires_in": 90
}
```

The `request_uri` is single-use and expires after 90 seconds.

### 3. Implement The Customer Token Exchange Endpoint

Your registered Token Exchange endpoint must:

* Use HTTPS.
* Accept `POST` requests with `application/x-www-form-urlencoded` bodies.
* Validate the Fasten-signed client assertion before accessing CSP credentials.
* Use the assertion's `sub` claim to locate the expected patient and their active CSP grant.
* Return a newly issued CSP ID Token.

Fasten sends a request in the following form:

```http theme={null}
POST /exchange/token HTTP/1.1
Host: identity.customer.example.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&
subject_token=eyJhbGciOiJSUzI1NiIsImtpZCI6...&
subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Ajwt&
requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
```

The line breaks above are for readability. The actual request is a standard URL-encoded form body.

#### Validate Fasten's Client Assertion

The `subject_token` carries a short-lived client assertion JWT signed by Fasten. Validate:

| Field      | Requirement                                                                                      |
| ---------- | ------------------------------------------------------------------------------------------------ |
| JOSE `alg` | Approved asymmetric signing algorithm.                                                           |
| JOSE `kid` | Must resolve to an active key in Fasten's JWKS.                                                  |
| `iss`      | Must be `https://api.connect.fastenhealth.com`.                                                  |
| `sub`      | Must be a valid `patient_id` issued by your system.                                              |
| `aud`      | Exact URL of your registered Token Exchange endpoint.                                            |
| `exp`      | Must be in the future and no more than five minutes after `iat`.                                 |
| `iat`      | Must be within five minutes of the current time, allowing up to 60 seconds of clock skew.        |
| `nbf`      | Must not be in the future beyond 60 seconds of clock skew.                                       |
| `jti`      | Must be present, unique, and rejected if previously used.                                        |
| `task_id`  | Optional. Present when Fasten requests an ID Token for an EHI Export or another background task. |

Cache each accepted `jti` until its assertion expires to prevent replay. Retrieve Fasten signing keys from
`https://identity.fastenhealth.com/jwks.json` and support normal key rotation. If an unknown `kid` is received, refresh
the JWKS once before rejecting the request.

An example decoded payload:

```json theme={null}
{
  "iss": "https://api.connect.fastenhealth.com",
  "sub": "patient_01JAZ6Y3G2M4Q8K1V7N9",
  "aud": "https://identity.customer.example.com/exchange/token",
  "exp": 1782298800,
  "iat": 1782298500,
  "nbf": 1782298440,
  "jti": "7f13c12e-c359-46ab-b763-4ca479f566d8",
  "task_id": "task_01JAZ78Q8G4H1MM2T5QF"
}
```

<Note>
  The `task_id` is context for logging and tracing purposes. It is optional, do not reference it for authorization;
  validate the assertion signature, issuer, audience, lifetime, and replay status on every request.
</Note>

#### Successful Response

Return `200 OK` and `Content-Type: application/json`

```json theme={null}
{
  "id_token": "<CSP-issued ID Token>",
  "idp": "clear_csp"
}
```

The `idp` must identify the CSP that issued the ID Token. Supported values are `clear_csp`, `idme_csp`, and
`persona_csp`.

#### Error Responses

Return OAuth-compatible JSON errors with `Cache-Control: no-store`.

```json theme={null}
{
  "error": "invalid_grant",
  "error_description": "The patient CSP authorization has expired or was revoked."
}
```

| HTTP status | Error                     | Use when                                                                                           |
| ----------- | ------------------------- | -------------------------------------------------------------------------------------------------- |
| `400`       | `invalid_request`         | Required form fields are missing, malformed, duplicated, or unsupported.                           |
| `400`       | `invalid_grant`           | The underlying CSP grant is expired, revoked, inactive, or not valid for the patient.              |
| `400`       | `unsupported_grant_type`  | `grant_type` is not the RFC 8693 token-exchange grant.                                             |
| `400`       | `invalid_target`          | The requested token type, CSP, audience, or resource is not allowed.                               |
| `401`       | `invalid_client`          | The Fasten client assertion is missing, invalid, expired, replayed, or signed by an untrusted key. |
| `429`       | `temporarily_unavailable` | The endpoint is rate limiting Fasten. Include `Retry-After`.                                       |

### 4. Pass The `request_uri` To Fasten Stitch

Initialize Fasten Stitch with the `request_uri` returned by the PAR response.

```html theme={null}
<fasten-stitch-element
  public-id="public_test_xxxxxxxxxx"
  identity-request-uri="urn:ietf:params:oauth:request_uri:4c7f0f56-9302-4217-98d3-3b4d1e5f98ad">
</fasten-stitch-element>
```

Redeem the `request_uri` immediately after your backend creates it. If the patient takes too long or refreshes the page, create a new PAR request and relaunch Stitch with the new value.

### 5. Handle Completion Events

Listen for the same Fasten Stitch events you use in other consent flows. Store the resulting `org_connection_id` and related metadata so your backend can request exports and support the patient later.

* Use `widget.complete` to update your frontend after Stitch finishes.
* Use [`patient.connection_success`](/webhooks/events#patient-connection-success-beta) as the durable backend signal.
* Store the resulting `org_connection_id`.
* Use [`POST /bridge/fhir/ehi-export`](/api-reference/ehi_export/create) when you are ready to retrieve records.

## On-Demand Refresh

Fasten calls the same registered Token Exchange endpoint whenever it requires a fresh CSP ID Token. Each request contains
a newly generated Fasten-signed client assertion with the original `patient_id` in `sub`. For an EHI Export or another
background task, the assertion may also contain a `task_id`.

Your endpoint must return an ID Token for the same CSP identity established by the initial exchange. Fasten rejects a
refreshed token if its CSP `iss` or `sub` differs from the initial token, even if the token is otherwise valid.

Your EHI Export request only needs the Fasten API credentials and `connection_id`; you are not required to send a CSP ID Token in the
/ehi-export request. Fasten retrieves a fresh token from your Token Exchange endpoint when needed. If the endpoint cannot
return a valid token, collection fails and the patient must reauthenticate with your CSP.

Token Exchange endpoint implementations must be safe when Fasten retries a request or makes concurrent requests:

* Do not assume a request is delivered exactly once.
* Coordinate access to rotating CSP refresh tokens.
* Persist a replacement CSP refresh token before invalidating the previous stored value.
* Return the same successful result when safely possible, or perform another valid CSP exchange.
* Do not revoke the patient grant merely because a request timed out or was retried.

Fasten may retry temporary failures and rate-limited requests. Use `Retry-After` with `429 Too Many Requests` or
`503 Service Unavailable` when Fasten should delay the next attempt.

## Security And Operations

* Keep your Fasten private key on your backend.
* Keep the `patient_id` stable and never associate it with a different person.
* Return CSP ID Tokens only from your backend Token Exchange endpoint.
* Treat the CSP ID Token as sensitive patient identity data.
* Fasten receives the verified ID Token, not the patient’s ID photos or CSP proofing session materials.

## Implementation Checklist

* Complete TEFCA subparticipant and BYOI onboarding.
* Register the Token Exchange endpoint, organization HCID, and supported CSP with Fasten.
* Authenticate patients to AAL2.
* Issue stable, opaque, never-reassigned `patient_id` values.
* Store each patient's active CSP authorization grant securely on your backend.
* Implement Fasten client assertion validation and `jti` replay protection using Fasten's JWKS.
* Return the CSP ID Token and `idp` in the Token Exchange response.
* Verify retry and concurrent-refresh behavior with rotating CSP refresh tokens.
* Re-verify the patient when the CSP grant expires or is revoked.
* Keep all Fasten and CSP credentials on backend systems.

## Standards

* [OAuth 2.0 Token Exchange (RFC 8693)](https://www.rfc-editor.org/rfc/rfc8693.html)
* [JWT Profile for OAuth 2.0 Client Authentication (RFC 7523)](https://www.rfc-editor.org/rfc/rfc7523.html)
* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)
* [NIST Digital Identity Guidelines: Authentication and Authenticator Management](https://pages.nist.gov/800-63-4/sp800-63b.html)

For Fasten-managed identity proofing, see the [TEFCA IAS Developer Guide](/guides/tefca-ias).
