diff options
author | Frederick Muriuki Muriithi | 2024-10-03 11:37:49 -0500 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2024-10-03 11:37:49 -0500 |
commit | 45f2eaa9d2965c79d77c898aab3a01a1f06e4149 (patch) | |
tree | 5b5945e81091c68d9f861c71ac8af3da8a05b4e3 /gn_auth | |
parent | b9de9e436dd4f84174f6fc1b707e1b303a94fcf4 (diff) | |
download | gn-auth-45f2eaa9d2965c79d77c898aab3a01a1f06e4149.tar.gz |
Provide a way to change OAuth2 client secrets.
Diffstat (limited to 'gn_auth')
4 files changed, 109 insertions, 3 deletions
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/<uuid:client_id>/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) diff --git a/gn_auth/templates/admin/confirm-change-client-secret.html b/gn_auth/templates/admin/confirm-change-client-secret.html new file mode 100644 index 0000000..aa8ef81 --- /dev/null +++ b/gn_auth/templates/admin/confirm-change-client-secret.html @@ -0,0 +1,45 @@ +{%extends "base.html"%} + +{%block title%}gn-auth: View OAuth2 Client{%endblock%} + +{%block pagetitle%}View OAuth2 Client{%endblock%} + +{%block content%} +{{flash_messages()}} + +<h2>Change Oauth2 Client Secret</h2> + +<p>You are attempting to change the <strong>CLIENT_SECRET</strong> value for the + following client:</p> + +<table class="table"> + <tbody> + <tr> + <td><strong>Client ID</strong></td> + <td>{{client.client_id}}</td> + </tr> + <tr> + <td><strong>Client Name</strong></td> + <td>{{client.client_metadata.client_name}}</td> + </tr> + </tbody> +</table> + +<p>Are you absolutely sure you want to do this?<br /> + <small>Note that you'll need to update your configurations for the client and + restart it for the settings to take effect!</small></p> + +<form id="frm-change-client-secret" + method="POST" + action="{{url_for('oauth2.admin.change_client_secret', + client_id=client.client_id)}}"> + + <input type="hidden" name="client_id" value="{{client.client_id}}" /> + <input type="hidden" name="client_name" value="{{client.client_metadata.client_name}}" /> + + <div class="form-group"> + <input type="submit" class="btn btn-danger" value="generate new secret" /> + </div> +</form> + +{%endblock%} diff --git a/gn_auth/templates/admin/list-oauth2-clients.html b/gn_auth/templates/admin/list-oauth2-clients.html index ca0ee6d..6da5b2f 100644 --- a/gn_auth/templates/admin/list-oauth2-clients.html +++ b/gn_auth/templates/admin/list-oauth2-clients.html @@ -15,7 +15,7 @@ <th>Client Name</th> <th>Default Redirect URI</th> <th>Owner</th> - <th colspan="2">Actions</th> + <th colspan="3">Actions</th> </tr> </thead> @@ -43,6 +43,14 @@ class="btn btn-danger" /> </form> </td> + <td> + <a href="{{url_for('oauth2.admin.change_client_secret', + client_id=client.client_id)}}" + title="Change the client secret!" + class="btn btn-danger"> + Change Secret + </a> + </td> </tr> {%else%} <tr> |