Clients and their keys
Public and confidential clients, private_key_jwt assertions accepted once, DPoP proofs, exact redirect URIs and the discovery document.
Every company's issuer is <PUBLIC_URL>/<company>. Its metadata answers at
<issuer>/.well-known/oauth-authorization-server and
<issuer>/.well-known/openid-configuration, and its key set at the jwks_uri
they name. The metadata is generated from what the server does: it lists the
scopes and claims it releases and advertises nothing it would refuse.
Two kinds of client
- A public client (
none) holds no key: a browser or native application. It always uses PKCE. - A confidential client (
private_key_jwt) holds a private key and registers the public half,EdDSA(Ed25519) orES256. There are no shared client secrets.
Clients are registered in the admin console or through its API (see
Clients and signing keys), with their
redirect URIs, a scope ceiling, the resources their tokens may be addressed to,
the grant types they may redeem, and optionally dpop_bound_access_tokens,
post_logout_redirect_uris and a backchannel_logout_uri. A client redeems only
the grant types it registered.
Redirect URIs
A redirect URI matches a registered one exactly, as a string. The one exception is a native application's loopback address, where only the port may differ (RFC 8252 §7.3).
Client assertions
A confidential client authenticates at the token, PAR and revocation endpoints
with a private_key_jwt assertion (RFC 7523):
- signed by a key the client registered, under
EdDSAorES256; - addressed to the company's issuer alone;
- valid for at most five minutes, and at most ten seconds ahead of the server's clock;
- its subject names the client, so
client_idmay be left out beside it (RFC 7521 §4.2); when it is sent, it must be that subject.
Each assertion is accepted once: its jti is kept in a TessariDB space until it
could no longer be accepted, and a second presentation is refused as a replay.
DPoP proofs
A client may bind its tokens to a key of its own with DPoP (RFC 9449). A proof is
accepted when it is typed dpop+jwt, signed by the public key it carries under
the server's algorithms, bound to this method and URI, at most a minute old and at
most ten seconds ahead, and seen once per key. The token it accompanies is bound
to that key's RFC 7638 thumbprint.
An authorization request may name the key its code is bound to as dpop_jkt; a
pushed request sent with a proof is bound to the proof's key, which a dpop_jkt
beside it must name. Such a code is redeemed only with a proof made by that key
(RFC 9449 §10). See Tokens for what a bound token
changes at the token endpoint and at UserInfo.
Scopes and claims
The server releases openid, profile and groups. An access token carries
authority only (see Tokens); a user's names and groups
are answered by UserInfo and appear in
no token. sub is pairwise: each client knows a user by an identifier of its own.