forked from Github-Mirrors/canaille
Bumped to authlib 1
This commit is contained in:
parent
723c697c86
commit
a1c4f7a278
11 changed files with 39 additions and 25 deletions
|
@ -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
|
||||
*****
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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] }}",
|
||||
|
|
Loading…
Reference in a new issue