Optional ReadonlyallowedOptional ReadonlyallowedWhen true, this client MAY call POST /oauth/federation/:name/token to retrieve the user's upstream federation access_token. Deny-by-default (deny-by-absence); must be explicitly opted in per client.
Why default false: federation access_tokens grant access to the user's external resources (Google Calendar, GitHub API, etc.) — high blast radius. Opt-in prevents accidentally granting this power to a generic OAuth client registration that only needs auth.
Optional ReadonlyallowedGrant types this client is explicitly permitted to use.
Enforced centrally by isGrantTypeAllowed — once at /oauth/token
grant dispatch, before the concrete handler runs, and at /authorize
against authorization_code — so every current and future grant
inherits the check rather than opting in (#268). The central rule:
undefined (absent) → no restriction. Absence means the
registration declared no policy, not that it declared an empty one;
denying here would revoke every grant from every registration written
before this field existed.[] (empty) → every grant is denied. An empty allowlist names no
grant type, so none can match it.grant_type string
appears in the list, compared exactly.A grant handler that declares requiresExplicitGrantAllowlist on its
GrantHandler contract composes a stricter rule on top: dispatch
denies by absence for that grant, so machine-to-machine access is
never acquired by omission (#326). client_credentials
(grants/clientCredentials.mts) and the WebAuthn grant
(@o3co/auth-provider-webauthn) declare it. Both rules are enforced
at dispatch — either can reject, and only the absent case
distinguishes them; no handler carries its own copy of the check.
ReadonlyallowedReadonlyallowedOptional ReadonlyallowWhether this client may use the RFC 7636 plain PKCE challenge method
(#273).
PKCE is mandatory for every authorization-code client and S256 is the
only method the authorization server accepts — there is no server-wide
setting that admits plain, because a deployment-wide one would quietly
cover every client at once. This flag is the ONLY way to reach it, and it
is deliberately per client: admitting plain is a named exception for a
named registration, visible in the client record itself.
plain stores the verifier as the challenge, so anything that can read
the authorization request (browser history, a proxy log, a referrer)
learns the verifier too and PKCE stops proving anything. Set this only
for a legacy client that genuinely cannot compute SHA-256, and treat it
as a migration deadline rather than a configuration.
Absent and false are the same: S256 only. Like firstParty, the check
is a strict === true, so an uncoerced "true" from YAML or an
environment variable does not widen the policy.
Surfaces through PublicClient (via Omit) and AuthenticatedClient
(via the /token route's projection) so /authorize and /token read
the same value.
Optional ReadonlybackchannelOptional ReadonlybackchannelReadonlyclientOptional ReadonlyclientRequired when tokenEndpointAuthMethod is "client_secret_basic" or
"client_secret_post". MUST be absent (undefined) when the method is
"none". The ClientEntrySchema superRefine enforces both directions.
Optional ReadonlydefaultWhat an omitted scope parameter grants (#396). Absent means the client
has not declared a default: a scope-omitting request is then refused with
invalid_scope whenever allowedScopes is non-empty — the old behavior
granted the ENTIRE allowlist, making "forgot to send scope" the maximum
grant (deny-by-absence, the #326/#363 shape). A client whose
allowedScopes is empty is unaffected: there is nothing to over-grant,
and scope-less deployments keep working.
Optional ReadonlyfirstWhether this client is first-party — i.e. operated by the same organisation as this authorization server, and trusted to receive the user's identity without the user being asked (#267).
GET /authorize mints an authorization code as soon as the session is
authenticated, with no consent step. That is defensible in a pure
first-party OP and only there: a forced top-level navigation from an
attacker's page makes a logged-in victim's browser mint a code, bound to
the victim's session, delivered to the named client's registered
redirect_uri. Registering one semi-trusted client turns the endpoint
into an account-linking vector.
So the assumption is now enforced rather than assumed: /authorize
refuses any client that is not true here — one with no firstParty
field and one carrying an explicit false alike. There is no opt-out:
the one-time oauth.authorize.allowUnmarkedClients migration flag that
admitted unmarked registrations (#317) was removed in #330, and a config
still setting it fails at boot with migration instructions.
This does not make /authorize safe against forced navigation for a
client that is first-party — that is the accepted model, and the
user-interaction step which changes it is consent (#284). What the flag
closes is the escalation: a client that should never have been trusted
with a silent code cannot be registered into that position by accident.
Optional ReadonlyfrontchannelOptional ReadonlyfrontchannelOptional ReadonlypostOptional ReadonlysenderSender-constraint requirement for this client. See Wave 2 Token-
binding Cluster spec §4.8. Surfaces through PublicClient (via
Omit) and AuthenticatedClient (via the /token route's
projection).
ReadonlytokenToken-endpoint authentication method. REQUIRED — the schema rejects client entries that omit it; deployments upgrading from v0.5.0 must add the field explicitly per the v0.5.1 migration guide.
Public clients ("none") MUST present PKCE/S256 at /authorize;
confidential clients ("client_secret_basic" / "client_secret_post")
MUST present a clientSecret and use the matching transport at /token.
Audience URIs this client may receive tokens for.
Consumers:
audienceparameter selection — when this list is empty or undefined, only the client's ownclientIdis accepted as an audience target.client_credentialsgrant defaultaudclaim — selects the first entry (allowedAudiences[0]); when absent, falls back to the issuer (and ultimately omitsaudwhen no issuer is configured).