From 8ee844abf69575074cc8db7428db0a46c5808e28 Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Sat, 27 Jun 2026 14:08:01 +0200 Subject: [PATCH] fix(oauth): exempt /auth/oauth/ from platform CSRF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude.ai's dynamic client registration and token exchange are cookieless machine-to-machine POSTs that can't carry the platform's double-submit CSRF token — they were 403'ing. /auth/oauth/register + /token are protected by PKCE + client validation, and the consent POST carries its own signed token, so the whole /auth/oauth/ prefix is safe to exempt (gated on oauth_server.enabled). Claude-Session: https://claude.ai/code/session_0154TnwYASjN1u1Hw97JQ2vd --- enlace_auth/plugin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/enlace_auth/plugin.py b/enlace_auth/plugin.py index ee6d362..3fb5ff4 100644 --- a/enlace_auth/plugin.py +++ b/enlace_auth/plugin.py @@ -336,6 +336,12 @@ def wire(parent: "FastAPI", config) -> None: # proxy to a black-box upstream that can't participate in enlace's # double-submit flow, so their entire mount prefix must also be exempt. csrf_exempt = ["/auth/callback", "/auth/login/", "/api/"] + if auth_cfg.oauth_server.enabled: + # OAuth 2.1 server endpoints: /register + /token are cookieless + # machine-to-machine calls (protected by PKCE + client validation), and + # the consent POST carries its own signed CSRF token — so the platform's + # double-submit CSRF must not gate them. + csrf_exempt.append("/auth/oauth/") for app in getattr(config, "apps", []): if getattr(app, "mode", "asgi") in ("process", "external"): prefix = app.route_prefix