fix: OAuth callback — recover mode from state when session cookie is lost
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:
+14
-10
@@ -234,18 +234,22 @@ async def callback(
|
|||||||
state: str = Query(...),
|
state: str = Query(...),
|
||||||
):
|
):
|
||||||
"""Handle OAuth2 callback from Gitea."""
|
"""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", "")
|
expected_state = request.session.get("oauth_state", "")
|
||||||
provider_name = request.session.get("oauth_provider", "gitea")
|
provider_name = request.session.get("oauth_provider", "gitea")
|
||||||
if not expected_state:
|
|
||||||
return HTMLResponse("<h1>Invalid state: session expired</h1>", status_code=400)
|
auth_mode = ""
|
||||||
# Check exact match or state:mode format
|
raw_state = state
|
||||||
if state != expected_state:
|
if ":" in state:
|
||||||
parts = state.rsplit(":", 1)
|
raw_state, auth_mode = state.rsplit(":", 1)
|
||||||
if len(parts) == 2 and parts[0] == expected_state:
|
if auth_mode:
|
||||||
request.session["oauth_mode"] = parts[1]
|
request.session["oauth_mode"] = auth_mode
|
||||||
else:
|
|
||||||
return HTMLResponse("<h1>Invalid state</h1>", status_code=400)
|
# 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
|
from app.auth.providers import get_provider
|
||||||
oauth_provider = get_provider(provider_name)
|
oauth_provider = get_provider(provider_name)
|
||||||
|
|||||||
Reference in New Issue
Block a user