Add scope management to self-service portal

master
informatic 2020-05-25 22:57:17 +02:00
parent 54e1ba0608
commit 3daace694e
5 changed files with 30 additions and 10 deletions

View File

@ -53,3 +53,10 @@ class ClientForm(FlaskForm):
choices=[("client_secret_basic", "Basic"), ("client_secret_post", "POST")],
validators=[DataRequired()],
)
scope = MultiCheckboxField(
"Allowed scopes",
choices=[("profile:read", "profile:read"), ("openid", "openid")],
validators=[DataRequired()],
default=["openid"],
)

View File

@ -3,6 +3,7 @@ from authlib.integrations.sqla_oauth2 import (
OAuth2TokenMixin,
OAuth2AuthorizationCodeMixin,
)
from authlib.oauth2.rfc6749.util import scope_to_list, list_to_scope
from sso.extensions import db
from sso.directory import LDAPUserProxy
@ -14,6 +15,20 @@ class Client(db.Model, OAuth2ClientMixin):
owner_id = db.Column(db.String(40), nullable=True)
def __repr__(self):
return "<Client %s>" % (self.client_id,)
@property
def scope(self):
return self.client_metadata.get("scope", [])
def get_allowed_scope(self, scope):
if not scope:
return ""
allowed = set(self.scope)
scopes = scope_to_list(scope)
return list_to_scope([s for s in scopes if s in allowed])
class AuthorizationCode(db.Model, OAuth2AuthorizationCodeMixin):
__tablename__ = "oauth2_code"

View File

@ -79,7 +79,7 @@ class OpenIDCode(_OpenIDCode):
return exists_nonce(nonce, request)
def get_jwt_config(self, grant):
return app.get('JWT_CONFIG')
return app.config.get("JWT_CONFIG")
def generate_user_info(self, user, scope):
return generate_user_info(user, scope)
@ -90,7 +90,7 @@ class ImplicitGrant(_OpenIDImplicitGrant):
return exists_nonce(nonce, request)
def get_jwt_config(self, grant):
return app.get('JWT_CONFIG')
return app.config.get("JWT_CONFIG")
def generate_user_info(self, user, scope):
return generate_user_info(user, scope)
@ -113,6 +113,7 @@ class HybridGrant(_OpenIDHybridGrant):
authorization = AuthorizationServer()
require_oauth = ResourceProtector()
def save_token(token, request):
if request.user:
user_id = request.user.get_user_id()
@ -122,21 +123,17 @@ def save_token(token, request):
# FIXME: is this the correct way of handling this? left for backward
# compatiblity
toks = Token.query.filter_by(client_id=client.client_id,
user_id=user_id)
toks = Token.query.filter_by(client_id=client.client_id, user_id=user_id)
# make sure that every client has only one token connected to a user
for t in toks:
db.session.delete(t)
item = Token(
client_id=client.client_id,
user_id=user_id,
**token
)
item = Token(client_id=client.client_id, user_id=user_id, **token)
db.session.add(item)
db.session.commit()
def config_oauth(app):
query_client = create_query_client_func(db.session, Client)
authorization.init_app(app, query_client=query_client, save_token=save_token)

View File

@ -24,6 +24,7 @@
{{ render_field(form.token_endpoint_auth_method) }}
{{ render_field(form.grant_types) }}
{{ render_field(form.response_types) }}
{{ render_field(form.scope) }}
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<button type="submit" class="btn btn-primary btn-block">Save</button>

View File

@ -51,7 +51,7 @@
</thead>
<tbody>
{% for client in clients %}
<tr><td>{{ client.client_name }}</td><td><a href="{{ url_for('.client_edit', client_id=client.id) }}" class="btn btn-xs btn-warning">Edit</a></td></tr>
<tr><td>{{ client.client_name }}</td><td class="text-right"><a href="{{ url_for('.client_edit', client_id=client.id) }}" class="btn btn-xs btn-warning">Edit</a></td></tr>
{% else %}
<tr><td colspan=4 class="placeholder">No registered applications yet</td></tr>
{% endfor %}