Skip to content

Use PKCE for oauth2 logins - #327

Merged
umputun merged 2 commits into
go-pkgz:masterfrom
paskal:feat/oauth2-pkce
Nov 9, 2026
Merged

umputun merged 2 commits into
go-pkgz:masterfrom
paskal:feat/oauth2-pkce

Conversation

@paskal

@paskal paskal commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

Previously, the oauth2 handler sent no PKCE parameters, so logins had no protection against authorization code injection, and servers that require PKCE rejected them. After this change, every login through the shared oauth2 handler, which serves the built-in oauth2 providers except Apple and every AddCustomProvider registration, generates a fresh verifier with oauth2.GenerateVerifier, keeps it in the handshake token as Handshake.CodeVerifier, and sends its S256 challenge to the authorize endpoint; the callback sends the verifier to the token endpoint. Servers without PKCE support ignore both parameters (RFC 7636 §5), so there is nothing to configure.

A handshake issued before the upgrade carries no verifier, and its callback sends none, so logins in flight during a deploy still complete. The debug line in LoginHandler logs the claims without the verifier. Apple uses its own handler and is unchanged. v1 and v2 get the same change.

The mock oauth2 server in the provider tests now enforces PKCE, so every existing login test runs the full flow. TestOauth2LoginSendsPKCEChallenge covers the S256 challenge, a fresh verifier per login and log redaction; TestOauth2CallbackWithoutPKCEVerifier covers a handshake from before the change. Tests pass with -race for both modules, and golangci-lint v2.12.2 reports no issues.

The branch also bumps CI, in its own commit: both workflows move to actions/setup-go@v7 and golangci-lint v2.15.0, and AGENTS.md drops its local lint instructions, which pinned the old version and a toolchain workaround. The other actions are already on their latest major. golangci-lint v2.15.0 reports no issues on either module, and actionlint passes on the workflows.

Resolves #325

The oauth2 handler sent no PKCE parameters, which left logins without
protection against authorization code injection and made servers that
require PKCE reject them. RFC 9700 recommends PKCE for confidential
clients too.

Each login now generates a verifier, keeps it in the handshake token and
sends its S256 challenge to the authorize endpoint; the callback sends the
verifier to the token endpoint. Servers without PKCE support ignore both
parameters. A handshake issued before this change carries no verifier, and
its callback sends none.
@paskal
paskal requested a review from umputun as a code owner November 8, 2026 21:11
@coveralls

coveralls commented Nov 8, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 42560394420

Coverage increased (+0.09%) to 86.917%

Details

  • Coverage increased (+0.09%) from the base build.
  • Patch coverage: 16 of 16 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 3860
Covered Lines: 3355
Line Coverage: 86.92%
Coverage Strength: 10.09 hits per line

💛 - Coveralls

setup-go v7 is the current major, and golangci-lint v2.15.0 reports no
new issues on either module. AGENTS.md drops its local lint instructions
instead of tracking each pinned version and toolchain workaround.

@umputun umputun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@umputun
umputun merged commit 1ba90bf into go-pkgz:master Nov 9, 2026
6 checks passed
@paskal
paskal deleted the feat/oauth2-pkce branch November 9, 2026 17:51
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.

PKCE for oauth2 providers

3 participants