I successfully have my Rails 3 app running with devise and devise_ldap_authenticatable to authenticate against the local Active Directory.
Now I want to add authorization capabilities in order to allow access only to AD users that belong to certain AD groups.
So to start simple, I first have looked up my own user in AD with the linux command ldapsearch. The result contained something like ...
(...)
memberOf: CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
memberOf: CN=my,OU=foo,DC=bar2,DC=role,DC=domain,DC=com
memberOf: (...)
(...)
Ok, now I decided, that I want to restrict access to members of CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com.
So, I changed my ldap.yml to contain:
authorizations: &AUTHORIZATIONS
group_base: ou=role,dc=domain,dc=com
required_groups:
- CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
development:
(...)
<<: *AUTHORIZATIONS
And in addition changed my devise.rb to contain:
Devise.setup do |config|
config.ldap_logger = true
config.ldap_create_user = true
config.ldap_update_password = false
config.ldap_check_group_membership = true # <-- activated this line
config.ldap_use_admin_to_bind = true
#config.ldap_ad_group_check = true <-- don't know what this is good for
Now, when trying to authenticate, access is denied, which I did not expect:
User CN=myuser,OU=org,DC=domain,DC=com is not in group: CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
Any idea, how authorization against AD is accomplished with devise_ldap_authenticatable? The documentation of this module is not yet that comprehensive when it comes to authorization.
Rails 7 requires Ruby 2.7. 0 or newer. Rails 6 requires Ruby 2.5.
September 15, 2021 Welcome to the first alpha release of Rails 7. It brings some very exciting new answers to how we do JavaScript, an awesome approach to at-work encryption with Active Record,...
Ruby 3 is only compatible with Rails 6.0.
Rails 7.0. 1 is compatible with Ruby 3.1.
Note: Adding an answer on behalf of the OP (@kwirschau)
devise.rb
to activate the attribute ldap_check_attributes
and remove/comment out ldap_check_group
as it does not check against the AD-specific attribute memberOf
ldap.yml
and comment out group_base
and required_groups
. Add the required group membership to require_attribute
.In summary, the setup for the example in the question looks like this:
# devise.rb
Devise.setup do |config|
# [ ... ]
config.ldap_check_attributes = true
# [ ... ]
end
and
# ldap.yml
# [ ... ]
authorizations: &AUTHORIZATIONS
#group_base: ou=role,dc=domain,dc=com
#required_groups:
# - CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
require_attribute:
memberOf: CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
# [ ... ]
So, the answer by zekus will only work if the user is directly a member of the given group. It will not search groups recursively. kwirschau, you were almost there with your initial configuration. You stated:
"#config.ldap_ad_group_check = true <-- don't know what this is good for"
When that flag is set, the ldap query will search nested groups by using a filter with the LDAP_MATCHING_RULE_IN_CHAIN rule, which searches the user's groups recursively.
Thus, in your devise.rb, set:
config.ldap_check_group_membership = true
config.ldap_use_admin_to_bind = true
config.ldap_ad_group_check = true
Set your authorization group in your ldap.yml
authorizations: &AUTHORIZATIONS
group_base: ou=role,dc=domain,dc=com
required_groups:
- CN=my,OU=foo,DC=bar,DC=role,DC=domain,DC=com
Additionally, in your code, if you want to check a user against another group, don't use "memberOf", as this will not search nested groups. Instead, use:
ldap_connect = Devise::LdapAdapter.ldap_connect(username)
ldap_connect.in_group?(group_name)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With