v0.23.2 // (AD) LDAP & "Default user role"... also, multiple ldap_user_filter entries? #785

Closed
opened 2026-02-04 22:17:00 +03:00 by OVERLORD · 5 comments
Owner

Originally created by @derek-shnosh on GitHub (Aug 20, 2018).

Disclosure

I wasn't sure how to submit this, as a request or as a bug, so please flag accordingly. I have concerns/questions regarding using LDAP integration with AD. I may have overlooked something that's just not registering with me right now because my head is so deep in the weeds.

Goal

Match user roles to security groups without manually entering them in the admin UI. If the LDAP user is not a member of a group name matching any of the roles, then login should not be permitted.

Meat n' Potatoes

I'm not sure if this is more a BookStack concern or a MSFT concern, but are groups supported in the ldap_user_filter entries?

I see that adding users individually to the ldap_user_filter is supported, per @ssddanbrown's comment on issue #971 (reference).

Based on based on this, I don't think its an MSFT concern since we're running Server 2016 in our environment (domain function level 2012).

Active Directory in Windows 2000 operating system does not implement three-value logic for search filter evaluation as defined in [RFC2251] section 4.5.1. In Windows 2000, filters evaluate to either "true" or "false". Filters that would evaluate to "Undefined", as per the RFC, are instead evaluated to "false". Active Directory in Windows Server 2003 operating system and later uses three-value logic for evaluating search filters, in conformance with the RFC.

Observation

  • It seems that this is at least partially working, as;
    • I can successfully authenticate to a user found in either of my two configured ldap_user_filter entries.
    • I cannot authenticate to any other user (desired result) .
  • However it seems that the Default user role after registration setting is being applied to LDAP users at first time login.
  • So it seems logical to deduce that the group name is not being appropriately matched when two ldap_user_filter entries exist.

Example

If the default role is configured to Docs_Public and a user in the group Docs_Viewer logs in for the first time, they are incorrectly assigned the Docs_Public role.

User AD Group Role Assigned
test Docs_Viewer Docs_Public

Validation

$ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D docssvc@domain.local -W | grep memberOf
Enter LDAP Password: 
memberOf: CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Result

image

Configuration Details

Detail -
BookStack Version 0.23.2
PHP Version PHP 7.2.7-0ubuntu0.18.04.2
Hosting Method Apache (install script)

File /.env

# General auth
AUTH_METHOD=ldap

# LDAP Settings
LDAP_SERVER=dc.domain.local
LDAP_BASE_DN="OU=corp,DC=domain,DC=local"
LDAP_DN="CN=docs service,OU=service accounts,OU=corp,DC=domain,DC=local"
LDAP_PASS=*****
LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))"
LDAP_VERSION=3
# Do you want to sync LDAP groups to BookStack roles for a user
LDAP_USER_TO_GROUPS=true
# What is the LDAP attribute for group memberships
LDAP_GROUP_ATTRIBUTE="memberOf"
# Would you like to remove users from roles on BookStack if they do not match on LDAP
# If false, the ldap groups-roles sync will only add users to roles
LDAP_REMOVE_FROM_GROUPS=false

Notes

  • I tried changing the ldap_user_filter to use (objectClass=user) instead of (sAMAccountName=${user}), but then I can't even complete the first login.
  • It does not matter which order I arrange the groups in the LDAP_USER_FILTER string, the end result is the same.
Originally created by @derek-shnosh on GitHub (Aug 20, 2018). ## Disclosure I wasn't sure how to submit this, as a request or as a bug, so please flag accordingly. I have concerns/questions regarding using LDAP integration with AD. I may have overlooked something that's just not registering with me right now because my head is so deep in the weeds. ## Goal Match user roles to security groups without manually entering them in the admin UI. If the LDAP user is not a member of a group name matching any of the roles, then login should not be permitted. ## Meat n' Potatoes I'm not sure if this is more a BookStack concern or a MSFT concern, **but are groups supported in the `ldap_user_filter` entries?** I see that adding users individually to the `ldap_user_filter` is supported, per @ssddanbrown's comment on issue #971 ([reference](971#issuecomment-414128685)). Based on based on [this](https://msdn.microsoft.com/en-us/library/cc223241.aspx), I don't think its an MSFT concern since we're running Server 2016 in our environment (domain function level 2012). > Active Directory in Windows 2000 operating system does not implement three-value logic for search filter evaluation as defined in [RFC2251] section 4.5.1. In Windows 2000, filters evaluate to either "true" or "false". Filters that would evaluate to "Undefined", as per the RFC, are instead evaluated to "false". **Active Directory in Windows Server 2003 operating system and later uses three-value logic for evaluating search filters, in conformance with the RFC.** ### Observation - It seems that this is at least partially working, as; - I can successfully authenticate to a user found in either of my two configured `ldap_user_filter` entries. - I cannot authenticate to any other user (desired result) . - However it seems that the _Default user role after registration_ setting is being applied to LDAP users at first time login. - So it seems logical to deduce that the group name is not being appropriately matched when two `ldap_user_filter` entries exist. ### Example If the default role is configured to **Docs_Public** and a user in the group **Docs_Viewer** logs in for the first time, they are incorrectly assigned the **Docs_Public** role. |User|AD Group|Role Assigned |-|-|- |test|Docs_Viewer|*Docs_Public* #### *Validation* ```bash $ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D docssvc@domain.local -W | grep memberOf Enter LDAP Password: memberOf: CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local ``` #### Result ![image](https://user-images.githubusercontent.com/21090563/44360755-b254e280-a470-11e8-9f8d-20180364a0d4.png) ### Configuration Details |Detail|- |-|- |BookStack Version|0.23.2 |PHP Version|PHP 7.2.7-0ubuntu0.18.04.2 |Hosting Method|Apache (install script) File `/.env` ```bash # General auth AUTH_METHOD=ldap # LDAP Settings LDAP_SERVER=dc.domain.local LDAP_BASE_DN="OU=corp,DC=domain,DC=local" LDAP_DN="CN=docs service,OU=service accounts,OU=corp,DC=domain,DC=local" LDAP_PASS=***** LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))" LDAP_VERSION=3 # Do you want to sync LDAP groups to BookStack roles for a user LDAP_USER_TO_GROUPS=true # What is the LDAP attribute for group memberships LDAP_GROUP_ATTRIBUTE="memberOf" # Would you like to remove users from roles on BookStack if they do not match on LDAP # If false, the ldap groups-roles sync will only add users to roles LDAP_REMOVE_FROM_GROUPS=false ``` #### Notes - I tried changing the `ldap_user_filter` to use `(objectClass=user)` instead of `(sAMAccountName=${user})`, but then I can't even complete the first login. - It does not matter which order I arrange the groups in the `LDAP_USER_FILTER` string, the end result is the same.
OVERLORD added the Question label 2026-02-04 22:17:00 +03:00
Author
Owner

@derek-shnosh commented on GitHub (Aug 21, 2018):

Looked at this again with a semi-clear head and thought the LDAP_REMOVE_FROM_GROUPS configuration set to true might accomplish what I want to do.

  1. I turned that option on and tried to log into an LDAP user who had already been assigned the Docs_Admin role via LDAP match (the same user I've been using to admin thus far).

    • I was able to log in, but I wasn't an admin anymore.
  2. I then tried to log into a new LDAP (added to the Docs_Admin AD group).

    • I was able to log in, but was not an admin.
  3. I set the AUTH_METHOD=standard and logged in with a local user and was able to confirm both LDAP matched accounts were now assigned the Docs_Public role.

I re-ran the ldapsearch again (each time) for good measure and the Docs_Admin group was returned successfully.

$ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D docssvc@domain.local -W | grep memberOf
Enter LDAP Password: 
memberOf: CN=Docs_Admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Maybe this is a bug? or my head isn't as clear as I thought it was and I'm still missing something.

@derek-shnosh commented on GitHub (Aug 21, 2018): Looked at this again with a semi-clear head and thought the `LDAP_REMOVE_FROM_GROUPS` configuration set to `true` might accomplish what I want to do. 1. I turned that option on and tried to log into an LDAP user who had already been assigned the `Docs_Admin` role via LDAP match (the same user I've been using to admin thus far). - I was able to log in, **but I wasn't an admin anymore.** 2. I then tried to log into a new LDAP (added to the `Docs_Admin` AD group). - I was able to log in, **but was not an admin.** 3. I set the `AUTH_METHOD=standard` and logged in with a _local_ user and was able to confirm both LDAP matched accounts were now assigned the `Docs_Public` role. I re-ran the `ldapsearch` again (each time) for good measure and the `Docs_Admin` group was returned successfully. ```bash $ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D docssvc@domain.local -W | grep memberOf Enter LDAP Password: memberOf: CN=Docs_Admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local ``` Maybe this is a bug? <sup>or my head isn't as clear as I thought it was and I'm still missing something.</sup>
Author
Owner

@derek-shnosh commented on GitHub (Aug 21, 2018):

I took one last stab and added the DN for the Docs_Admin AD group to the Docs_Admin role under External Authentication IDs: CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local

I created another test user and was still assigned the Doc_Public role upon first login; as a reminder, the Doc_Public role is configured as the Default user role after registration in the app settings.

@derek-shnosh commented on GitHub (Aug 21, 2018): I took one last stab and added the DN for the `Docs_Admin` _AD group_ to the `Docs_Admin` role under _External Authentication IDs_: `CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local` I created another test user and was still assigned the `Doc_Public` role upon first login; as a reminder, the `Doc_Public` role is configured as the _Default user role after registration_ in the app settings.
Author
Owner

@ssddanbrown commented on GitHub (Sep 23, 2018):

Hi @derek-shnosh, Sorry for the lack of reply. I had missed this issue before so sorry if it's too late.
The above is quite a lot to take in and I'm not really certain what the issue is but hopefully this helps:

Ldap Group Sync Logic with 'remove_from_groups' Enabled

  • Upon every login
  • BookStack will talk to LDAP using user_filter & provided credentials and will reject login if user not found or if cannot bind to user dn with the given password.
  • BookStack will fetch groups for the user from LDAP.
  • LDAP groups are matched up with roles.
    • This is based on the role name and the first component of the LDAP group DN (Usually the CN).
    • If the role has a 'external auth id' value there are split out on comma and used to match instead of the role name.
  • Existing BookStack roles are removed and the found roles are added.
  • The default registration role is attached to the user if not already added.

I've bolded the part that may be relevant from reading the above. I think you may just need to set the External Authentication Ids of the bookstack admin role to be docs_admin instead of the whole DN.

Let me know if that helps or if I've missed the mark.

@ssddanbrown commented on GitHub (Sep 23, 2018): Hi @derek-shnosh, Sorry for the lack of reply. I had missed this issue before so sorry if it's too late. The above is quite a lot to take in and I'm not really certain what the issue is but hopefully this helps: ### Ldap Group Sync Logic with 'remove_from_groups' Enabled - Upon every login - BookStack will talk to LDAP using user_filter & provided credentials and will reject login if user not found or if cannot bind to user dn with the given password. - BookStack will fetch groups for the user from LDAP. - LDAP groups are matched up with roles. - This is based on the role name and the **first component of the LDAP group DN (Usually the CN)**. - If the role has a 'external auth id' value there are split out on comma and used to match instead of the role name. - Existing BookStack roles are removed and the found roles are added. - The default registration role is attached to the user if not already added. --- I've bolded the part that may be relevant from reading the above. I think you may just need to set the `External Authentication Ids` of the bookstack admin role to be `docs_admin` instead of the whole DN. Let me know if that helps or if I've missed the mark.
Author
Owner

@derek-shnosh commented on GitHub (Sep 25, 2018):

Thanks for the response @ssddanbrown.

Here is my LDAP_USER_FILTER, and how it is broken down;

LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))"

LDAP_USER FILTER objects;

  • sAMAccountName=${user}
  • memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local
  • memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Per the documentation;

BookStack has the ability to sync LDAP user groups with BookStack roles. By default this will match LDAP group names with the BookStack role display names with casing ignored.

Hopefully I'm interpreting this correctly; i.e. (providing the account was found within any of the groups configured in the LDAP_USER_FILTER and BookStack was able to bind to the user DN) a user account that is a member of the AD group Docs_Admin should be assigned the BookStack user role Docs_Admin without entering docs_admin in the External Authentication ID field; correct?

@derek-shnosh commented on GitHub (Sep 25, 2018): Thanks for the response @ssddanbrown. Here is my LDAP_USER_FILTER, and how it is broken down; ```bash LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))" ``` **LDAP_USER FILTER objects;** * `sAMAccountName=${user}` * `memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local` * `memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local` Per the documentation; > BookStack has the ability to sync LDAP user groups with BookStack roles. By default this will match LDAP group names with the BookStack role display names with casing ignored. Hopefully I'm interpreting this correctly; i.e. (providing the account was found within any of the groups configured in the `LDAP_USER_FILTER` and BookStack was able to bind to the user DN) a user account that is a member of the AD group **Docs_Admin** should be assigned the BookStack user role **Docs_Admin** without entering `docs_admin` in the *External Authentication ID* field; correct?
Author
Owner

@derek-shnosh commented on GitHub (Sep 25, 2018):

I did some experimenting this morning and have things working.

My interpretation of the LDAP authentication configuration

The LDAP_USER_FILTER field defines a CN for users or groups to merely log in to BookStack. They also need to be a member of a security group whose name matches a role configured in BookStack; or the security group CN needs to be configured in the role's External Authentication ID field.

My configuration changes

  • LDAP user filter changed as follows;
    LDAP_USER_FILTER="(&(sAMAccountName=${user})(memberOf=CN=docs_login,OU=security,OU=groups,OU=corp,DC=domain,DC=local))"
    
  • Test user added to the following AD security groups (slash-delimited format);
    • domain.local/corp/groups/security/docs_login
    • domain.local/corp/groups/security/docs_admin

Results

  • The user was able to log in and was assigned the Docs_Admin role.
  • I created docs_editor and docs_viewer security groups and tested logging out and back in after moving the user between groups and the user was reassigned to roles as expected (with the LDAP_REMOVE_FROM_GROUPS=true set in .env).
  • I was also able to prevent the test user from logging in by removing it from the docs_login group.

I am confused as to why my previous configuration didn't work, because my test account was a member of the AD security group Docs_Admin which was defined in my LDAP_USER_FILTER string; so theoretically it should have worked. However, I'm not too concerned about it because it's working as desired/intended now, so I'll close this one out.

@derek-shnosh commented on GitHub (Sep 25, 2018): I did some experimenting this morning and have things working. #### My interpretation of the LDAP authentication configuration The `LDAP_USER_FILTER` field defines a CN for users or groups to merely _log in_ to BookStack. They also need to be a member of a security group whose name matches a role configured in BookStack; or the security group CN needs to be configured in the role's *External Authentication ID* field. #### My configuration changes * LDAP user filter changed as follows; ```bash LDAP_USER_FILTER="(&(sAMAccountName=${user})(memberOf=CN=docs_login,OU=security,OU=groups,OU=corp,DC=domain,DC=local))" ``` * Test user added to the following AD security groups (slash-delimited format); * **domain.local/corp/groups/security/docs_login** * **domain.local/corp/groups/security/docs_admin** #### Results * The user was able to log in and was assigned the **Docs_Admin** role. * I created **docs_editor** and **docs_viewer** security groups and tested logging out and back in after moving the user between groups and the user was reassigned to roles as expected (with the `LDAP_REMOVE_FROM_GROUPS=true` set in **.env**). * I was also able to prevent the test user from logging in by removing it from the **docs_login** group. I am confused as to why my previous configuration didn't work, because my test account was a member of the AD security group **Docs_Admin** which was defined in my `LDAP_USER_FILTER` string; so theoretically it should have worked. However, I'm not too concerned about it because it's working as desired/intended now, so I'll close this one out.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/BookStack#785