forked from Github-Mirrors/canaille
Merge branch 'issue-73-disable-oidc' into 'master'
Option to not use OIDC Closes #73 See merge request yaal/canaille!23
This commit is contained in:
commit
7091834910
7 changed files with 47 additions and 27 deletions
|
@ -82,7 +82,7 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
# You can define access controls that define what users can do on canaille
|
# You can define access controls that define what users can do on canaille
|
||||||
# An access control consists in a FILTER to match users, a list of PERMISSIONS
|
# An access control consists in a FILTER to match users, a list of PERMISSIONS
|
||||||
# matched users will be able to perform, and fields users will be able
|
# matched users will be able to perform, and fields users will be able
|
||||||
# to READ and WRITE.
|
# to READ and WRITE. Users matching several filters will cumulate permissions.
|
||||||
#
|
#
|
||||||
# A 'FILTER' parameter that is a LDAP filter used to determine if a user
|
# A 'FILTER' parameter that is a LDAP filter used to determine if a user
|
||||||
# belongs to an access control. If absent, all the users will match this
|
# belongs to an access control. If absent, all the users will match this
|
||||||
|
@ -94,9 +94,10 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
#
|
#
|
||||||
# The 'PERMISSIONS' parameter that is an list of items the users in the access
|
# The 'PERMISSIONS' parameter that is an list of items the users in the access
|
||||||
# control will be able to manage. 'PERMISSIONS' is optionnal. Values can be:
|
# control will be able to manage. 'PERMISSIONS' is optionnal. Values can be:
|
||||||
|
# - "use_oidc" to allow OpenID Connect authentication
|
||||||
|
# - "manage_oidc" to allow OpenID Connect client managements
|
||||||
# - "manage_users" to allow other users management
|
# - "manage_users" to allow other users management
|
||||||
# - "manage_groups" to allow group edition and creation
|
# - "manage_groups" to allow group edition and creation
|
||||||
# - "manage_oidc" to allow OpenID Connect client managements
|
|
||||||
# - "delete_account" allows a user to delete his own account. If used with
|
# - "delete_account" allows a user to delete his own account. If used with
|
||||||
# manage_users, the user can delete any account
|
# manage_users, the user can delete any account
|
||||||
# - "impersonate_users" to allow a user to take the identity of another user
|
# - "impersonate_users" to allow a user to take the identity of another user
|
||||||
|
@ -105,6 +106,7 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
# object that users will be able to read and/or write.
|
# object that users will be able to read and/or write.
|
||||||
[ACL.DEFAULT]
|
[ACL.DEFAULT]
|
||||||
READ = ["uid", "groups"]
|
READ = ["uid", "groups"]
|
||||||
|
PERMISSIONS = ["use_oidc"]
|
||||||
WRITE = ["givenName", "sn", "userPassword", "telephoneNumber"]
|
WRITE = ["givenName", "sn", "userPassword", "telephoneNumber"]
|
||||||
|
|
||||||
[ACL.ADMIN]
|
[ACL.ADMIN]
|
||||||
|
@ -116,8 +118,7 @@ PERMISSIONS = [
|
||||||
"delete_account",
|
"delete_account",
|
||||||
"impersonate_users",
|
"impersonate_users",
|
||||||
]
|
]
|
||||||
READ = ["uid"]
|
WRITE = ["groups"]
|
||||||
WRITE = ["groups", "givenName", "sn", "userPassword"]
|
|
||||||
|
|
||||||
# The jwt configuration. You can generate a RSA keypair with:
|
# The jwt configuration. You can generate a RSA keypair with:
|
||||||
# openssl genrsa -out private.pem 4096
|
# openssl genrsa -out private.pem 4096
|
||||||
|
|
|
@ -150,6 +150,10 @@ class User(LDAPObject):
|
||||||
self.read |= set(details.get("READ", []))
|
self.read |= set(details.get("READ", []))
|
||||||
self.write |= set(details.get("WRITE", []))
|
self.write |= set(details.get("WRITE", []))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def can_use_oidc(self):
|
||||||
|
return "use_oidc" in self.permissions
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def can_manage_users(self):
|
def can_manage_users(self):
|
||||||
return "manage_users" in self.permissions
|
return "manage_users" in self.permissions
|
||||||
|
|
|
@ -76,6 +76,9 @@ def authorize():
|
||||||
|
|
||||||
return redirect(request.url)
|
return redirect(request.url)
|
||||||
|
|
||||||
|
if not user.can_use_oidc:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
# CONSENT
|
# CONSENT
|
||||||
|
|
||||||
consents = Consent.filter(
|
consents = Consent.filter(
|
||||||
|
|
|
@ -38,11 +38,13 @@
|
||||||
<i class="id card icon"></i>
|
<i class="id card icon"></i>
|
||||||
{% trans %}My profile{% endtrans %}
|
{% trans %}My profile{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
|
{% if user.can_use_oidc %}
|
||||||
<a class="item {% if menuitem == "consents" %}active{% endif %}"
|
<a class="item {% if menuitem == "consents" %}active{% endif %}"
|
||||||
href="{{ url_for('consents.consents') }}">
|
href="{{ url_for('consents.consents') }}">
|
||||||
<i class="handshake icon"></i>
|
<i class="handshake icon"></i>
|
||||||
{% trans %}My consents{% endtrans %}
|
{% trans %}My consents{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
{% if user.can_manage_users %}
|
{% if user.can_manage_users %}
|
||||||
<a class="item {% if menuitem == "users" %}active{% endif %}"
|
<a class="item {% if menuitem == "users" %}active{% endif %}"
|
||||||
href="{{ url_for('account.users') }}">
|
href="{{ url_for('account.users') }}">
|
||||||
|
|
|
@ -84,7 +84,7 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
# You can define access controls that define what users can do on canaille
|
# You can define access controls that define what users can do on canaille
|
||||||
# An access control consists in a FILTER to match users, a list of PERMISSIONS
|
# An access control consists in a FILTER to match users, a list of PERMISSIONS
|
||||||
# matched users will be able to perform, and fields users will be able
|
# matched users will be able to perform, and fields users will be able
|
||||||
# to READ and WRITE.
|
# to READ and WRITE. Users matching several filters will cumulate permissions.
|
||||||
#
|
#
|
||||||
# A 'FILTER' parameter that is a LDAP filter used to determine if a user
|
# A 'FILTER' parameter that is a LDAP filter used to determine if a user
|
||||||
# belongs to an access control. If absent, all the users will match this
|
# belongs to an access control. If absent, all the users will match this
|
||||||
|
@ -96,9 +96,10 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
#
|
#
|
||||||
# The 'PERMISSIONS' parameter that is an list of items the users in the access
|
# The 'PERMISSIONS' parameter that is an list of items the users in the access
|
||||||
# control will be able to manage. 'PERMISSIONS' is optionnal. Values can be:
|
# control will be able to manage. 'PERMISSIONS' is optionnal. Values can be:
|
||||||
|
# - "use_oidc" to allow OpenID Connect authentication
|
||||||
|
# - "manage_oidc" to allow OpenID Connect client managements
|
||||||
# - "manage_users" to allow other users management
|
# - "manage_users" to allow other users management
|
||||||
# - "manage_groups" to allow group edition and creation
|
# - "manage_groups" to allow group edition and creation
|
||||||
# - "manage_oidc" to allow OpenID Connect client managements
|
|
||||||
# - "delete_account" allows a user to delete his own account. If used with
|
# - "delete_account" allows a user to delete his own account. If used with
|
||||||
# manage_users, the user can delete any account
|
# manage_users, the user can delete any account
|
||||||
# - "impersonate_users" to allow a user to take the identity of another user
|
# - "impersonate_users" to allow a user to take the identity of another user
|
||||||
|
@ -107,6 +108,7 @@ GROUP_USER_FILTER = "member={user.dn}"
|
||||||
# object that users will be able to read and/or write.
|
# object that users will be able to read and/or write.
|
||||||
[ACL.DEFAULT]
|
[ACL.DEFAULT]
|
||||||
READ = ["uid", "groups"]
|
READ = ["uid", "groups"]
|
||||||
|
PERMISSIONS = ["use_oidc"]
|
||||||
WRITE = ["givenName", "sn", "userPassword", "telephoneNumber"]
|
WRITE = ["givenName", "sn", "userPassword", "telephoneNumber"]
|
||||||
|
|
||||||
[ACL.ADMIN]
|
[ACL.ADMIN]
|
||||||
|
@ -118,14 +120,12 @@ PERMISSIONS = [
|
||||||
"delete_account",
|
"delete_account",
|
||||||
"impersonate_users",
|
"impersonate_users",
|
||||||
]
|
]
|
||||||
READ = ["uid"]
|
WRITE = ["groups"]
|
||||||
WRITE = ["groups", "givenName", "sn", "userPassword"]
|
|
||||||
|
|
||||||
[ACL.HALF_ADMIN]
|
[ACL.HALF_ADMIN]
|
||||||
FILTER = "memberof=cn=moderators,ou=groups,dc=mydomain,dc=tld"
|
FILTER = "memberof=cn=moderators,ou=groups,dc=mydomain,dc=tld"
|
||||||
PERMISSIONS = ["manage_users", "manage_groups", "delete_account"]
|
PERMISSIONS = ["manage_users", "manage_groups", "delete_account"]
|
||||||
READ = ["uid"]
|
WRITE = ["groups"]
|
||||||
WRITE = ["groups", "givenName", "sn", "userPassword"]
|
|
||||||
|
|
||||||
# The jwt configuration. You can generate a RSA keypair with:
|
# The jwt configuration. You can generate a RSA keypair with:
|
||||||
# openssl genrsa -out private.pem 4096
|
# openssl genrsa -out private.pem 4096
|
||||||
|
|
|
@ -147,7 +147,7 @@ def configuration(slapd_server, smtpd, keypair_path):
|
||||||
"ACL": {
|
"ACL": {
|
||||||
"DEFAULT": {
|
"DEFAULT": {
|
||||||
"READ": ["uid", "groups"],
|
"READ": ["uid", "groups"],
|
||||||
"PERMISSIONS": [],
|
"PERMISSIONS": ["use_oidc"],
|
||||||
"WRITE": [
|
"WRITE": [
|
||||||
"mail",
|
"mail",
|
||||||
"givenName",
|
"givenName",
|
||||||
|
@ -166,28 +166,14 @@ def configuration(slapd_server, smtpd, keypair_path):
|
||||||
"impersonate_users",
|
"impersonate_users",
|
||||||
"manage_groups",
|
"manage_groups",
|
||||||
],
|
],
|
||||||
"READ": ["uid"],
|
|
||||||
"WRITE": [
|
"WRITE": [
|
||||||
"mail",
|
|
||||||
"givenName",
|
|
||||||
"sn",
|
|
||||||
"userPassword",
|
|
||||||
"telephoneNumber",
|
|
||||||
"employeeNumber",
|
|
||||||
"groups",
|
"groups",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"MODERATOR": {
|
"MODERATOR": {
|
||||||
"FILTER": "(|(uid=moderator)(sn=moderator))",
|
"FILTER": "(|(uid=moderator)(sn=moderator))",
|
||||||
"PERMISSIONS": ["manage_users", "manage_groups", "delete_account"],
|
"PERMISSIONS": ["manage_users", "manage_groups", "delete_account"],
|
||||||
"READ": ["uid"],
|
|
||||||
"WRITE": [
|
"WRITE": [
|
||||||
"mail",
|
|
||||||
"givenName",
|
|
||||||
"sn",
|
|
||||||
"userPassword",
|
|
||||||
"telephoneNumber",
|
|
||||||
"employeeNumber",
|
|
||||||
"groups",
|
"groups",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -438,6 +438,30 @@ def test_authorization_code_flow_when_consent_already_given_but_for_a_smaller_sc
|
||||||
assert "groups" in consents[0].oauthScope
|
assert "groups" in consents[0].oauthScope
|
||||||
|
|
||||||
|
|
||||||
|
def test_authorization_code_flow_but_user_cannot_use_oidc(
|
||||||
|
testclient, slapd_connection, user, client, keypair, other_client
|
||||||
|
):
|
||||||
|
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = []
|
||||||
|
|
||||||
|
res = testclient.get(
|
||||||
|
"/oauth/authorize",
|
||||||
|
params=dict(
|
||||||
|
response_type="code",
|
||||||
|
client_id=client.oauthClientID,
|
||||||
|
scope="profile",
|
||||||
|
nonce="somenonce",
|
||||||
|
),
|
||||||
|
status=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
res.form["login"] = "John (johnny) Doe"
|
||||||
|
res = res.form.submit(status=200)
|
||||||
|
|
||||||
|
res.form["password"] = "correct horse battery staple"
|
||||||
|
res = res.form.submit(status=302)
|
||||||
|
res = res.follow(status=400)
|
||||||
|
|
||||||
|
|
||||||
def test_prompt_none(testclient, slapd_connection, logged_user, client):
|
def test_prompt_none(testclient, slapd_connection, logged_user, client):
|
||||||
Consent(
|
Consent(
|
||||||
oauthClient=client.dn,
|
oauthClient=client.dn,
|
||||||
|
|
Loading…
Reference in a new issue