From b6a36068c3c1b94dcbe7906a90695b102c063796 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Tue, 9 May 2023 11:31:47 +0300 Subject: auth: Handle authentication using the "Authorization Code Flow" --- wqflask/wqflask/oauth2/client.py | 15 ++++++++++++++- wqflask/wqflask/oauth2/toplevel.py | 34 ++++++++++++++++++++++++++++++---- wqflask/wqflask/oauth2/users.py | 2 +- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/wqflask/wqflask/oauth2/client.py b/wqflask/wqflask/oauth2/client.py index dba52644..efa862f2 100644 --- a/wqflask/wqflask/oauth2/client.py +++ b/wqflask/wqflask/oauth2/client.py @@ -1,6 +1,6 @@ """Common oauth2 client utilities.""" import requests -from typing import Optional +from typing import Any, Optional from urllib.parse import urljoin from flask import session, current_app as app @@ -54,3 +54,16 @@ def no_token_get(uri_path: str, **kwargs) -> Either: if resp.status_code == 200: return Right(resp.json()) return Left(resp) + +def no_token_post(uri_path: str, data: dict[str, Any]) -> Either: + config = app.config + request_data = { + **data, + "client_id": config["OAUTH2_CLIENT_ID"], + "client_secret": config["OAUTH2_CLIENT_SECRET"] + } + resp = requests.post(urljoin(config["GN_SERVER_URL"], uri_path), + data=request_data, json=request_data) + if resp.status_code == 200: + return Right(resp.json()) + return Left(resp) diff --git a/wqflask/wqflask/oauth2/toplevel.py b/wqflask/wqflask/oauth2/toplevel.py index 1803ef85..df2ff0aa 100644 --- a/wqflask/wqflask/oauth2/toplevel.py +++ b/wqflask/wqflask/oauth2/toplevel.py @@ -1,13 +1,11 @@ """Authentication endpoints.""" -import requests from urllib.parse import urljoin - -from authlib.integrations.base_client.errors import OAuthError from flask import ( flash, request, session, Blueprint, url_for, redirect, render_template, current_app as app) -from .client import oauth2_client +from .client import no_token_post +from .request_utils import process_error from .checks import require_oauth2, user_logged_in toplevel = Blueprint("toplevel", __name__) @@ -20,3 +18,31 @@ toplevel = Blueprint("toplevel", __name__) def register_client(): """Register an OAuth2 client.""" return "USER IS LOGGED IN AND SUCCESSFULLY ACCESSED THIS ENDPOINT!" + +@toplevel.route("/code", methods=["GET"]) +def authorisation_code(): + """Use authorisation code to get token.""" + def __error__(error): + flash(f"{error['error']}: {error['error_description']}", + "alert-danger") + return redirect("/") + + def __success__(token): + session["oauth2_token"] = token + return redirect(url_for("oauth2.user.user_profile")) + + code = request.args.get("code", "") + if bool(code): + request_data = { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": urljoin( + request.base_url, + url_for("oauth2.toplevel.authorisation_code")), + "client_id": app.config["OAUTH2_CLIENT_ID"] + } + return no_token_post( + "oauth2/token", data=request_data).either( + lambda err: __error__(process_error(err)), __success__) + flash("AuthorisationError: No code was provided.", "alert-danger") + return redirect("/") diff --git a/wqflask/wqflask/oauth2/users.py b/wqflask/wqflask/oauth2/users.py index a82eb5c6..44ba252a 100644 --- a/wqflask/wqflask/oauth2/users.py +++ b/wqflask/wqflask/oauth2/users.py @@ -100,7 +100,7 @@ def logout(): session.pop(key, default=None) flash("Successfully logged out.", "alert-success") - return redirect(url_for("oauth2.user.login")) + return redirect("/") @users.route("/register", methods=["GET", "POST"]) def register_user(): -- cgit v1.2.3