mirror of
https://github.com/niels-emmer/myace.git
synced 2026-09-14 07:36:39 +02:00
[PR #68] [MERGED] fix: OAuth login 500s at callback — code_verifier never forwarded to token exchange #66
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
github-mirrors/myace#66
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/niels-emmer/myace/pull/68
Author: @niels-emmer
Created: 8/12/2026
Status: ✅ Merged
Merged: 8/12/2026
Merged by: @niels-emmer
Base:
main← Head:fix/oauth-pkce-code-verifier-not-sent📝 Commits (1)
4bd911cfix: forward PKCE code_verifier from session to OAuth token exchange📊 Changes
3 files changed (+119 additions, -1 deletions)
View changed files
📝
AGENTS.md(+14 -0)📝
backend/app/api/auth.py(+10 -1)➕
backend/tests/test_oauth_callback.py(+95 -0)📄 Description
Summary
authlib...OAuthError: invalid_grant: A code_verifier was not included, but the authorization request included a code_challenge.login()generates a PKCEcode_verifier/code_challengeitself and stashes the verifier inrequest.session["code_verifier"], passingcode_challenge/code_challenge_methodtoauthorize_redirect()as per-request kwargs (so one generic client works for OIDC/GitHub/Google). Authlib only auto-generates and replays acode_verifierthrough its own session-backed state whencode_challenge_methodis set on the client at registration time — since it isn't here, Authlib's internal state never contains a verifier, andauth_callback()was callingauthorize_access_token(request)with nothing to fill that gap. The verifierlogin()stored was written but never read back.auth_callback()now doesrequest.session.pop("code_verifier", None)and passes it explicitly toauthorize_access_token(request, code_verifier=code_verifier).code_challenge, not against any mocked test.Test plan
backend/tests/test_oauth_callback.pywith a fake OAuth client (no network calls) that records whatauthorize_redirect/authorize_access_tokenwere called with, and asserts the verifier sent at callback time cryptographically produces (via S256) the challenge sent at login time — plus a single-use regression test.ruff checkclean on the changed files.pytestrun against the local dev container hit 5 unrelated failures (test_seed_collections.py,test_provider_toggle.py,test_startup_warnings.py) — reproduced independent of this change (pre-existing Postgres-connection contention when the full suite runs back-to-back against this long-lived, already-poked-at local dev container instead of a fresh one); each of those passes individually. CI runs in a clean environment.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.