Enable PKCE on the OAuth authorization code flow #58
Loading…
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?
Severity: HIGH
The bug
docs/circa-spec.md§4.1 requires "OAuth2 with PKCE flow." PKCE is not enabled.A sub-agent verified this against the installed Authlib 1.6.10 source. Authlib adds
code_verifier/code_challengeonly whencode_challenge_methodis set on the client — twoseparate gates, both in
sync_app.py:274andoauth2/client.py:163-170. Circa's registration(
backend/app/auth/oauth.py:27-34) passes only:So
client.code_challenge_methodisNone, both gates skip, and the flow is a bareauthorization-code exchange. Anyone who intercepts the code can redeem it.
Interception is realistic here: the default redirect URI is
http://localhost:8000/...andCIRCA_ENVIRONMENTdefaults todevelopment, which disables HTTPS enforcement — so codes cantravel in plaintext on the LAN.
Fix
One line:
Authlib handles verifier generation and storage automatically once this is set. Confirm
Authentik advertises
S256in its discovery metadata (it does by default).Done when
code_challenge_method: "S256"is set on the registrationcode_challengeandcode_challenge_methodReferences
backend/app/auth/oauth.py:27-34docs/circa-spec.md§4.1sync_app.py:272-296,oauth2/client.py:163-170Related: #43 (GenericOAuth2Backend) touches the same registration.
Fixed in
244ebb7. CI green.Verified against the pinned Authlib 1.7.2 rather than the 1.6.10 the audit inspected — the dev
server venv predates the lockfile, so those versions had drifted:
sync_app.py:232—session = self.client_cls(**self.client_kwargs), soclient_kwargsdoesreach the
OAuth2Clientconstructor. Placement is correct.sync_app.py:279—if client.code_challenge_method:is the gate that generates thecode_verifier. It is now truthy.A test asserts
code_challenge_methodsits insideclient_kwargsrather than as a top-levelregister()argument, since onlyclient_kwargsis forwarded to the client.