# Direct OIDC Integration

LFA is a standard OIDC identity provider. Any stack that can federate to an
external OIDC IdP, or perform an authorization-code flow, can consume LFA. You
redirect to LFA, the user proves presence on their phone, and you get back an
id_token whose claims carry the location verdict.

The [Quick Start](/docs/getting-started/quickstart/) walks the wire protocol end to
end. This page covers the integration decisions around it.

---

## The one non-standard requirement

This is the **direct** path, where your app drives the OIDC flow itself. On this
path your **token exchange must include `octet_user_id`**, your stable, opaque
identifier for the user signing in. It drives
[device-to-user binding](/docs/concepts/device-lifecycle/), and a production exchange
without it is rejected (`invalid_request`).

:::note
If you federate through an identity **broker** (Okta, Microsoft Entra ID,
Auth0), the broker runs a fixed token exchange and cannot add `octet_user_id`.
That path is still supported: the broker authenticates the front channel with a
signed `/authorize` request instead, and the device binds to the verified
`login_hint`. See [Okta](/docs/integration/okta/). The rest of this page assumes the
direct path.
:::

This shapes the library question. Any OIDC library can handle the `/authorize`
redirect. For the token exchange, either:

- your library lets you add a custom form field to the token request, so use it,
  or
- perform the exchange yourself. It is one POST (see the
  [Quick Start](/docs/getting-started/quickstart/#3-exchange-the-code-with-octet_user_id)),
  and you can hand the resulting tokens back to your session layer.

Your callback handler knows which of your users is mid-login, because you
initiated the redirect from their session or your primary IdP's. The identifier
is already in hand when you exchange.

## Selecting a policy per login

Pass `octet_policy_id` on `/authorize` to choose which registered
[policy](/docs/concepts/policies/) this login must satisfy. One client can use many
policies:

```bash
&octet_policy_id=country_uk
```

Omit it to use your client's pinned default. An unknown id is rejected rather
than falling back, so a typo cannot silently weaken the check.

## `login_hint`

If you pass `login_hint` on `/authorize`, LFA echoes it back in the id_token as
the namespaced, **unverified** `octet_login_hint` claim. It is useful for
correlating the response with the login you started. On the direct path it is
pure passthrough: LFA does not verify or persist it, does not bind to it
(`octet_user_id` on `/token` is the binding identifier), and never reflects it
into identity claims such as `email`.

## Strictness worth knowing up front

LFA is deliberately narrow. Misconfigurations fail immediately rather than
degrading:

- PKCE **S256 is required**. `state` and `nonce` are **both mandatory**.
- Scopes are `openid octet.location`. Extra scopes a library adds
  (`profile email`) are ignored, and no profile claims come back.
- No refresh tokens. A location proof is a statement about now. Re-prompt when
  you need fresh presence.
- Authorization codes are single-use with a **60-second** redemption window.

The full tables (endpoints, parameters, claims, errors) live in the
[OIDC Reference](/docs/reference/oidc/).

## Gating on the result

Two levels. Use what fits:

- **Simple gate.** Require `acr == "urn:octet:loc:strong"` in the id_token. That
  single check means hardware-attested presence with the policy passed.
- **Audit or downstream verification.** Keep the `octet_location_assertion`
  claim, also mirrored as top-level `location_assertion` in the token response.
  It is a signed, 120-second statement of the region verdict, verifiable against
  the same JWKS.

## Client registration

Clients are registered by the Octet team. Email
[hello@octetproof.com](mailto:hello@octetproof.com) with your redirect URIs and
the policies you need. See [Prerequisites](/docs/getting-started/prerequisites/).

## Where to go next

- [Device lifecycle](/docs/concepts/device-lifecycle/). Binding, new phones, and
  revocation: the operational side of `octet_user_id`.
- [OIDC Reference](/docs/reference/oidc/). Every endpoint, parameter, claim, and error.
