Skip to main content

The shape of it

A tenant has its own users, clients, signing keys and sessions, isolated in the database by PostgreSQL row-level security (ADR 0009). Every protocol endpoint lives under /tenants/{tenant}/, so the tenant is chosen by the URL and never by a header or a parameter.

MethodPathWhat it is
GET/tenants/{tenant}/.well-known/openid-configurationDiscovery document
GET/tenants/{tenant}/protocol/openid-connect/certsJWKS (public signing keys)
GET/tenants/{tenant}/protocol/openid-connect/authAuthorization endpoint
POST/tenants/{tenant}/protocol/openid-connect/authAuthorization endpoint (form)
POST/tenants/{tenant}/login-actions/authenticateLogin form submission
POST/tenants/{tenant}/login-actions/consentConsent screen submission (allow/deny)
POST/tenants/{tenant}/login-actions/select-accountAccount chooser submission
POST/tenants/{tenant}/login-actions/required-actionComplete a pending required action (enrolment, password)
POST/tenants/{tenant}/login-actions/passkey-challengeRequest options for a usernameless passkey assertion
GET/tenants/{tenant}/login-actions/registrationSelf-registration form
POST/tenants/{tenant}/login-actions/registrationSelf-registration submission
GET/tenants/{tenant}/login-actions/action-tokenRedeem a mailed action token (verify email, reset password, required actions)
POST/tenants/{tenant}/login-actions/action-tokenSubmit a new password, or the required actions, against a token
GET/tenants/{tenant}/login-actions/reset-passwordPassword reset request form
POST/tenants/{tenant}/login-actions/reset-passwordPassword reset request submission
POST/tenants/{tenant}/protocol/openid-connect/tokenToken endpoint
POST/tenants/{tenant}/protocol/openid-connect/token/introspectToken introspection (RFC 7662)
POST/tenants/{tenant}/protocol/openid-connect/revokeToken revocation (RFC 7009)
GET/tenants/{tenant}/protocol/openid-connect/userinfoUserInfo
POST/tenants/{tenant}/protocol/openid-connect/userinfoUserInfo (form)
GET/tenants/{tenant}/protocol/openid-connect/logoutRP-initiated logout (end_session_endpoint)
POST/tenants/{tenant}/protocol/openid-connect/logoutRP-initiated logout (form-serialized), confirmation form
POST/tenants/{tenant}/clients-registrations/openid-connectDynamic client registration (RFC 7591)
GET/health/live, /health/readyLiveness, readiness
GET/docs, /docs/*The documentation, below

/login-actions/authenticate is deliberately outside the /protocol/openid-connect/ namespace: that namespace is the OIDC wire protocol, and the login form is Odudu's own UI, which no specification describes and no client library calls.

Four grant types reach /token: authorization_code, refresh_token, client_credentials and RFC 8693 token exchange (urn:ietf:params:oauth:grant-type:token-exchange, Path D). They share almost everything. Client authentication, scope resolution, access-token minting and the response envelope are one path for all four; only one stage — deciding whether this client may have this grant, and what subject it names — is grant-specific. That is why the error vocabulary is so uniform below: most refusals come from shared code. config.grantTypes gates all four alike: a client not registered for the grant it sends is refused unauthorized_client before anything grant-specific runs.