You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
suchwow/suchwow/routes/auth.py

71 lines
1.9 KiB

from uuid import uuid4
import requests
from flask import session, redirect, url_for, request, Blueprint
from suchwow import config
bp = Blueprint("auth", "auth")
@bp.route("/login")
def login():
state = uuid4().hex
session["auth_state"] = state
url = f"{config.OIDC_URL}/auth?" \
f"client_id={config.OIDC_CLIENT_ID}&" \
f"redirect_uri={config.OIDC_REDIRECT_URL}&" \
f"response_type=code&" \
f"state={state}"
return redirect(url)
@bp.route("/logout")
def logout():
session["auth"] = None
return redirect(url_for("main.index"))
@bp.route("/auth/")
def auth():
# todo - clean up assertions
assert "state" in request.args
assert "session_state" in request.args
assert "code" in request.args
# verify state
if not session.get("auth_state"):
return "session error", 500
if request.args["state"] != session["auth_state"]:
return "attack detected :)", 500
# with this authorization code we can fetch an access token
url = f"{config.OIDC_URL}/token"
data = {
"grant_type": "authorization_code",
"code": request.args["code"],
"redirect_uri": config.OIDC_REDIRECT_URL,
"client_id": config.OIDC_CLIENT_ID,
"client_secret": config.OIDC_CLIENT_SECRET,
"state": request.args["state"]
}
resp = requests.post(url, data=data)
resp.raise_for_status()
data = resp.json()
assert "access_token" in data
assert data.get("token_type") == "bearer"
access_token = data["access_token"]
# fetch user information with the access token
url = f"{config.OIDC_URL}/userinfo"
try:
resp = requests.post(url, headers={"Authorization": f"Bearer {access_token}"})
resp.raise_for_status()
user_profile = resp.json()
except:
return resp.content, 500
# user can now visit /secret
session["auth"] = user_profile
return redirect(url_for("main.index"))