feat: Improve ease of adding a new client
All checks were successful
Build Docker / Build Docker (push) Successful in 30s

This commit is contained in:
Nathan Woodburn 2024-06-17 17:46:03 +10:00
parent 4965bda4da
commit be587b815e
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
4 changed files with 178 additions and 14 deletions

View File

@ -16,6 +16,7 @@ from requests_doh import DNSOverHTTPSSession, add_dns_provider
from datetime import timedelta from datetime import timedelta
from eth_account.messages import encode_defunct from eth_account.messages import encode_defunct
from eth_account import Account from eth_account import Account
import json
@ -380,7 +381,7 @@ def create_client():
"grant_types": split_by_crlf(form["grant_type"]), "grant_types": split_by_crlf(form["grant_type"]),
"redirect_uris": split_by_crlf(form["redirect_uri"]), "redirect_uris": split_by_crlf(form["redirect_uri"]),
"response_types": split_by_crlf(form["response_type"]), "response_types": split_by_crlf(form["response_type"]),
"scope": form["scope"], "scope": " ".join(form.getlist("scope")),
"token_endpoint_auth_method": form["token_endpoint_auth_method"], "token_endpoint_auth_method": form["token_endpoint_auth_method"],
} }
client.set_client_metadata(client_metadata) client.set_client_metadata(client_metadata)
@ -392,7 +393,27 @@ def create_client():
db.session.add(client) db.session.add(client)
db.session.commit() db.session.commit()
return redirect("/") return redirect("/client/" + client_id)
@bp.route("/client/<client_id>")
def client(client_id):
user = current_user()
if not user:
return redirect("/")
client:OAuth2Client = OAuth2Client.query.filter_by(client_id=client_id).first()
if not client:
return redirect("/")
if client.user_id != user.id and user.id != 1:
return redirect("/")
metadata = client.client_metadata
# Convert metadata to json
metadata = json.dumps(metadata, indent=4)
return render_template("client.html", client=metadata,id=client_id,
secret=client.client_secret)
@bp.route("/delete_client") @bp.route("/delete_client")
@ -400,14 +421,18 @@ def delete_client():
user = current_user() user = current_user()
if not user: if not user:
return redirect("/") return redirect("/")
if user.id != 1:
return redirect("/")
client_id = request.args.get("client_id") client_id = request.args.get("client_id")
client = OAuth2Client.query.filter_by(client_id=client_id).first() client:OAuth2Client = OAuth2Client.query.filter_by(client_id=client_id).first()
if client:
db.session.delete(client) if not client:
db.session.commit() return redirect("/")
if client.user_id != user.id and user.id != 1:
return redirect("/")
db.session.delete(client)
db.session.commit()
return redirect("/") return redirect("/")

View File

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HNS Login</title>
<link rel="icon" href="/favicon.png" type="image/png">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
/* Dark theme*/
background-color: #222;
color: #fff;
}
h1 {
margin: 0;
padding: 20px;
background-color: #333;
color: #fff;
text-align: center;
}
h2 {
margin: 0;
padding: 20px;
text-align: center;
}
p {
margin: 0;
padding: 20px;
text-align: center;
}
form {
text-align: center;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
}
a.button {
display: block;
width: 200px;
margin: 20px auto;
padding: 10px 20px;
font-size: 16px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
text-align: center;
text-decoration: none;
}
a {
color: white;
}
button.loginbutton {
/* Put in the centre of the screen */
margin-left: 50%;
margin-top: 20px;
transform: translateX(-50%);
}
.login-option {
margin-top: 20px;
}
select {
padding: 10px 20px;
font-size: 16px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
margin-right: 25px;
}
.centre {
display: block;
text-align: center;
}
input {
padding: 10px 20px;
font-size: 16px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
margin-right: 25px;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
<h1>HNS Login</h1>
<h2>Client Information</h2>
<p>Client ID: {{id}}</p>
<p>Client Secret: {{secret}}</p>
<h3 style="text-align: center;">URLS</h3>
<p>Authorization URL: <a href="{{url_for('.authorize')}}">{{url_for('.authorize',_external=True)}}</a></p>
<p>Token URL: <a href="{{url_for('.issue_token')}}">{{url_for('.issue_token',_external=True)}}</a></p>
<p>Revoke URL: <a href="{{url_for('.revoke_token')}}">{{url_for('.revoke_token',_external=True)}}</a></p>
<p>Discovery URL: <a href="{{url_for('.autodiscovery')}}">{{url_for('.autodiscovery',_external=True)}}</a></p>
<br>
<a href="{{url_for('.delete_client',client_id=id)}}" class="button">Delete Client</a>
<div style="position: fixed; bottom: 0; width: 100%; text-align: center; background-color: #333; padding: 10px;">
Powered by <a href="https://auth.varo.domains/implement" target="_blank">Varo Auth</a>, <a href="https://hns.id/"
target="_blank">HNS.ID</a> and <a href="https://nathan.woodburn.au" target="_blank">Nathan.Woodburn/</a>
</div>
<div style="height: 5em;"></div>
</body>
</html>

View File

@ -58,7 +58,7 @@
<a href="/"><h1>Home</h1></a> <a href="/"><h1>Home</h1></a>
<h2>Create OAuth Client</h2> <h2>Create an OAuth Client</h2>
<form action="" method="post"> <form action="" method="post">
<label> <label>
@ -71,7 +71,13 @@
</label> </label>
<label> <label>
<span>Allowed Scope</span> <span>Allowed Scope</span>
<input type="text" name="scope"> <label>
<input type="checkbox" name="scope" value="profile" checked>Profile</label>
<label>
<input type="checkbox" name="scope" value="email" checked>Email</label>
<label>
<input type="checkbox" name="scope" value="openid" checked>OpenID</label>
</label> </label>
<label> <label>
<span>Redirect URIs</span> <span>Redirect URIs</span>
@ -79,17 +85,17 @@
</label> </label>
<label> <label>
<span>Allowed Grant Types</span> <span>Allowed Grant Types</span>
<textarea name="grant_type" cols="30" rows="10"></textarea> <textarea name="grant_type" cols="30" rows="10">authorization_code</textarea>
</label> </label>
<label> <label>
<span>Allowed Response Types</span> <span>Allowed Response Types</span>
<textarea name="response_type" cols="30" rows="10"></textarea> <textarea name="response_type" cols="30" rows="10">code</textarea>
</label> </label>
<label> <label>
<span>Token Endpoint Auth Method</span> <span>Token Endpoint Auth Method</span>
<select name="token_endpoint_auth_method"> <select name="token_endpoint_auth_method">
<option value="client_secret_basic">client_secret_basic</option>
<option value="client_secret_post">client_secret_post</option> <option value="client_secret_post">client_secret_post</option>
<option value="client_secret_basic">client_secret_basic</option>
<option value="none">none</option> <option value="none">none</option>
</select> </select>
</label> </label>

View File

@ -117,6 +117,7 @@
<a href="{{ url_for('.logout') }}" class="button">Log Out</a> <a href="{{ url_for('.logout') }}" class="button">Log Out</a>
<a href="{{ url_for('.create_client') }}" class="button">Create an OAuth client</a>
{% for client in clients %} {% for client in clients %}
<pre> <pre>
@ -188,6 +189,7 @@
<form action="/txt?next={{ next }}" method="post"> <form action="/txt?next={{ next }}" method="post">
<input type="text" name="domain" placeholder="Enter your domain"> <input type="text" name="domain" placeholder="Enter your domain">
<button type="submit">Login</button> <button type="submit">Login</button>
</form>
</div> </div>
</div> </div>
@ -277,7 +279,7 @@
<option value="{{nft.name}}">{{nft.name}}</option> <option value="{{nft.name}}">{{nft.name}}</option>
{% endfor %} {% endfor %}
</select> </select>
<button onclick="HNSIDLoginSelect()">Login</button> <button onclick="HNSIDLoginSelect();">Login</button>
</div> </div>
<script> <script>
function HNSIDLoginSelect() { function HNSIDLoginSelect() {