Developers
Answers for people who add sign-in to an application or protect an API with identity.
On this page
Answers for people who build on identity. Start with the Quickstart if you have not yet.
Getting started#
How do I add sign-in to my application?#
Register a client, configure the relying party in the SDK, mount its routes, and sign in once. The Quickstart walks through all four steps, and Log users in covers the details.
Which OAuth flow does identity use?#
The authorization code flow with PKCE (S256) and pushed authorization requests. The response type is code only, and the authorization endpoint accepts only your client_id and the request_uri from the pushed request. There is no implicit flow. See Grant types and client authentication.
Do I get a client secret?#
No. A client proves itself with a signed assertion (private_key_jwt), or with a certificate where a deployment supports it. Public clients use no secret and are bound by PKCE and DPoP. You keep a private key instead of a shared secret.
Where are the endpoint addresses?#
In the discovery document at /.well-known/openid-configuration. Read the addresses from it rather than hard-coding them. See OIDC endpoints.
Is there an SDK?#
Yes. It handles the pushed authorization request, the callback, the token exchange, DPoP proofs and nonce retries, token verification for your API, and back-channel logout. See Build with identity. It is the package @tdacorp/identity-sdk on the public npm registry.
Tokens#
What is in a token?#
An access token is a signed JWT of type at+jwt for exactly one audience, and an ID token states who signed in and how. See Token claims.
How long do tokens live?#
Access tokens at most 900 seconds. An authorization code and a pushed request reference live at most 60 seconds. Refresh tokens depend on the client. See Token lifetimes.
Is the sub the same for every application?#
By default, yes. A client can be registered for pairwise subject identifiers (discovery lists subject_types_supported), and then the ID token and the userinfo response carry an identifier of its own for each person, and no picture. Access tokens always carry the real sub. See Token claims.
Why is there no roles claim?#
Tokens do not carry roles, and discovery does not advertise one. A product that must decide what someone may do asks the authorization API. See Authorization.
How do I get an access token for my own API?#
Ask for the API's address as a resource when the person signs in, and pass the same address as the audience when you verify. See Scopes and consent and Protect your API.
Which scopes can I ask for?#
openid, profile, email, offline_access and tdaid.tenant, plus a scope named after your product where it applies. See Scopes.
Can I ask for a language for the sign-in pages?#
Yes. Send ui_locales on the authorization request, a space-separated list of language tags, best first. It is a preference: a language saved in the person's profile wins, and a language identity does not support is skipped. A malformed list is refused with invalid_request. See Languages.
DPoP and security of tokens#
Do I need DPoP?#
Almost always. Only a first-party web client may hold an unbound token. Any other client must prove a key, and a client registered with require_dpop must do it at the pushed request, the token endpoint and revocation. See DPoP.
Why do I get use_dpop_nonce?#
It is part of the protocol: identity requires a server nonce, and the first request has none. Sign a new proof with the nonce from the DPoP-Nonce header and send the request once more. The SDK does it for you. See invalid_dpop_proof and use_dpop_nonce.
Where do I keep the DPoP key?#
In a secret store, and load it at start-up. Refresh tokens are bound to its thumbprint, so a key that changes at every start loses every refresh token.
Operations#
Why did I get invalid_grant?#
The code, refresh token or subject token you presented is no longer acceptable. The error_description says which. See invalid_grant.
Why was my redirect address refused?#
It must equal a registered address exactly. See Redirect URI mismatch.
How do I handle a 429?#
Wait for Retry-After seconds. The SDK's relying party and service client retry a 429 a few times on their own, waiting for Retry-After; if you still see one, the retries ran out or the wait asked for was too long. See 429 Too Many Requests.
What is insufficient_user_authentication?#
A resource server or the token endpoint saying the person needs a stronger or fresher sign-in (RFC 9470), with the acr_values and max_age to ask for. Send the person back through /authorize with them. An organization that enforces single sign-on answers this way too (flag sso_enforcement, OFF by default). See step_up_required.
How do I call another service?#
With a token exchange or client_credentials. See Service to service.
How do I find out that a person signed out?#
Register a back-channel logout address. Identity sends a signed logout token with the sid of the ended session. See Back-channel logout.
What is promised about changes?#
Nothing beyond what Versioning policy says. Read discovery, ignore unknown fields and branch on error codes.