fix(api): Send PKCE code_verifier in token exchange and secure OIDC cookies

The /exchange-token endpoint was not sending the code_verifier to the
token endpoint, rendering PKCE protection ineffective. Add the verifier
to the POST body so the IdP can validate the authorization code exchange.

Also add secure=True and samesite='Lax' to all OIDC cookies on /login
to improve cookie security per the recommended remediation.

Refs vuln-0004
This commit is contained in:
2026-06-29 19:49:07 +02:00
parent 0d39efd034
commit 77b2531106
+17 -3
View File
@@ -182,9 +182,20 @@ async def login(request: Request):
response = RedirectResponse(auth_url)
# Store state and nonce in secure http-only cookies for validation on callback
response.set_cookie("oidc_state", state, httponly=True, max_age=300)
response.set_cookie("oidc_nonce", nonce, httponly=True, max_age=300)
response.set_cookie("oidc_verifier", code_verifier, httponly=True, max_age=300)
response.set_cookie(
"oidc_state", state, httponly=True, secure=True, samesite="Lax", max_age=300
)
response.set_cookie(
"oidc_nonce", nonce, httponly=True, secure=True, samesite="Lax", max_age=300
)
response.set_cookie(
"oidc_verifier",
code_verifier,
httponly=True,
secure=True,
samesite="Lax",
max_age=300,
)
return response
@@ -257,6 +268,7 @@ async def callback(request: Request, code: str, state: str):
@app.get("/exchange-token")
async def exchange_token(
request: Request,
code: str,
headers: Annotated[AuthHeaders, Header()],
):
@@ -264,6 +276,7 @@ async def exchange_token(
if not headers.authorized():
raise HTTPException(401, detail="get out")
code_verifier = request.cookies.get("oidc_verifier")
# Exchange authorization code for access token
token_data = {
"grant_type": "authorization_code",
@@ -271,6 +284,7 @@ async def exchange_token(
"client_secret": CLIENT_SECRET,
"code": code,
"redirect_uri": REDIRECT_URI,
"code_verifier": code_verifier,
}
response = requests.post(TOKEN_ENDPOINT, data=token_data)