You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: support public (secretless, PKCE-only) OAuth2 clients
An RFC 7591 registration requesting `token_endpoint_auth_method: "none"`
now produces a public client: no secret is minted, `client_type` is
persisted as `public`, and the token endpoint accepts that client's
authorization_code exchange with PKCE alone. Discovery advertises "none"
as a supported auth method.
PKCE was already mandatory for every authorization_code flow, so public
clients inherit it unchanged. That makes the code ownership check
(`dbCode.AppID != app.ID`) the sole binding between the exchange and the app
named by `client_id` for a public client, where it was defense in depth for
confidential ones. It is retained and covered with a public client, along
with the refresh and revocation paths, which are the first to see a NULL
`app_secret_id`. The RFC 7636 §4.1 code_verifier length floor added in #28003
is exercised here against a public client specifically, since for that
client type PKCE is the only client authentication and a later change that
scoped the check to confidential clients only would leave public clients
silently unprotected.
Registration writes the app and its secret in one transaction. Two
independently committed inserts could leave a permanently committed app that
can never authenticate while still holding a registration access token.
An RFC 7592 update can no longer move a client between public and
confidential, and secret creation is rejected for a public app: the token
endpoint would never validate that secret, and deleting it revokes nothing
because a public client's tokens carry a NULL `app_secret_id` instead of
cascading from the secret.
Clients registered with "none" before it was honored are stored
confidential and still require their secret, so an update that resends their
own metadata is accepted rather than rejected, and the auth method reported
back is the one the server actually enforces.
Depends on #27931 for the client_type constraint and the schema-level
alignment of the two columns, and on #28003 for the RFC 7636 §4.1
code_verifier length floor.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
// @Param client_secret formData string false "Client secret, required if grant_type=authorization_code and the client is confidential. Public clients (token_endpoint_auth_method=none) send no secret."
// @Param code_verifier formData string false "PKCE code verifier, required if grant_type=authorization_code. 43-128 characters per RFC 7636. This is the only client authentication a public client has."
0 commit comments