Skip to content

Commit b1ecb2c

Browse files
committed
preserve CSRF protection
1 parent 1b8dbac commit b1ecb2c

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

app/auth.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ def google_login():
408408

409409
# We generate our own state so we can key Redis storage on it reliably
410410
state = secrets.token_urlsafe(32)
411+
session["google_oauth_state"] = state
412+
413+
# NEW: also persist the state server-side so we can validate without session
414+
try:
415+
r = _redis_client()
416+
r.setex(f"oidc:state:{state}", 600, "1")
417+
except Exception as e:
418+
current_app.logger.warning("Failed to cache OAuth state in Redis: %s", e)
411419

412420
oauth = OAuth2Session(
413421
client_id,
@@ -455,6 +463,20 @@ def google_callback():
455463
# --- CSRF (state) check ---
456464
state = request.args.get("state")
457465
expected_state = session.pop("google_oauth_state", None)
466+
467+
# NEW: accept state if present in Redis (one-time)
468+
state_ok = False
469+
try:
470+
r = _redis_client()
471+
if r.get(f"oidc:state:{state}"):
472+
state_ok = True
473+
r.delete(f"oidc:state:{state}") # one-time use
474+
except Exception as e:
475+
current_app.logger.warning("Could not read OAuth state from Redis: %s", e)
476+
477+
if not state or not (state == expected_state or state_ok):
478+
flash("State mismatch. Authentication failed.", "danger")
479+
return redirect(url_for("auth.login"))
458480
if not state or state != expected_state:
459481
flash("State mismatch. Authentication failed.", "danger")
460482
return redirect(url_for("auth.login"))

0 commit comments

Comments
 (0)