about summary refs log tree commit diff
path: root/gn2/wqflask/oauth2
diff options
context:
space:
mode:
Diffstat (limited to 'gn2/wqflask/oauth2')
-rw-r--r--gn2/wqflask/oauth2/request_utils.py3
-rw-r--r--gn2/wqflask/oauth2/toplevel.py65
2 files changed, 47 insertions, 21 deletions
diff --git a/gn2/wqflask/oauth2/request_utils.py b/gn2/wqflask/oauth2/request_utils.py
index a453d18e..1cdc465f 100644
--- a/gn2/wqflask/oauth2/request_utils.py
+++ b/gn2/wqflask/oauth2/request_utils.py
@@ -35,7 +35,8 @@ def process_error(error: Response,
     if error.status_code in range(400, 500):
         try:
             err = error.json()
-            msg = err.get("error_description", f"{error.reason}")
+            msg = err.get(
+                "error", err.get("error_description", f"{error.reason}"))
         except simplejson.errors.JSONDecodeError as _jde:
             msg = message
         return {
diff --git a/gn2/wqflask/oauth2/toplevel.py b/gn2/wqflask/oauth2/toplevel.py
index dffc0a7c..23965cc1 100644
--- a/gn2/wqflask/oauth2/toplevel.py
+++ b/gn2/wqflask/oauth2/toplevel.py
@@ -1,14 +1,18 @@
 """Authentication endpoints."""
-from uuid import UUID
+import uuid
+import datetime
 from urllib.parse import urljoin, urlparse, urlunparse
+
+from authlib.jose import jwt
 from flask import (
     flash, request, Blueprint, url_for, redirect, render_template,
     current_app as app)
 
 from . import session
-from .client import SCOPE, no_token_post, user_logged_in
 from .checks import require_oauth2
 from .request_utils import user_details, process_error
+from .client import (
+    SCOPE, no_token_post, user_logged_in, authserver_uri, oauth2_clientid)
 
 toplevel = Blueprint("toplevel", __name__)
 
@@ -18,38 +22,59 @@ 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.set_user_token(token)
-        udets = user_details()
-        session.set_user_details({
-            "user_id": UUID(udets["user_id"]),
-            "name": udets["name"],
-            "email": udets["email"],
-            "token": session.user_token(),
-            "logged_in": True
-        })
-        return redirect("/")
-
     code = request.args.get("code", "")
     if bool(code):
         base_url = urlparse(request.base_url, scheme=request.scheme)
+        jwtkey = app.config["SSL_PRIVATE_KEY"]
+        issued = datetime.datetime.now()
         request_data = {
-            "grant_type": "authorization_code",
+            "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
             "code": code,
             "scope": SCOPE,
             "redirect_uri": urljoin(
                 urlunparse(base_url),
                 url_for("oauth2.toplevel.authorisation_code")),
+            "assertion": jwt.encode(
+                header={
+                    "alg": "RS256",
+                    "typ": "jwt",
+                    "kid": jwtkey.as_dict()["kid"]},
+                payload={
+                    "iss": str(oauth2_clientid()),
+                    "sub": request.args["user_id"],
+                    "aud": urljoin(authserver_uri(), "auth/token"),
+                    "exp": (issued + datetime.timedelta(minutes=5)),
+                    "nbf": int(issued.timestamp()),
+                    "iat": int(issued.timestamp()),
+                    "jti": str(uuid.uuid4())},
+                key=jwtkey).decode("utf8"),
             "client_id": app.config["OAUTH2_CLIENT_ID"]
         }
+
+        def __error__(error):
+            flash(f"{error['error']}: {error['error_description']}",
+                  "alert-danger")
+            app.logger.debug("Request error (%s) %s: %s",
+                             error["status_code"], error["error_description"],
+                             request_data)
+            return redirect("/")
+
+        def __success__(token):
+            session.set_user_token(token)
+            udets = user_details()
+            session.set_user_details({
+                "user_id": uuid.UUID(udets["user_id"]),
+                "name": udets["name"],
+                "email": udets["email"],
+                "token": session.user_token(),
+                "logged_in": True
+            })
+            return redirect("/")
+
         return no_token_post(
             "auth/token", data=request_data).either(
                 lambda err: __error__(process_error(err)), __success__)