Switch from UniAuth to OpenID Connect
This commit is contained in:
parent
1f026c31ca
commit
e0b9e4e719
3 changed files with 50 additions and 16 deletions
63
web_view.py
63
web_view.py
|
|
@ -15,10 +15,11 @@ from collections import defaultdict
|
|||
from datetime import date, datetime, timedelta, timezone
|
||||
|
||||
import flask
|
||||
import UniAuth.auth
|
||||
import werkzeug
|
||||
import werkzeug.debug.tbtools
|
||||
import yaml
|
||||
from authlib.integrations.flask_client import OAuth
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
import agenda.data
|
||||
import agenda.error_mail
|
||||
|
|
@ -36,14 +37,33 @@ from agenda.types import StrDict, Trip
|
|||
app = flask.Flask(__name__)
|
||||
app.debug = False
|
||||
app.config.from_object("config.default")
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
|
||||
|
||||
agenda.error_mail.setup_error_mail(app)
|
||||
|
||||
oauth = OAuth(app)
|
||||
authentik_url = app.config["AUTHENTIK_URL"]
|
||||
oauth.register(
|
||||
name="authentik",
|
||||
client_id=app.config["AUTHENTIK_CLIENT_ID"],
|
||||
client_secret=app.config["AUTHENTIK_CLIENT_SECRET"],
|
||||
server_metadata_url=f"{authentik_url}/application/o/agenda/.well-known/openid-configuration",
|
||||
client_kwargs={"scope": "openid email profile"},
|
||||
)
|
||||
|
||||
|
||||
class User:
|
||||
"""Simple user object for template compatibility."""
|
||||
|
||||
def __init__(self, is_authenticated: bool) -> None:
|
||||
"""Init."""
|
||||
self.is_authenticated = is_authenticated
|
||||
|
||||
|
||||
@app.before_request
|
||||
def handle_auth() -> None:
|
||||
"""Handle authentication and set global user."""
|
||||
flask.g.user = UniAuth.auth.get_current_user()
|
||||
"""Set global user from session."""
|
||||
flask.g.user = User(is_authenticated=bool(flask.session.get("user")))
|
||||
|
||||
|
||||
@app.errorhandler(werkzeug.exceptions.InternalServerError)
|
||||
|
|
@ -831,23 +851,38 @@ def schengen_report() -> str:
|
|||
return agenda.trip_schengen.flask_route_schengen_report()
|
||||
|
||||
|
||||
@app.route("/callback")
|
||||
def auth_callback() -> tuple[str, int] | werkzeug.Response:
|
||||
"""Process the authentication callback."""
|
||||
return UniAuth.auth.auth_callback()
|
||||
|
||||
|
||||
@app.route("/login")
|
||||
def login() -> werkzeug.Response:
|
||||
"""Login."""
|
||||
next_url = flask.request.args["next"]
|
||||
return UniAuth.auth.redirect_to_login(next_url)
|
||||
"""Redirect to Authentik for OIDC login."""
|
||||
next_url = flask.request.args.get("next", flask.url_for("index"))
|
||||
flask.session["login_next"] = next_url
|
||||
redirect_uri = flask.url_for("auth_callback", _external=True)
|
||||
return oauth.authentik.authorize_redirect(redirect_uri)
|
||||
|
||||
|
||||
@app.route("/callback")
|
||||
def auth_callback() -> werkzeug.Response:
|
||||
"""Handle OIDC callback from Authentik."""
|
||||
try:
|
||||
token = oauth.authentik.authorize_access_token()
|
||||
except Exception:
|
||||
return flask.redirect(flask.url_for("login"))
|
||||
userinfo = token.get("userinfo") or oauth.authentik.userinfo()
|
||||
flask.session["user"] = {
|
||||
"sub": userinfo["sub"],
|
||||
"username": userinfo.get("preferred_username"),
|
||||
"email": userinfo.get("email"),
|
||||
}
|
||||
next_url = flask.session.pop("login_next", flask.url_for("index"))
|
||||
return flask.redirect(next_url)
|
||||
|
||||
|
||||
@app.route("/logout")
|
||||
def logout() -> werkzeug.Response:
|
||||
"""Logout."""
|
||||
return UniAuth.auth.redirect_to_logout(flask.request.args["next"])
|
||||
"""Log out and redirect to Authentik end-session endpoint."""
|
||||
flask.session.pop("user", None)
|
||||
end_session_url = f"{authentik_url}/application/o/agenda/end-session/"
|
||||
return flask.redirect(end_session_url)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue