Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 & devise_ldap_authenticatable: Authorization against Active Directory?

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.

like image 393
tschlein Avatar asked Feb 10 '12 14:02

tschlein


People also ask

Does Rails 7 require Ruby 3?

Rails 7 requires Ruby 2.7. 0 or newer. Rails 6 requires Ruby 2.5.

Is Rails 7 released?

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,...

Does Rails 5.2 support Ruby 3?

Ruby 3 is only compatible with Rails 6.0.

Does Rails work with Ruby 3?

Rails 7.0. 1 is compatible with Ruby 3.1.


2 Answers

Note: Adding an answer on behalf of the OP (@kwirschau)


  1. Change 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
  2. Change 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
# [ ... ]
like image 153
4 revs, 2 users 86% Avatar answered Nov 02 '22 06:11

4 revs, 2 users 86%


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)
like image 38
Roger Garza Avatar answered Nov 02 '22 06:11

Roger Garza