BookStackApp / BookStack

A platform to create documentation/wiki content built with PHP & Laravel
https://www.bookstackapp.com/
MIT License
15.21k stars 1.9k forks source link

LDAP authentication not possible #5267

Closed DaarKyns closed 1 week ago

DaarKyns commented 1 week ago

Attempted Debugging

Searched GitHub Issues

Describe the Scenario

Hello,

I'm having problems with LDAP authentication I'm using BookStack 24.02.3 on a Debian 12 with the docker image linuxserver.io (https://hub.docker.com/r/linuxserver/bookstack) installed with docker CLI, my database is separate.

When authenticating with login/password, I get this message “This information does not correspond to any account” but nothing is added to the LOG files to identify the problem.

AUTH_METHOD=ldap

# The LDAP host, Adding a port is optional
LDAP_SERVER=ldap://IP_AD_Server:389
# If using LDAP over SSL you should also define the protocol:
# LDAP_SERVER=ldaps://example.com:636

# The base DN from where users will be searched within
LDAP_BASE_DN=dc=domain,dc=lan

# The full DN and password of the user used to search the server
# Can both be left as 'false' (without quotes) to bind anonymously
LDAP_DN="cn=sa_bookstack_ad_auth,OU=1,OU=2,OU=3,DC=domain,DC=lan"
LDAP_PASS="password"

# A filter to use when searching for users
# The user-provided user-name used to replace any occurrences of '{user}'.
# (Also supported via '${user}' for backwards compatibility.
LDAP_USER_FILTER="(&(sAMAccountName={user}))"

# Set the LDAP version to use when connecting to the server
# Should be set to 3 in most cases.
LDAP_VERSION=3

# Set the property to use as a unique identifier for this user.
# Stored and used to match LDAP users with existing BookStack users.
# Prefixing the value with 'BIN;' will assume the LDAP service provides the attribute value as
# binary data and BookStack will convert the value to a hexidecimal representation.
# Defaults to 'uid'.
LDAP_ID_ATTRIBUTE=BIN;objectGUID

# Set the default 'email' attribute. Defaults to 'mail'
LDAP_EMAIL_ATTRIBUTE=mail

# Set the property to use for a user's display name. Defaults to 'cn'
LDAP_DISPLAY_NAME_ATTRIBUTE=cn

# Set the attribute to use for the user's avatar image.
# Must provide JPEG binary image data.
# Will be used upon login or registration when the user doesn't
# already have an avatar image set.
# Remove this option or set to 'null' to disable LDAP avatar import.
# LDAP_THUMBNAIL_ATTRIBUTE=jpegphoto

# Force TLS to be used for LDAP communication.
# Use this if you can but your LDAP support will need to support it and
# you may need to import your certificate to the BookStack host machine.
# Defaults to 'false'.
LDAP_START_TLS=false

# Certificate Authority Certificates to use for LDAP TLS connections.
# Generally not needed if using a publicly trusted certificates.
# Value should be a path to a specific CA certificate in pem format,
# or a directory path where certificates are named via hashes, as
# can be managed by a utility like "c_rehash".
# Defaults to 'false'.
#LDAP_TLS_CA_CERT=/etc/ldap/certs

# If you need to allow untrusted LDAPS certificates, add the below and uncomment (remove the #)
# Only set this option if debugging or you're absolutely sure it's required for your setup.
# If using php-fpm, you may want to restart it after changing this option to avoid instability.
#LDAP_TLS_INSECURE=true

# If you need to debug the details coming from your LDAP server, add the below and uncomment (remove the #)
# Only set this option if debugging since it will block logins and potentially show private details.
#LDAP_DUMP_USER_DETAILS=true

Can you help me ?

Thanks in advance.

Exact BookStack Version

BookStack 24.02.3

Log Content

No response

Hosting Environment

Debian 12 docker image : lscr.io/linuxserver/bookstack:24.02.3 PHP : 8.3.6 MariaDB : 10.11.6

ssddanbrown commented 1 week ago

Hi @DaarKyns,

When authenticating with login/password, I get this message “This information does not correspond to any account”

Can you post a screenshot of that? Just want to confirm where exactly that's appearing as that text is not an error message I remember existing.

DaarKyns commented 1 week ago

Hello @ssddanbrown,

Thanks for the quick reply. Here's the screenshot Bookstack LDAP

I tested it by installing ldapsearchon my Debian and it seems to work.

Thanks for your help

ssddanbrown commented 1 week ago

This typically means that the connection to LDAP is working, but the issue is likely one of two things:

You could try temporarily setting LDAP_DUMP_USER_DETAILS=true and see if that stops and dumps user details on login attempt. If not, then it's probably not matching any users.

Also, how exactly are you defining these options for the container?

DaarKyns commented 1 week ago

Enabling LDAP_DUMP_USER_DETAILS=true in the .env file doesn't change anything, still this message and no activity in LOG files or anywhere else.

Maybe I'm not looking in the right place ?

volume/docker/bookstack/log/bookstack/laravel.log ? volume/docker/bookstack/backups ?

I created the container using the docker CLI available at (https://hub.docker.com/r/linuxserver/bookstack)

docker run -d \
  --name=bookstack \
  -e PUID=1000 \    
  -e PGID=1000 \
  -e TZ=Etc/UTC \
  -e APP_URL=URL \
  -e DB_HOST=IP_server \
  -e DB_PORT=3306 \
  -e DB_USER=DB_user \
  -e DB_PASS=DB_password \
  -e DB_DATABASE=DB_bookstack \
  -e QUEUE_CONNECTION= `#optional` \
  -p 80:80 \
  -v /data/bookstack_config:/config \
  --restart unless-stopped \
  lscr.io/linuxserver/bookstack:24.02.3
ssddanbrown commented 1 week ago

in the .env file doesn't change anything

Generally that means that the search for the user in LDAP is not returning any results, possibly indicating a bad user filter value, bad base DN, or wrong (not matching) username value provided in the form.

no activity in LOG files or anywhere else.

I wouldn't expect any errors to be logged to log files for this.

DaarKyns commented 1 week ago

The path is /data/bookstack_config/www/.env

The name in the “User name” field is the same as the sAMAccountName value in Active Directory

ssddanbrown commented 1 week ago

Okay.

Can you try running the following exec against the running container to confirm the output:

docker exec -it bookstack php /app/www/artisan tinker --execute="dd(config('services.ldap.user_filter'))"
DaarKyns commented 1 week ago

Hello,

Here is the output of the command

"(sAMAccountName=$${user})" // vendor/psy/psysh/src/ExecutionClosure.php(40) : eval()'d code:1

ssddanbrown commented 1 week ago

@DaarKyns Okay, so that appears to be different to what you originally posted above. Can you check the option in your .env file, does the option there include any $ symbols in the value?

DaarKyns commented 1 week ago

After verification, the .env file is indeed 'LDAP_USER_FILTER=“(&(sAMAccountName={user}))”' This '(sAMAccountName=$${user})' comes from the creation of the container in docker CLI

docker run -d   
    --name=bookstack   
    -e PUID=1000   
    -e PGID=1000   
    -e TZ=Etc/UTC   
    -e APP_URL=URL   
    -e DB_HOST=IP_Server   
    -e DB_PORT=3306   
    -e DB_USER=book_user   
    -e DB_PASS=password   
    -e DB_DATABASE=bookstack   
    -e LDAP_HOST=IP_AD_Server   
    -e LDAP_BASE_DN=dc=domain,dc=lan   
    -e LDAP_USER_DN=cn=sa_bookstack_ad_auth,OU=1,OU=2,OU=3,DC=domain,DC=lan   
    -e LDAP_USER_PASSWORD=user_password
    -e LDAP_USER_FILTER='(&(sAMAccountName={user}))'   
    -p 80:80   
    -v /data/bookstack_config:/config   
    --restart unless-stopped   
    lscr.io/linuxserver/bookstack:24.02.3

I run the command : docker exec -it bookstack php /app/www/artisan tinker --execute="dd(config('services.ldap.user_filter'))"

The output is : "(&(sAMAccountName={user}))" // vendor/psy/psysh/src/ExecutionClosure.php(40) : eval()'d code:1

I'm not an expert on containerization I'm looking to see if there are multiple .env files.

find / -name ".env"

/var/lib/docker/overlay2/7aeeddb1e801ba151c7441bcaa7b290e781eeb65610bf615e464913cf290f8e3/merged/app/www/.env
/var/lib/docker/overlay2/7aeeddb1e801ba151c7441bcaa7b290e781eeb65610bf615e464913cf290f8e3/diff/app/www/.env
/data/bookstack_config/www/.env
/path/to/bookstack/config/www/.env
/user/bookstack_config/www/.env

Only one of the .env files has LDAP configuration (/data/bookstack_config/www/.env).

Sorry I'm not much help.

ssddanbrown commented 1 week ago

@DaarKyns Okay, remove all LDAP options from the container/command-line itself, and just keep to configuring LDAP options via the /data/bookstack_config/.env file, so we only have to worry about one level of configuration. Currently these command line/docker env options will be overriding anything in the .env file causing confusion.

Then test things out again.

DaarKyns commented 1 week ago

I stopped the container docker stop bookstack I delete the container docker rm bookstack I created a new container without LDAP options

docker run -d   
    --name=bookstack   
    -e PUID=1000   
    -e PGID=1000   
    -e TZ=Etc/UTC   
    -e APP_URL=URL 
    -e DB_HOST=IP_Server   
    -e DB_PORT=3306   
    -e DB_USER=book_user   
    -e DB_PASS=password   
    -e DB_DATABASE=bookstack     
    -p 80:80   
    -v /data/bookstack_config:/config   
    --restart unless-stopped   
    lscr.io/linuxserver/bookstack:24.02.3

I deleted the other .env files, leaving only the /data file.

I run the command docker exec -it bookstack php /app/www/artisan tinker --execute="dd(config('services.ldap.user_filter'))"

The result "(&(sAMAccountName={user}))" // vendor/psy/psysh/src/ExecutionClosure.php(40) : eval()'d code:1

The authentication problem is still present.

ssddanbrown commented 1 week ago

Try again with the LDAP_DUMP_USER_DETAILS=true option set (in the .env), now that the user filter is correct. If that does not stop and dump user details on login attempt, then the filter & provided username combined is not correct and is not matching users in your environment. Otherwise, if it does stop and dump user details, then it's likely a password issue.

DaarKyns commented 1 week ago

Problem solved, in fact a $ was missing from the LDAP filter

LDAP_USER_FILTER=(&(sAMAccountName={user}))
LDAP_USER_FILTER=(&(sAMAccountName=${user}))

Thank you for your quick help

ssddanbrown commented 1 week ago

Ah, yeah, you're on an older version, I had missed that. Good to hear it's working now though, will therefore close this off.