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

# Authentication guide

> How to integrate Azure OIDC sign-in, internal API token handling, refresh, and sign-out with Narrative SDK.

<Info>
  Use this page for request-level auth handling after you choose an authentication pattern. For the high-level comparison of embedded, Azure OIDC, and API auth, use [Authentication](/sdk/authentication).
</Info>

## Supported implementation paths

| Path                       | Typical use case                                                                                               | First credential source                                                          |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Azure OIDC sign-in         | User signs in through the configured Azure AD OIDC flow and the platform establishes a session after callback. | Azure AD OIDC + Narrative SDK platform                                           |
| API auth after sign-in     | Your frontend or backend calls protected APIs after a user session exists.                                     | Narrative-issued internal access token from embedded exchange or Azure OIDC flow |
| Embedded follow-on API use | Integration guidance for cases where an embedded SDK session later calls protected Narrative SDK APIs.         | Narrative-issued internal runtime session                                        |

## Recommended flow

<Steps>
  <Step title="Establish sign-in context">
    Complete the Azure OIDC sign-in flow or embedded token exchange and confirm that the returned session belongs to the expected tenant user.
  </Step>

  <Step title="Store only active access state">
    Keep short-lived access credentials in a controlled runtime store. The current web client persists access and refresh tokens through state storage; if your integration does the same, ensure the store is not exposed to untrusted code. Do not store long-lived secrets in browser local storage.
  </Step>

  <Step title="Call protected capabilities">
    Attach the active Narrative-issued internal access token to protected runtime requests and keep tenant scope checks close to the request boundary.
  </Step>

  <Step title="Handle expiry with one bounded refresh">
    If the platform returns `401 Unauthorized`, request a fresh access token once and retry the failed request once.
  </Step>

  <Step title="Sign out and clear state">
    Clear client auth state, attempt server-side revoke where supported, and force the next access attempt through sign-in again.
  </Step>
</Steps>

## Azure OIDC auth flow

Azure OIDC auth applies when the user signs in through the configured Azure AD OIDC flow instead of receiving an Embed Token from a tenant application. This is the current non-embedded sign-in path supported by the platform.

```mermaid theme={null}
sequenceDiagram
  participant User as User
  participant Client as NSDK client
  participant IdP as Azure AD OIDC
  participant NSDK as Narrative SDK platform

  User->>Client: Initiate sign-in
  Client->>IdP: Redirect to identity provider
  IdP-->>NSDK: Identity callback with claims
  NSDK-->>Client: Issue session and access state
  Client->>NSDK: Call protected capability
  NSDK-->>Client: Return protected response
```

### Azure OIDC implementation guidance

* Azure AD handles credential collection; the platform receives verified identity claims via the callback.
* Treat the returned access credential as short-lived runtime state.
* Re-authenticate if sign-in fails or if refresh cannot restore a valid session.

## API request handling

### Request pattern

Protected Narrative SDK APIs accept only Narrative-issued internal access tokens. Do not send raw identity-provider access tokens directly to these endpoints.

```js JavaScript theme={null}
async function callProtectedResource(url, accessToken) {
  const response = await fetch(url, {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  })

  return response
}
```

The bearer token must represent the current Narrative SDK session. The backend validates token structure and also verifies tenant-user binding before serving protected data.

### Controlled refresh pattern

```js JavaScript theme={null}
async function callWithRefresh(url, getAccessToken, refreshAccessToken, clearSession) {
  let accessToken = await getAccessToken()
  let response = await callProtectedResource(url, accessToken)

  if (response.status !== 401) {
    return response
  }

  accessToken = await refreshAccessToken()

  if (!accessToken) {
    await clearSession()
    throw new Error('Authentication refresh failed')
  }

  response = await callProtectedResource(url, accessToken)

  if (response.status === 401) {
    await clearSession()
    throw new Error('Authentication retry failed')
  }

  return response
}
```

## Token lifecycle handling

### Acquisition

* Start only after a successful embedded token exchange or Azure OIDC sign-in.
* Bind the credential to the expected tenant and user context.
* Do not reuse bootstrap or sign-in artifacts as long-lived API credentials.

### Refresh

* Refresh only when a protected request returns `401 Unauthorized`.
* Attempt a single controlled refresh and a single retry.
* If refresh requires backend participation, keep that logic on the server side.

### Expiry

* Expect access tokens to expire regularly.
* Remove expired credentials from runtime state as soon as refresh fails.
* Do not continue retry loops beyond the single refresh attempt.

### Sign-out

* Clear persisted and memory-held credentials and any cached auth metadata.
* Treat server-side revoke as best-effort. The current web client clears local state first and may ignore revoke failure on logout.
* Force the next protected action through sign-in again.

## Error handling baseline

| Condition                                                      | Response                                                                                       |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Any `401 Unauthorized` from a protected request                | Attempt one refresh, then retry once.                                                          |
| Retry still returns `401 Unauthorized`                         | Clear session and require sign-in again.                                                       |
| Token structure, tenant binding, or context validation failure | Treat as authentication failure. Do not assume the backend will expose a stable `401` subtype. |
| Validation failure                                             | Block the request and surface actionable integration feedback.                                 |
| Rate limiting                                                  | Retry with bounded backoff according to platform guidance.                                     |
| Repeated runtime failure                                       | Capture trace identifiers and escalate through support channels.                               |

## Security requirements

<Warning>
  Do not store long-lived credentials in browser local storage. Keep session lifetimes short, refresh through approved flows only, and fail closed when recovery is not safe.
</Warning>

* Use HTTPS end-to-end.
* Keep refresh or signing secrets off the browser.
* Keep access tokens scoped to the current user and tenant.
* Do not mask repeated authentication failures with silent retries.

## Related pages

* [Authentication](/sdk/authentication)
* [SDK integration](/sdk/integration)
* [Tenant embedding guide](/sdk/tenant-embedding-guide)
* [Troubleshooting](/sdk/troubleshooting)
