This is OpenID Connect as you already know it - Authorization Code flow with
PKCE, a discovery document, an `id_token`, a userinfo endpoint. The difference is
what sits behind it. When someone signs in with TrueVault for the first time,
they prove who they are before the code comes back to you, so the session you
end up with belongs to a verified person rather than to whoever typed in an
email address.

Anything that speaks OIDC can talk to us. If you have a library, use it.

{% callout type="info" %}
Sandbox issuer is `https://sandbox.truevault.com.au`, production is
`https://app.truevault.com.au`. Read
[the discovery document](/oauth-oidc-reference/endpoints/discovery-metadata)
rather than hardcoding endpoints - it also lists every claim we can return, in
`true_claims_supported`.
{% /callout %}

## What you get that a standard provider does not

*   **A verified person, not an account.** The first sign-in takes them through
    document and biometric checks. You get the result, not the documents.

*   **Claims you can rely on.** `trueidentity.valid` is checked against a
    ruleset, not self-asserted. See
    [Claims and credentials](/claims-and-credentials/introduction).

*   **Checks obtained on demand.** Mark a claim essential and the person is taken
    through getting the credential - a police check, a right-to-work check - as
    part of signing in. See
    [Requesting claims](/claims-and-credentials/requesting-claims).

*   **Nothing to store.** You can ask for a yes or no and receive only that. The
    identity documents never reach your systems, so they are not yours to lose.

## Is OIDC the right integration for you?

Start here. The redirect flow is the shortest path to a verified person, and it
is the one most integrations want.

| Use the OIDC flow when | Use the [Identity REST API](/rest-api-reference/trueidentity-api) when |
|---|---|
| The person is in a browser now, and you want them signed in at the end | Nobody is in a browser - a mobile app, a third-party plugin, a back-office process |
| You want a session, tokens and a `sub` you can key a user record on | You want a verification result delivered to your server by webhook |
| The answer is wanted while they wait | The answer may take days, as an ACIC police check can |

The two are not exclusive, and they read the same credentials underneath. A
common shape is OIDC for sign-in, then the REST API later on when a check has to
be renewed and the person is not around.

## Before you start

*   A `client_id`, and a `client_secret` unless you are configuring a public
    client. [Create your first client](/oauth-oidc-reference/setting-up-your-oidc-client)
    walks through the dashboard.

*   Your `redirect_uri`, registered against that client. It has to match exactly.

*   The rulesets you intend to request, enabled on the client. Asking for one
    that is not enabled fails the authorization request.

*   PKCE. It is mandatory here, including for confidential clients, and
    `code_challenge_method` must be `S256` - `plain` is not accepted.

*   HTTPS on your redirect URI in production.

## How the flow runs

1.  Generate a `code_verifier` and its S256 `code_challenge`, plus a `state` and
    a `nonce`. Keep all three in the user's session.

2.  Redirect to
    [`/oauth/oidc/authorize`](/oauth-oidc-reference/endpoints/authorization-request)
    with those, your scopes, and the claims you need.

3.  We take the person through identity verification, or straight to a consent
    screen if they already hold what you asked for.

4.  They come back to your `redirect_uri` with a `code` and your `state`. Check
    the `state` matches before you do anything with the code.

5.  Exchange the code at
    [`/oauth/oidc/token`](/oauth-oidc-reference/endpoints/token-exchange), sending
    the original `code_verifier`. Validate the `id_token` signature against
    [the JWKS](/oauth-oidc-reference/endpoints/jwks-json-web-key-set) and check
    the `nonce`.

6.  Call
    [`/oauth/oidc/userinfo`](/oauth-oidc-reference/endpoints/userinfo-endpoint)
    with the access token for the claims themselves.

[The user journey](/oauth-oidc-reference/user-journey) draws the same sequence,
including what the person sees at each step.

## A minimal authorization request

Enough to sign someone in and learn nothing else about them:

```http
GET /oauth/oidc/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fyour-app.com%2Fcallback
  &scope=openid
  &state=RANDOM_STATE
  &nonce=RANDOM_NONCE
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
  &claims=%7B%22true%22%3A%5B%22trueidentity.valid%22%5D%7D
Host: sandbox.truevault.com.au
```

That `claims` parameter, decoded, is `{"true":["trueidentity.valid"]}` - one
boolean saying the person met the ruleset. Ask for more only when you have a
reason to hold it.

## Where to go next

{% cards %}
{% card title="Create your first client" icon="🔑" href="/oauth-oidc-reference/setting-up-your-oidc-client" %}
Get a client_id and choose your rulesets and scopes.
{% /card %}
{% card title="Quick start" icon="⚡" href="/oauth-oidc-reference/quick-start-guide" %}
The four requests, end to end, with real parameters.
{% /card %}
{% card title="Endpoint reference" icon="📓" href="/oauth-oidc-reference/endpoints" %}
Every endpoint, its parameters and its responses.
{% /card %}
{% card title="Claims and credentials" icon="🎫" href="/claims-and-credentials/introduction" %}
What you can ask for, and what comes back.
{% /card %}
{% card title="Build it with AI" icon="🤖" href="/getting-started/build-with-ai" %}
A prompt that gets an assistant writing this correctly.
{% /card %}
{% card title="Error handling" icon="🚧" href="/oauth-oidc-reference/error-handling" %}
What goes wrong, and what it looks like when it does.
{% /card %}
{% /cards %}
