From 2af73069f74d68837d83d2032ea85c6dbe7c19c0 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 2 May 2024 08:23:29 +0300 Subject: Delete a client's public key. --- gn_auth/auth/authorisation/users/admin/views.py | 69 +++++++++++++++++++++---- gn_auth/templates/admin/view-oauth2-client.html | 3 +- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/gn_auth/auth/authorisation/users/admin/views.py b/gn_auth/auth/authorisation/users/admin/views.py index 3aadf49..f004027 100644 --- a/gn_auth/auth/authorisation/users/admin/views.py +++ b/gn_auth/auth/authorisation/users/admin/views.py @@ -10,7 +10,7 @@ from dataclasses import asdict from urllib.parse import urlparse from datetime import datetime, timezone, timedelta -from authlib.jose import JsonWebKey +from authlib.jose import KeySet, JsonWebKey from email_validator import validate_email, EmailNotValidError from flask import ( flash, @@ -295,8 +295,62 @@ def register_client_public_key(): with open(keypath, mode="w", encoding="utf8") as _kpth: _kpth.write(form["client_ssl_key"]) - from gn_auth.debug import __pk__ - with_db_connection(partial(save_client, the_client=OAuth2Client( + with_db_connection(partial(save_client, the_client=OAuth2Client( + client_id=_client.client_id, + client_secret=_client.client_secret, + client_id_issued_at=_client.client_id_issued_at, + client_secret_expires_at=_client.client_secret_expires_at, + client_metadata={ + **_client.client_metadata, + "public_keys": list(set( + _client.client_metadata.get("public_keys", []) + + [str(keypath)]))}, + user=_client.user))) + flash("Client key successfully registered.", "alert-success") + return view_client_uri + + +@admin.route("/delete-client-public-key", methods=["POST"]) +@is_admin +def delete_client_public_key(): + """Delete a client's SSL key""" + form = request.form + admin_dashboard_uri = redirect(url_for("oauth2.admin.dashboard")) + view_client_uri = redirect(url_for("oauth2.admin.view_client", + client_id=form["client_id"])) + if not bool(form.get("client_id")): + flash("No client selected.", "alert-danger") + return admin_dashboard_uri + + try: + _client = with_db_connection(partial( + oauth2_client, client_id=uuid.UUID(form["client_id"]))) + if _client.is_nothing(): + raise ValueError("No such client.") + _client = _client.value + except ValueError: + flash("Invalid client ID provided.", "alert-danger") + return admin_dashboard_uri + + if form.get("ssl_key", None) is None: + flash("The key must be provided.", "alert-danger") + return view_client_uri + + try: + def find_by_kid(keyset: KeySet, kid: str) -> JsonWebKey: + for key in keyset.keys: + if key.thumbprint() == kid: + return key + raise ValueError('Invalid JSON Web Key Set') + _key = find_by_kid(_client.jwks, form.get("ssl_key")) + except ValueError: + flash("Could not delete: No such public key.", "alert-danger") + return view_client_uri + + _keys = (_key for _key in _client.jwks.keys + if _key.thumbprint() != form["ssl_key"]) + _keysdir = Path(app.config["CLIENTS_SSL_PUBLIC_KEYS_DIR"]) + with_db_connection(partial(save_client, the_client=OAuth2Client( client_id=_client.client_id, client_secret=_client.client_secret, client_id_issued_at=_client.client_id_issued_at, @@ -304,13 +358,10 @@ def register_client_public_key(): client_metadata={ **_client.client_metadata, "public_keys": list(set( - _client.client_metadata.get("public_keys", []) + - [str(keypath)]))}, + keysdir.joinpath(f"{_key.thumbprint()}.pem") + for _key in _keys))}, user=_client.user))) - flash("Client key successfully registered.", "alert-success") - return view_client_uri - - flash("Client key already exists.", "alert-warning") + flash("Key deleted.", "alert-success") return view_client_uri diff --git a/gn_auth/templates/admin/view-oauth2-client.html b/gn_auth/templates/admin/view-oauth2-client.html index 80ef84a..f5b5422 100644 --- a/gn_auth/templates/admin/view-oauth2-client.html +++ b/gn_auth/templates/admin/view-oauth2-client.html @@ -85,7 +85,8 @@