diff --git a/canaille/ldap_backend/schemas/oauth2-openldap.ldif b/canaille/ldap_backend/schemas/oauth2-openldap.ldif index bcfb65d5..061f95b2 100644 --- a/canaille/ldap_backend/schemas/oauth2-openldap.ldif +++ b/canaille/ldap_backend/schemas/oauth2-openldap.ldif @@ -135,7 +135,6 @@ olcAttributeTypes: ( 1.3.6.1.4.1.56207.1.1.16 NAME 'oauthClientContact' ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 - SINGLE-VALUE USAGE userApplications X-ORIGIN 'OAuth 2.0' ) olcAttributeTypes: ( 1.3.6.1.4.1.56207.1.1.17 NAME 'oauthClientURI' diff --git a/canaille/ldap_backend/schemas/oauth2-openldap.schema b/canaille/ldap_backend/schemas/oauth2-openldap.schema index 46614fbf..6d8ef18f 100644 --- a/canaille/ldap_backend/schemas/oauth2-openldap.schema +++ b/canaille/ldap_backend/schemas/oauth2-openldap.schema @@ -132,7 +132,6 @@ attributetype ( 1.3.6.1.4.1.56207.1.1.16 NAME 'oauthClientContact' ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 - SINGLE-VALUE USAGE userApplications X-ORIGIN 'OAuth 2.0' ) attributetype ( 1.3.6.1.4.1.56207.1.1.17 NAME 'oauthClientURI' diff --git a/canaille/oidc/clients.py b/canaille/oidc/clients.py index 2b48b314..b06e1931 100644 --- a/canaille/oidc/clients.py +++ b/canaille/oidc/clients.py @@ -28,21 +28,21 @@ def index(user): def client_audiences(): - return [(client.dn, client.name) for client in Client.all()] + return [(client.dn, client.client_name) for client in Client.all()] class ClientAdd(FlaskForm): - name = wtforms.StringField( + client_name = wtforms.StringField( _("Name"), validators=[wtforms.validators.DataRequired()], render_kw={"placeholder": "Client Name"}, ) - contact = wtforms.EmailField( + contacts = wtforms.EmailField( _("Contact"), validators=[wtforms.validators.Optional()], render_kw={"placeholder": "admin@mydomain.tld"}, ) - uri = wtforms.URLField( + client_uri = wtforms.URLField( _("URI"), validators=[wtforms.validators.DataRequired()], render_kw={"placeholder": "https://mydomain.tld"}, @@ -57,7 +57,7 @@ class ClientAdd(FlaskForm): validators=[wtforms.validators.Optional()], render_kw={"placeholder": "https://mydomain.tld/you-have-been-disconnected"}, ) - grant_type = wtforms.SelectMultipleField( + grant_types = wtforms.SelectMultipleField( _("Grant types"), validators=[wtforms.validators.DataRequired()], choices=[ @@ -75,7 +75,7 @@ class ClientAdd(FlaskForm): default="openid profile email", render_kw={"placeholder": "openid profile"}, ) - response_type = wtforms.SelectMultipleField( + response_types = wtforms.SelectMultipleField( _("Response types"), validators=[wtforms.validators.DataRequired()], choices=[("code", "code"), ("token", "token"), ("id_token", "id_token")], @@ -127,7 +127,7 @@ class ClientAdd(FlaskForm): validators=[wtforms.validators.Optional()], render_kw={"placeholder": ""}, ) - jwk_uri = wtforms.URLField( + jwks_uri = wtforms.URLField( _("JKW URI"), validators=[wtforms.validators.Optional()], render_kw={"placeholder": ""}, @@ -162,14 +162,14 @@ def add(user): client_id_issued_at = datetime.datetime.now() client = Client( client_id=client_id, - issue_date=client_id_issued_at, - name=form["name"].data, - contact=form["contact"].data, - uri=form["uri"].data, - grant_type=form["grant_type"].data, + client_id_issued_at=client_id_issued_at, + client_name=form["client_name"].data, + contacts=[form["contacts"].data], + client_uri=form["client_uri"].data, + grant_types=form["grant_types"].data, redirect_uris=[form["redirect_uris"].data], post_logout_redirect_uris=[form["post_logout_redirect_uris"].data], - response_type=form["response_type"].data, + response_types=form["response_types"].data, scope=form["scope"].data.split(" "), token_endpoint_auth_method=form["token_endpoint_auth_method"].data, logo_uri=form["logo_uri"].data, @@ -178,9 +178,9 @@ def add(user): software_id=form["software_id"].data, software_version=form["software_version"].data, jwk=form["jwk"].data, - jwk_uri=form["jwk_uri"].data, + jwks_uri=form["jwks_uri"].data, preconsent=form["preconsent"].data, - secret="" + client_secret="" if form["token_endpoint_auth_method"].data == "none" else gen_salt(48), ) @@ -236,13 +236,13 @@ def client_edit(client_id): else: client.update( - name=form["name"].data, - contact=form["contact"].data, - uri=form["uri"].data, - grant_type=form["grant_type"].data, + client_name=form["client_name"].data, + contacts=[form["contacts"].data], + client_uri=form["client_uri"].data, + grant_types=form["grant_types"].data, redirect_uris=[form["redirect_uris"].data], post_logout_redirect_uris=[form["post_logout_redirect_uris"].data], - response_type=form["response_type"].data, + response_types=form["response_types"].data, scope=form["scope"].data.split(" "), token_endpoint_auth_method=form["token_endpoint_auth_method"].data, logo_uri=form["logo_uri"].data, @@ -251,7 +251,7 @@ def client_edit(client_id): software_id=form["software_id"].data, software_version=form["software_version"].data, jwk=form["jwk"].data, - jwk_uri=form["jwk_uri"].data, + jwks_uri=form["jwks_uri"].data, audience=form["audience"].data, preconsent=form["preconsent"].data, ) diff --git a/canaille/oidc/models.py b/canaille/oidc/models.py index 6e9f6348..c4b18acb 100644 --- a/canaille/oidc/models.py +++ b/canaille/oidc/models.py @@ -15,21 +15,21 @@ class Client(LDAPObject, ClientMixin): attribute_table = { "description": "description", "client_id": "oauthClientID", - "name": "oauthClientName", - "contact": "oauthClientContact", - "uri": "oauthClientURI", + "client_name": "oauthClientName", + "contacts": "oauthClientContact", + "client_uri": "oauthClientURI", "redirect_uris": "oauthRedirectURIs", "post_logout_redirect_uris": "oauthPostLogoutRedirectURI", "logo_uri": "oauthLogoURI", - "issue_date": "oauthIssueDate", - "secret": "oauthClientSecret", - "secret_expires_date": "oauthClientSecretExpDate", - "grant_type": "oauthGrantType", - "response_type": "oauthResponseType", + "client_id_issued_at": "oauthIssueDate", + "client_secret": "oauthClientSecret", + "client_secret_expires_date": "oauthClientSecretExpDate", + "grant_types": "oauthGrantType", + "response_types": "oauthResponseType", "scope": "oauthScope", "tos_uri": "oauthTermsOfServiceURI", "policy_uri": "oauthPolicyURI", - "jwk_uri": "oauthJWKURI", + "jwks_uri": "oauthJWKURI", "jwk": "oauthJWK", "token_endpoint_auth_method": "oauthTokenEndpointAuthMethod", "software_id": "oauthSoftwareID", @@ -50,10 +50,10 @@ class Client(LDAPObject, ClientMixin): return redirect_uri in self.redirect_uris def has_client_secret(self): - return bool(self.secret) + return bool(self.client_secret) def check_client_secret(self, client_secret): - return client_secret == self.secret + return client_secret == self.client_secret def check_endpoint_auth_method(self, method, endpoint): if endpoint == "token": @@ -61,10 +61,10 @@ class Client(LDAPObject, ClientMixin): return True def check_response_type(self, response_type): - return all(r in self.response_type for r in response_type.split(" ")) + return all(r in self.response_types for r in response_type.split(" ")) def check_grant_type(self, grant_type): - return grant_type in self.grant_type + return grant_type in self.grant_types @property def client_info(self): diff --git a/canaille/templates/oidc/admin/client_edit.html b/canaille/templates/oidc/admin/client_edit.html index 4c37d8d0..2a1a72bb 100644 --- a/canaille/templates/oidc/admin/client_edit.html +++ b/canaille/templates/oidc/admin/client_edit.html @@ -49,7 +49,7 @@
- +
diff --git a/canaille/templates/oidc/admin/client_list.html b/canaille/templates/oidc/admin/client_list.html index 5d467131..5215d272 100644 --- a/canaille/templates/oidc/admin/client_list.html +++ b/canaille/templates/oidc/admin/client_list.html @@ -35,9 +35,9 @@ {% endif %} - {{ client.name }} + {{ client.client_name }} {{ client.uri }} - {% if client.issue_date %}{{ client.issue_date }}{% endif %} + {% if client.client_id_issued_at %}{{ client.client_id_issued_at }}{% endif %} {% endfor %} diff --git a/canaille/templates/oidc/admin/token_list.html b/canaille/templates/oidc/admin/token_list.html index ec90b7ca..f526bcb0 100644 --- a/canaille/templates/oidc/admin/token_list.html +++ b/canaille/templates/oidc/admin/token_list.html @@ -29,7 +29,7 @@ - {{ client.name }} + {{ client.client_name }} diff --git a/canaille/templates/oidc/admin/token_view.html b/canaille/templates/oidc/admin/token_view.html index 4b4f08ef..9bcd9a66 100644 --- a/canaille/templates/oidc/admin/token_view.html +++ b/canaille/templates/oidc/admin/token_view.html @@ -17,7 +17,7 @@ {{ _("Client") }} - {{ token_client.name }} + {{ token_client.client_name }} @@ -46,7 +46,7 @@ {% for client in token_audience %}
  • - {{ client.name }} + {{ client.client_name }}
  • {% endfor %} diff --git a/canaille/templates/oidc/user/authorize.html b/canaille/templates/oidc/user/authorize.html index 645442ef..9e4c8a0f 100644 --- a/canaille/templates/oidc/user/authorize.html +++ b/canaille/templates/oidc/user/authorize.html @@ -3,10 +3,10 @@ {% block content %}
    {% if client.logo_uri %} - {{ client.name }} + {{ client.client_name }} {% endif %} -

    {{ gettext('The application %(name)s is requesting access to:', name=client.name) }}

    +

    {{ gettext('The application %(name)s is requesting access to:', name=client.client_name) }}

    {% for claim in grant.request.scope.split(" ") %} diff --git a/canaille/templates/oidc/user/consent_list.html b/canaille/templates/oidc/user/consent_list.html index 64153b94..f0381ccb 100644 --- a/canaille/templates/oidc/user/consent_list.html +++ b/canaille/templates/oidc/user/consent_list.html @@ -32,9 +32,9 @@ {% endif %} {% if client.uri %} - {{ client.name }} + {{ client.client_name }} {% else %} -
    {{ client.name }}
    +
    {{ client.client_name }}
    {% endif %}
    {% trans %}From:{% endtrans %} {{ consent.issue_date.strftime("%d/%m/%Y %H:%M:%S") }}
    {% if consent.revokation_date %} diff --git a/canaille/templates/oidc/user/logout.html b/canaille/templates/oidc/user/logout.html index 045034af..a9d2c76d 100644 --- a/canaille/templates/oidc/user/logout.html +++ b/canaille/templates/oidc/user/logout.html @@ -13,7 +13,7 @@

    {{ _("You are currently logged in as %(username)s.", username=user.name) }} {% if client %} - {{ _("The application %(client_name)s want to disconnect your account.", client_name=client.name) }} + {{ _("The application %(client_name)s want to disconnect your account.", client_name=client.client_name) }} {% endif %}

    diff --git a/tests/oidc/__init__.py b/tests/oidc/__init__.py index 62102100..9b6e7b01 100644 --- a/tests/oidc/__init__.py +++ b/tests/oidc/__init__.py @@ -3,5 +3,5 @@ import base64 def client_credentials(client): return base64.b64encode( - client.client_id.encode("utf-8") + b":" + client.secret.encode("utf-8") + client.client_id.encode("utf-8") + b":" + client.client_secret.encode("utf-8") ).decode("utf-8") diff --git a/tests/oidc/conftest.py b/tests/oidc/conftest.py index 2b6d9f3b..ffbeb92f 100644 --- a/tests/oidc/conftest.py +++ b/tests/oidc/conftest.py @@ -15,28 +15,28 @@ from werkzeug.security import gen_salt def client(testclient, other_client, slapd_connection): c = Client( client_id=gen_salt(24), - name="Some client", - contact="contact@mydomain.tld", - uri="https://mydomain.tld", + client_name="Some client", + contacts="contact@mydomain.tld", + client_uri="https://mydomain.tld", redirect_uris=[ "https://mydomain.tld/redirect1", "https://mydomain.tld/redirect2", ], logo_uri="https://mydomain.tld/logo.png", - issue_date=datetime.datetime.now(), - secret=gen_salt(48), - grant_type=[ + client_id_issued_at=datetime.datetime.now(), + client_secret=gen_salt(48), + grant_types=[ "password", "authorization_code", "implicit", "hybrid", "refresh_token", ], - response_type=["code", "token", "id_token"], + response_types=["code", "token", "id_token"], scope=["openid", "email", "profile", "groups", "address", "phone"], tos_uri="https://mydomain.tld/tos", policy_uri="https://mydomain.tld/policy", - jwk_uri="https://mydomain.tld/jwk", + jwks_uri="https://mydomain.tld/jwk", token_endpoint_auth_method="client_secret_basic", post_logout_redirect_uris=["https://mydomain.tld/disconnected"], ) @@ -54,28 +54,28 @@ def client(testclient, other_client, slapd_connection): def other_client(testclient, slapd_connection): c = Client( client_id=gen_salt(24), - name="Some other client", - contact="contact@myotherdomain.tld", - uri="https://myotherdomain.tld", + client_name="Some other client", + contacts="contact@myotherdomain.tld", + client_uri="https://myotherdomain.tld", redirect_uris=[ "https://myotherdomain.tld/redirect1", "https://myotherdomain.tld/redirect2", ], logo_uri="https://myotherdomain.tld/logo.png", - issue_date=datetime.datetime.now(), - secret=gen_salt(48), - grant_type=[ + client_id_issued_at=datetime.datetime.now(), + client_secret=gen_salt(48), + grant_types=[ "password", "authorization_code", "implicit", "hybrid", "refresh_token", ], - response_type=["code", "token", "id_token"], + response_types=["code", "token", "id_token"], scope=["openid", "profile", "groups"], tos_uri="https://myotherdomain.tld/tos", policy_uri="https://myotherdomain.tld/policy", - jwk_uri="https://myotherdomain.tld/jwk", + jwks_uri="https://myotherdomain.tld/jwk", token_endpoint_auth_method="client_secret_basic", post_logout_redirect_uris=["https://myotherdomain.tld/disconnected"], ) diff --git a/tests/oidc/test_client_admin.py b/tests/oidc/test_client_admin.py index 43bc922c..82080b20 100644 --- a/tests/oidc/test_client_admin.py +++ b/tests/oidc/test_client_admin.py @@ -15,19 +15,19 @@ def test_invalid_client_edition(testclient, logged_admin): def test_client_list(testclient, client, logged_admin): res = testclient.get("/admin/client") - assert client.name in res.text + assert client.client_name in res.text def test_client_add(testclient, logged_admin): res = testclient.get("/admin/client/add") data = { - "name": "foobar", - "contact": "foo@bar.com", - "uri": "https://foo.bar", + "client_name": "foobar", + "contacts": "foo@bar.com", + "client_uri": "https://foo.bar", "redirect_uris": ["https:/foo.bar/callback"], - "grant_type": ["password", "authorization_code"], + "grant_types": ["password", "authorization_code"], "scope": "openid profile", - "response_type": ["code", "token"], + "response_types": ["code", "token"], "token_endpoint_auth_method": "none", "logo_uri": "https://foo.bar/logo.png", "tos_uri": "https://foo.bar/tos", @@ -35,7 +35,7 @@ def test_client_add(testclient, logged_admin): "software_id": "software", "software_version": "1", "jwk": "jwk", - "jwk_uri": "https://foo.bar/jwks.json", + "jwks_uri": "https://foo.bar/jwks.json", "audience": [], "preconsent": False, "post_logout_redirect_uris": ["https://foo.bar/disconnected"], @@ -55,6 +55,8 @@ def test_client_add(testclient, logged_admin): assert v == " ".join(client_value) elif k == "preconsent": assert v is False + elif k == "contacts": + assert [v] == client_value else: assert v == client_value @@ -62,13 +64,13 @@ def test_client_add(testclient, logged_admin): def test_client_edit(testclient, client, logged_admin, other_client): res = testclient.get("/admin/client/edit/" + client.client_id) data = { - "name": "foobar", - "contact": "foo@bar.com", - "uri": "https://foo.bar", + "client_name": "foobar", + "contacts": "foo@bar.com", + "client_uri": "https://foo.bar", "redirect_uris": ["https:/foo.bar/callback"], - "grant_type": ["password", "authorization_code"], + "grant_types": ["password", "authorization_code"], "scope": "openid profile", - "response_type": ["code", "token"], + "response_types": ["code", "token"], "token_endpoint_auth_method": "none", "logo_uri": "https://foo.bar/logo.png", "tos_uri": "https://foo.bar/tos", @@ -76,7 +78,7 @@ def test_client_edit(testclient, client, logged_admin, other_client): "software_id": "software", "software_version": "1", "jwk": "jwk", - "jwk_uri": "https://foo.bar/jwks.json", + "jwks_uri": "https://foo.bar/jwks.json", "audience": [client.dn, other_client.dn], "preconsent": True, "post_logout_redirect_uris": ["https://foo.bar/disconnected"], @@ -96,6 +98,8 @@ def test_client_edit(testclient, client, logged_admin, other_client): assert v == " ".join(client_value) elif k == "preconsent": assert v is True + elif k == "contacts": + assert [v] == client_value else: assert v == client_value diff --git a/tests/oidc/test_consent.py b/tests/oidc/test_consent.py index 786359e6..971f75e0 100644 --- a/tests/oidc/test_consent.py +++ b/tests/oidc/test_consent.py @@ -4,13 +4,13 @@ def test_no_logged_no_access(testclient): def test_consent_list(testclient, client, consent, logged_user, token): res = testclient.get("/consent", status=200) - assert client.name in res.text + assert client.client_name in res.text assert not token.revoked res = testclient.get(f"/consent/delete/{consent.cn[0]}", status=302) res = res.follow(status=200) - assert client.name not in res.text + assert client.client_name not in res.text token.reload() assert token.revoked diff --git a/tests/oidc/test_implicit_flow.py b/tests/oidc/test_implicit_flow.py index 0c94473c..0f747e22 100644 --- a/tests/oidc/test_implicit_flow.py +++ b/tests/oidc/test_implicit_flow.py @@ -6,7 +6,7 @@ from canaille.oidc.models import Token def test_oauth_implicit(testclient, user, client): - client.grant_type = ["token"] + client.grant_types = ["token"] client.token_endpoint_auth_method = "none" client.save() @@ -48,13 +48,13 @@ def test_oauth_implicit(testclient, user, client): "family_name": "Doe", } == res.json - client.grant_type = ["code"] + client.grant_types = ["code"] client.token_endpoint_auth_method = "client_secret_basic" client.save() def test_oidc_implicit(testclient, keypair, user, client, other_client): - client.grant_type = ["token id_token"] + client.grant_types = ["token id_token"] client.token_endpoint_auth_method = "none" client.save() @@ -104,7 +104,7 @@ def test_oidc_implicit(testclient, keypair, user, client, other_client): "family_name": "Doe", } == res.json - client.grant_type = ["code"] + client.grant_types = ["code"] client.token_endpoint_auth_method = "client_secret_basic" client.save() @@ -112,7 +112,7 @@ def test_oidc_implicit(testclient, keypair, user, client, other_client): def test_oidc_implicit_with_group( testclient, keypair, user, client, foo_group, other_client ): - client.grant_type = ["token id_token"] + client.grant_types = ["token id_token"] client.token_endpoint_auth_method = "none" client.save() @@ -164,6 +164,6 @@ def test_oidc_implicit_with_group( "groups": ["foo"], } == res.json - client.grant_type = ["code"] + client.grant_types = ["code"] client.token_endpoint_auth_method = "client_secret_basic" client.save() diff --git a/tests/oidc/test_password_flow.py b/tests/oidc/test_password_flow.py index 75b198e3..8a79330d 100644 --- a/tests/oidc/test_password_flow.py +++ b/tests/oidc/test_password_flow.py @@ -48,7 +48,7 @@ def test_password_flow_post(testclient, user, client): password="correct horse battery staple", scope="openid profile groups", client_id=client.client_id, - client_secret=client.secret, + client_secret=client.client_secret, ), status=200, )