Bumped to authlib 1

This commit is contained in:
Éloi Rivard 2022-04-10 16:00:51 +02:00
parent 723c697c86
commit a1c4f7a278
11 changed files with 39 additions and 25 deletions

View file

@ -11,6 +11,7 @@ Added
- ``DISABLE_PASSWORD_RESET`` configuration option to disable password recovery. :pr:`46`
- ``edit_self`` ACL permission to control user self edition. :pr:`47`
- Bumped to authlib 1 :pr:`48`
Fixed
*****

View file

@ -146,6 +146,8 @@ WRITE = ["groups"]
PRIVATE_KEY = "canaille/conf/private.pem"
# The path to the public key.
PUBLIC_KEY = "canaille/conf/public.pem"
# The URI of the identity provider
ISS = "https://auth.mydomain.tld"
# The key type parameter
# KTY = "RSA"
# The key algorithm

View file

@ -37,9 +37,6 @@ class Client(LDAPObject, ClientMixin):
"preconsent": "oauthPreconsent",
}
def get_client_id(self):
return self.id
def get_default_redirect_uri(self):
return self.redirect_uris[0]
@ -55,8 +52,10 @@ class Client(LDAPObject, ClientMixin):
def check_client_secret(self, client_secret):
return client_secret == self.secret
def check_token_endpoint_auth_method(self, method):
return method == self.token_endpoint_auth_method
def check_endpoint_auth_method(self, method, endpoint):
if endpoint == "token":
return method == self.token_endpoint_auth_method
return True
def check_response_type(self, response_type):
return all(r in self.response_type for r in response_type.split(" "))
@ -141,9 +140,6 @@ class Token(LDAPObject, TokenMixin):
def revoked(self):
return bool(self.revokation_date)
def get_client_id(self):
return Client.get(self.client).id
def get_scope(self):
return " ".join(self.scope)
@ -171,6 +167,12 @@ class Token(LDAPObject, TokenMixin):
< datetime.datetime.now()
)
def is_revoked(self):
return bool(self.revokation_date)
def check_client(self, client):
return client.client_id == Client.get(self.client).client_id
class Consent(LDAPObject):
object_class = ["oauthConsent"]

View file

@ -103,7 +103,7 @@ def authorize():
return jsonify(response)
try:
grant = authorization.validate_consent_request(end_user=user)
grant = authorization.get_consent_grant(end_user=user)
except OAuth2Error as error:
response = dict(error.get_body())
current_app.logger.debug("authorization endpoint response: %s", response)

View file

@ -45,7 +45,7 @@ def get_jwt_config(grant):
return {
"key": pk.read(),
"alg": current_app.config["JWT"].get("ALG", DEFAULT_JWT_ALG),
"iss": authorization.metadata["issuer"],
"iss": current_app.config["JWT"]["ISS"],
"exp": current_app.config["JWT"].get("EXP", DEFAULT_JWT_EXP),
}
@ -250,29 +250,30 @@ class BearerTokenValidator(_BearerTokenValidator):
class RevocationEndpoint(_RevocationEndpoint):
def query_token(self, token, token_type_hint, client):
def query_token(self, token, token_type_hint):
print("query_token")
if token_type_hint == "access_token":
return Token.filter(client=client.dn, access_token=token)
return Token.filter(access_token=token)
elif token_type_hint == "refresh_token":
return Token.filter(client=client.dn, refresh_token=token)
return Token.filter(refresh_token=token)
item = Token.filter(client=client.dn, access_token=token)
item = Token.filter(access_token=token)
if item:
return item[0]
item = Token.filter(client=client.dn, refresh_token=token)
item = Token.filter(refresh_token=token)
if item:
return item[0]
return None
def revoke_token(self, token):
def revoke_token(self, token, request):
token.revokation_date = datetime.datetime.now()
token.save()
class IntrospectionEndpoint(_IntrospectionEndpoint):
def query_token(self, token, token_type_hint, client):
def query_token(self, token, token_type_hint):
if token_type_hint == "access_token":
tok = Token.filter(access_token=token)
elif token_type_hint == "refresh_token":
@ -281,10 +282,10 @@ class IntrospectionEndpoint(_IntrospectionEndpoint):
tok = Token.filter(access_token=token)
if not tok:
tok = Token.filter(refresh_token=token)
if tok:
tok = tok[0]
if client.dn in tok.audience:
return tok
return tok[0] if tok else None
def check_permission(self, token, client, request):
return client.dn in token.audience
def introspect_token(self, token):
client_id = Client.get(token.client).client_id
@ -298,7 +299,7 @@ class IntrospectionEndpoint(_IntrospectionEndpoint):
"scope": token.get_scope(),
"sub": user.uid[0],
"aud": audience,
"iss": authorization.metadata["issuer"],
"iss": current_app.config["JWT"]["ISS"],
"exp": token.get_expires_at(),
"iat": token.get_issued_at(),
}

View file

@ -38,8 +38,7 @@ def create_app():
@app.route("/authorize")
def authorize():
token = oauth.yaal.authorize_access_token()
userinfo = oauth.yaal.parse_id_token(token)
session["user"] = userinfo
session["user"] = token.get("userinfo")
flash("You have been successfully logged in.", "success")
return redirect(url_for("index"))

View file

@ -152,6 +152,8 @@ WRITE = ["groups"]
PRIVATE_KEY = "conf/private.pem"
# The path to the public key.
PUBLIC_KEY = "conf/public.pem"
# The URI of the identity provider
ISS = "http://localhost:5000"
# The key type parameter
# KTY = "RSA"
# The key algorithm

View file

@ -152,6 +152,8 @@ WRITE = ["groups"]
PRIVATE_KEY = "conf/private.pem"
# The path to the public key.
PUBLIC_KEY = "conf/public.pem"
# The URI of the identity provider
ISS = "http://localhost:5000"
# The key type parameter
# KTY = "RSA"
# The key algorithm

View file

@ -178,6 +178,10 @@ Canaille needs a key pair to sign the JWT. The installation command will generat
**Required.** The path to the public key.
e.g. ``/path/to/canaille/conf/private.pem``
:ISS:
**Required.** The URI of the identity provider.
e.g. ``https://auth.mydomain.tld``
:KTY:
*Optional.* The key type parameter.
Defaults to ``RSA``.

View file

@ -25,7 +25,7 @@ packages = find:
include_package_data = true
python_requires = >= 3.7
install_requires =
authlib<1
authlib>1,<2
click<9
email_validator<2
flask<3

View file

@ -184,6 +184,7 @@ def configuration(slapd_server, smtpd, keypair_path):
"JWT": {
"PUBLIC_KEY": public_key_path,
"PRIVATE_KEY": private_key_path,
"ISS": "https://mydomain.tld",
"MAPPING": {
"SUB": "{{ user.uid[0] }}",
"NAME": "{{ user.cn[0] }}",