Skip to content

feat: accept PKCE-only token exchange for public clients - #28047

Draft
BobbyHo wants to merge 1 commit into
oauth2-public-clients-registrationfrom
oauth2-public-clients-token-exchange
Draft

feat: accept PKCE-only token exchange for public clients#28047
BobbyHo wants to merge 1 commit into
oauth2-public-clients-registrationfrom
oauth2-public-clients-token-exchange

Conversation

@BobbyHo

@BobbyHo BobbyHo commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Split out of #27873 to make that PR smaller to review. Fourth in the stack (on top of #28046); this is the half that makes the public client registered by the previous PR in the stack actually able to obtain a token.

The token endpoint no longer requires a client_secret for a public client: extractTokenRequest skips the client_secret presence check, and authorizationCodeGrant skips secret validation entirely for a public client, since it has none. PKCE was already mandatory for every authorization_code flow, so public clients inherit it with no new validation code. That makes the code ownership check (dbCode.AppID != app.ID) the only 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 now covered with a public client on both sides.

Issued tokens for a public client carry a NULL app_secret_id rather than referencing a secret row that does not exist. The refresh and revocation paths already verify ownership directly via app_id rather than joining through app_secret_id, so they need no code change, only updated comments and coverage confirming they handle a NULL app_secret_id correctly.

Refs https://linear.app/codercom/issue/ENG-3029/oauth2-support-public-client

@github-actions

Copy link
Copy Markdown

Docs preview

Check off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here.

@BobbyHo BobbyHo changed the title feat(coderd/oauth2provider): accept PKCE-only token exchange for public clients feat: accept PKCE-only token exchange for public clients Aug 12, 2026
…ic clients

Split out of #27873 to make that PR smaller to review. Fourth in the
stack; this is the half that makes the public client registered by the
previous PR in the stack actually able to obtain a token.

The token endpoint no longer requires a client_secret for a public
client: extractTokenRequest skips the client_secret presence check, and
authorizationCodeGrant skips secret validation entirely for a public
client, since it has none. PKCE was already mandatory for every
authorization_code flow, so public clients inherit it with no new
validation code. That makes the code ownership check (dbCode.AppID !=
app.ID) the only 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 now covered with a public client
on both sides.

Issued tokens for a public client carry a NULL app_secret_id rather
than referencing a secret row that does not exist. The refresh and
revocation paths already verify ownership directly via app_id rather
than joining through app_secret_id, so they need no code change, only
updated comments and coverage confirming they handle a NULL
app_secret_id correctly.

Refs https://linear.app/codercom/issue/ENG-3029/oauth2-support-public-client
@BobbyHo
BobbyHo force-pushed the oauth2-public-clients-registration branch from 7c8d3e5 to 800fda7 Compare August 12, 2026 01:33
@BobbyHo
BobbyHo force-pushed the oauth2-public-clients-token-exchange branch from be1eaf3 to b4ab1ba Compare August 12, 2026 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant