from flask import redirect, render_template, request, session, url_for import auth from core.flask_app import app @app.route("/login/2fa", methods=["GET", "POST"]) def login_2fa(): user_id = session.get("pending_login_user_id") if not user_id: return redirect(url_for("login")) user = auth.get_user_by_id(user_id) if not user: session.pop("pending_login_user_id", None) return redirect(url_for("login")) error = None if request.method == "POST": code = request.form.get("code", "") if not auth.verify_totp(user["totp_secret"], code): error = "Code invalide." else: next_url = session.pop("pending_login_next", "") or "" session.pop("pending_login_user_id", None) session["user_id"] = user_id # "/" seul (chemin relatif interne) accepté, jamais une URL # absolue/protocole-relative ("//evil.com") — sans ce garde, # "next" (posé par core/auth_guard.py au moment d'une # redirection vers /login) serait une ouverture classique de # redirection ouverte (open redirect). if next_url.startswith("/") and not next_url.startswith("//"): return redirect(next_url) if user["role"] == "admin": return redirect(url_for("index")) return redirect(url_for("game_dashboard", slug=user["project_slug"])) return render_template("auth/login_2fa.html", error=error)