Change to oidc and new foreign id format
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful

This commit is contained in:
2023-07-30 03:17:03 +03:00
parent d0fa0b1928
commit a28189a306
14 changed files with 390 additions and 198 deletions

100
inventory-app/oidc.py Normal file
View File

@@ -0,0 +1,100 @@
import os
import const
import jwt
import base64
import requests
from pymongo import MongoClient
from flask import Blueprint, abort, g, make_response, redirect, render_template, request, Flask, request, url_for, session
from common import CustomForm, build_query, flatten, format_name, spam
from functools import wraps
page_oidc = Blueprint("oidc", __name__)
db = MongoClient(const.MONGO_URI).get_default_database()
metadata = requests.get("https://auth.codemowers.eu/.well-known/openid-configuration").json()
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not read_user():
print("doing login redirect")
session["original_url"] = request.full_path
return do_login()
return f(*args, **kwargs)
return decorated_function
def do_login():
url = add_url_params(metadata["authorization_endpoint"], {
"client_id": os.getenv("OIDC_CLIENT_ID"),
"redirect_uri": url_for("oidc.login_callback", _external=True, _scheme='https'),
"response_type": "code",
"scope": "openid profile",
})
return redirect(url)
def add_url_params(url, params):
req = requests.models.PreparedRequest()
req.prepare_url(url, params)
return req.url
@page_oidc.route('/login-callback')
def login_callback():
code = request.args.get('code')
r = requests.post(metadata["token_endpoint"], {
"code": code,
"grant_type": "authorization_code",
"redirect_uri": url_for("oidc.login_callback", _external=True, _scheme='https'),
"client_id": os.getenv("OIDC_CLIENT_ID"),
"client_secret": os.getenv("OIDC_CLIENT_SECRET"),
}).json()
if "error" in r:
return "failed to fetch tokens", 500
if not validate_id_token(r["id_token"]) or not read_user(r["access_token"]):
return "tokens validation failed", 500
print("authenticated")
session["id_token"] = r["id_token"]
session["access_token"] = r["access_token"]
return redirect(session.pop("original_url", "/"))
@page_oidc.route("/logout")
def logout():
token = session.pop("access_token", "asdf")
session.clear()
s = os.getenv("OIDC_CLIENT_ID") + ":" + os.getenv("OIDC_CLIENT_SECRET")
r = requests.post(
url = metadata["revocation_endpoint"],
headers = {"Authorization": "Basic " + base64.b64encode(s.encode()).decode()},
data = {"token": token, "token_type_hint": "access_token"}
)
if r.status_code != 200:
return "oops", 500
return redirect("/")
def read_user(token=None):
token = token or session.get("access_token", False)
if not token:
return False
r = requests.get(url = metadata["userinfo_endpoint"], headers = {
"Authorization": "Bearer " + token
})
if r.status_code == 200:
return r.json()
else:
return False
def validate_id_token(token=None):
token = token or session.get("id_token", False)
if not token:
return False
jwks_client = jwt.PyJWKClient(metadata["jwks_uri"])
signing_key = jwks_client.get_signing_key_from_jwt(token)
try:
return jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience=os.getenv("OIDC_CLIENT_ID"),
options={"verify_exp": True},
)
except jwt.InvalidTokenError as e:
return False