From 45f2eaa9d2965c79d77c898aab3a01a1f06e4149 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 3 Oct 2024 11:37:49 -0500 Subject: Provide a way to change OAuth2 client secrets. --- .../authentication/oauth2/models/oauth2client.py | 23 +++++++++++++-- gn_auth/auth/authorisation/users/admin/views.py | 34 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) (limited to 'gn_auth/auth') diff --git a/gn_auth/auth/authentication/oauth2/models/oauth2client.py b/gn_auth/auth/authentication/oauth2/models/oauth2client.py index 8fac648..2c36f45 100644 --- a/gn_auth/auth/authentication/oauth2/models/oauth2client.py +++ b/gn_auth/auth/authentication/oauth2/models/oauth2client.py @@ -3,9 +3,9 @@ import json import logging import datetime from uuid import UUID -from dataclasses import dataclass from functools import cached_property -from typing import Sequence, Optional +from dataclasses import asdict, dataclass +from typing import Any, Sequence, Optional import requests from requests.exceptions import JSONDecodeError @@ -289,3 +289,22 @@ def delete_client( cursor.execute("DELETE FROM oauth2_tokens WHERE client_id=?", params) cursor.execute("DELETE FROM oauth2_clients WHERE client_id=?", params) return the_client + + +def update_client_attribute( + client: OAuth2Client, attribute: str, value: Any) -> OAuth2Client: + """Return a new OAuth2Client with the given attribute updated/changed.""" + attrs = { + attr: type(value) + for attr, value in asdict(client).items() + if attr != "client_id" + } + assert ( + attribute in attrs.keys() and isinstance(value, attrs[attribute])), ( + "Invalid attribute/value provided!") + return OAuth2Client( + client_id=client.client_id, + **{ + attr: (value if attr==attribute else getattr(client, attr)) + for attr in attrs + }) diff --git a/gn_auth/auth/authorisation/users/admin/views.py b/gn_auth/auth/authorisation/users/admin/views.py index 85aeb50..1dd2f1f 100644 --- a/gn_auth/auth/authorisation/users/admin/views.py +++ b/gn_auth/auth/authorisation/users/admin/views.py @@ -30,6 +30,7 @@ from ....authentication.oauth2.models.oauth2client import ( save_client, OAuth2Client, oauth2_clients, + update_client_attribute, client as oauth2_client, delete_client as _delete_client) from ....authentication.users import ( @@ -321,3 +322,36 @@ def delete_client(): "successfully."), "alert-success") return redirect(url_for("oauth2.admin.list_clients")) + + +@admin.route("/clients//change-secret", methods=["GET", "POST"]) +@is_admin +def change_client_secret(client_id: uuid.UUID): + def __no_client__(): + # Calling the function causes the flash to be evaluated + # flash("No such client was found!", "alert-danger") + return redirect(url_for("oauth2.admin.list_clients")) + + with db.connection(app.config["AUTH_DB"]) as conn: + if request.method == "GET": + return oauth2_client( + conn, client_id=client_id + ).maybe(__no_client__(), lambda _client: render_template( + "admin/confirm-change-client-secret.html", + client=_client + )) + + _raw = random_string() + return oauth2_client( + conn, client_id=client_id + ).then( + lambda _client: save_client( + conn, + update_client_attribute( + _client, "client_secret", hash_password(_raw))) + ).then( + lambda _client: render_template( + "admin/registered-client.html", + client=_client, + client_secret=_raw) + ).maybe(__no_client__(), lambda resp: resp) -- cgit v1.2.3