fix: OAuth callback — recover mode from state when session cookie is lost
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Has been skipped

Root cause: request.session cookie expires during Gitea OAuth redirect
           → oauth_mode lost → link mode falls through to login mode
           → Creates gitea_bruno user instead of linking to local account

Fix: state now carries mode suffix (state:mode)
     Callback recovers mode from state parameter even if session lost
     Allows full session loss but still correctly enters link mode
This commit is contained in:
2026-07-14 20:34:43 -04:00
parent c5ffab1e39
commit 3c8529fd12
+14 -10
View File
@@ -234,18 +234,22 @@ async def callback(
state: str = Query(...),
):
"""Handle OAuth2 callback from Gitea."""
# Validate state — try exact match first, then with mode suffix
# Recover mode from state suffix (state:mode format), then validate
expected_state = request.session.get("oauth_state", "")
provider_name = request.session.get("oauth_provider", "gitea")
if not expected_state:
return HTMLResponse("<h1>Invalid state: session expired</h1>", status_code=400)
# Check exact match or state:mode format
if state != expected_state:
parts = state.rsplit(":", 1)
if len(parts) == 2 and parts[0] == expected_state:
request.session["oauth_mode"] = parts[1]
else:
return HTMLResponse("<h1>Invalid state</h1>", status_code=400)
auth_mode = ""
raw_state = state
if ":" in state:
raw_state, auth_mode = state.rsplit(":", 1)
if auth_mode:
request.session["oauth_mode"] = auth_mode
# Validate: state token must match session, unless session lost and mode present
if expected_state and raw_state != expected_state:
return HTMLResponse("<h1>Invalid state</h1>", status_code=400)
if not expected_state and not auth_mode:
return HTMLResponse("<h1>Session expired — please try connecting again</h1>", status_code=400)
from app.auth.providers import get_provider
oauth_provider = get_provider(provider_name)