LDAP Auto Login #1232

Closed
opened 2026-02-05 00:20:28 +03:00 by OVERLORD · 10 comments
Owner

Originally created by @MKCPC on GitHub (Jun 20, 2019).

Describe the feature you'd like
I'd like a way for LDAP to support auto login, potentially using NTLM to pass the current users credentials enabling our users to be able to open the bookstack web page and automatically be logged in.

I'm not sure if this feature already exists but after looking through other feature/requests bugs i've not been able to find anyone else talking about it.

Describe the benefits this feature would bring to BookStack users
Ease of use for internal users not having to sign in every day to access documents. Links given to team members would be instantly available rather than having to login each time.

Originally created by @MKCPC on GitHub (Jun 20, 2019). **Describe the feature you'd like** I'd like a way for LDAP to support auto login, potentially using NTLM to pass the current users credentials enabling our users to be able to open the bookstack web page and automatically be logged in. I'm not sure if this feature already exists but after looking through other feature/requests bugs i've not been able to find anyone else talking about it. **Describe the benefits this feature would bring to BookStack users** Ease of use for internal users not having to sign in every day to access documents. Links given to team members would be instantly available rather than having to login each time.
OVERLORD added the 🔨 Feature Request🚪 Authentication labels 2026-02-05 00:20:28 +03:00
Author
Owner

@ssddanbrown commented on GitHub (Jun 22, 2019):

Thanks for writing up this request @MKCPC.

I can see how this may be useful. To be totally open, I'm not looking to spend much more efforts on the LDAP system unless it's a simple addition. Also, I'm not really familiar with NTLM in any way but from a quick search it appears to be microsoft/windows specific which would make me nervous about including support in this project.

If the re-logging-back-in is the main pain point here, you may be able to quickly alleviate that by setting the following in your .env file:

SESSION_LIFETIME=240

The number is the lifetime of a user session in minutes. The default is 120.

@ssddanbrown commented on GitHub (Jun 22, 2019): Thanks for writing up this request @MKCPC. I can see how this may be useful. To be totally open, I'm not looking to spend much more efforts on the LDAP system unless it's a simple addition. Also, I'm not really familiar with NTLM in any way but from a quick search it appears to be microsoft/windows specific which would make me nervous about including support in this project. If the re-logging-back-in is the main pain point here, you may be able to quickly alleviate that by setting the following in your .env file: ``` SESSION_LIFETIME=240 ``` The number is the lifetime of a user session in minutes. The default is 120.
Author
Owner

@Mant1kor commented on GitHub (Jun 22, 2019):

@MKCPC , seems like you want to use SSO(Single sign-on) auth mechanism.
@ssddanbrown , NTLM is not recommended to use. It old and a bit not secure.
Better way is using Kerberos authentication. But all component must understand Kerberos tickets:

  1. Web server
  2. BookStack
  3. System

Apache can do this after installing additional modules. Nginx you can build with third-party spnego module.
BookStack - don't support Kerberos.
Debian and RHEL based distributive supports Kerberos after some configuration.
So integration Kerberos-based SSO mechanism is not so easy as it seems.
P.S. If BookStack working on Windows server with IIS - 1 and 3 components support Kerberos auth by default.

@Mant1kor commented on GitHub (Jun 22, 2019): @MKCPC , seems like you want to use SSO(Single sign-on) auth mechanism. @ssddanbrown , NTLM is not recommended to use. It old and a bit not secure. Better way is using Kerberos authentication. But all component must understand Kerberos tickets: 1. Web server 2. BookStack 3. System Apache can do this after installing additional modules. Nginx you can build with third-party spnego module. BookStack - don't support Kerberos. Debian and RHEL based distributive supports Kerberos after some configuration. So integration Kerberos-based SSO mechanism is not so easy as it seems. P.S. If BookStack working on Windows server with IIS - 1 and 3 components support Kerberos auth by default.
Author
Owner

@MKCPC commented on GitHub (Jun 24, 2019):

@Mant1kor Yes that's correct, a much more elegant way of explaining it! I wasn't aware of the security issue around NTLM so Kerberos makes much more sense. SSO is exactly what I would like to request, all of our team members are logging on via a windows domain account so being able to pass the details of the current logged in user would make for a nice seamless user experience.

@ssddanbrown Thanks for session lifetime setting, i've updated that in the mean time to provide a session time spanning 8 hours so once a member of our team logs in once they will not need to login for the rest of the day at least.

@MKCPC commented on GitHub (Jun 24, 2019): @Mant1kor Yes that's correct, a much more elegant way of explaining it! I wasn't aware of the security issue around NTLM so Kerberos makes much more sense. SSO is exactly what I would like to request, all of our team members are logging on via a windows domain account so being able to pass the details of the current logged in user would make for a nice seamless user experience. @ssddanbrown Thanks for session lifetime setting, i've updated that in the mean time to provide a session time spanning 8 hours so once a member of our team logs in once they will not need to login for the rest of the day at least.
Author
Owner

@ethanmdavidson commented on GitHub (Jun 27, 2019):

I'm looking at using bookstack for a company-wide internal wiki, and SSO with kerberos is a key requirement. I recently set up a grails+tomcat+centos app to use kerberos (with activedirectory as the kdc) and it wasn't too difficult. kerberos setup on redhat is not too tricky (basically install some packages, generate a keytab file and put it on the server) and likewise grails was also fairly simple to configure (app needs to know where keytab file is, where the kdc server is, and what principal name to use). I didn't have to do anything with tomcat itself so I think that is more of an option than a requirement. In other words, (if my understanding is correct) either the web server or the application need to be "kerberized", not both.

A) If the webserver is kerberized, then it will pass the username to the app and the app just has to do the ldap lookup, which seems to be the approach taken by adldap2-laravel. (and here is a more detailed guide to the whole system setup)

B) Kerberizing the application itself is a valid approach, but would require much more work from the application developer. Grails/Spring makes it easy by providing a plugin, but I couldn't find anything like that for laravel.

Option A seems to be the way to go here, since it would require less work on bookstack's end. Of course, I am far from an expert on any of this, so please take it all with a grain of salt.

@ethanmdavidson commented on GitHub (Jun 27, 2019): I'm looking at using bookstack for a company-wide internal wiki, and SSO with kerberos is a key requirement. I recently set up a grails+tomcat+centos app to use kerberos (with activedirectory as the kdc) and it wasn't too difficult. [kerberos setup on redhat](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/managing_smart_cards/installing-kerberos) is not too tricky (basically install some packages, generate a keytab file and put it on the server) and likewise grails was also [fairly simple to configure](https://grails-plugins.github.io/grails-spring-security-kerberos/v3/index.html) (app needs to know where keytab file is, where the kdc server is, and what principal name to use). I didn't have to do anything with tomcat itself so I think that is more of an option than a requirement. In other words, (if my understanding is correct) *either* the web server *or* the application need to be "kerberized", not both. A) If the webserver is kerberized, then it will pass the username to the app and the app just has to do the ldap lookup, which seems to be the approach taken by [adldap2-laravel](https://adldap2.github.io/Adldap2-Laravel/#/auth/middleware). (and [here](https://robert.stadsbygd.net/2015/01/14/kerberos-auth-with-apachephp/) is a more detailed guide to the whole system setup) B) Kerberizing the application itself is a valid approach, but would require much more work from the application developer. Grails/Spring makes it easy by providing a plugin, but I couldn't find anything like that for laravel. Option A seems to be the way to go here, since it would require less work on bookstack's end. Of course, I am far from an expert on any of this, so please take it all with a grain of salt.
Author
Owner

@FrankPetrilli commented on GitHub (Jun 28, 2019):

On this note, I've written a kludge of a solution to do header-based auth since I also like doing SSO, though via Traefik and a forward authentication endpoint. Admittedly it's been a number of years since I used PHP regularly, so it's ugly... I welcome suggestions on improvement!

I edited app/Http/Controllers/Auth/LoginController.php to add the following in getLogin(). Be forewarned, it's lacking some niceties since it's for specifically my use-case.

  • This needs a centralized setting to decide whether this is enabled and what header is used. The calls to setting() were hard to understand, as well as where I'd add this setting.
  • UserRepo's registerNew wasn't auto-adding my new user to the default role - attachDefaultRole's call to setting() appeared to be returning nothing, but I didn't feel like tracking down why. I force-add the new user to the 'admin' role.
  • Redirects always force to home.
// Handle proxy authentication
        if (!auth()->check() && $request->header('X-Auth-User') !== null) {
                $proxyUsername = $request->header('X-Auth-User');
                $existingUser = $this->userRepo->getByEmail($proxyUsername);
                if ($existingUser !== null) {
                        auth()->login($existingUser);
                        $path = baseUrl('/', true);
                        return redirect($path);
                }
                // Create new
                $registerData = [];
                $registerData['name'] = $proxyUsername;
                $registerData['email'] = $proxyUsername;
                $registerData['password'] = sha1(rand());
                $proxyUser = $this->userRepo->registerNew($registerData, true);
                $this->userRepo->attachSystemRole($proxyUser, "admin"); // TODO: Better?
                auth()->login($proxyUser);
                $path = baseUrl('/', true);
                return redirect($path);
        }

@ssddanbrown I welcome your input on this - is there a better place I can put this check?

@FrankPetrilli commented on GitHub (Jun 28, 2019): On this note, I've written a kludge of a solution to do header-based auth since I also like doing SSO, though via Traefik and a forward authentication endpoint. Admittedly it's been a number of years since I used PHP regularly, so it's ugly... I welcome suggestions on improvement! I edited `app/Http/Controllers/Auth/LoginController.php` to add the following in `getLogin()`. Be forewarned, it's lacking some niceties since it's for specifically my use-case. - This needs a centralized setting to decide whether this is enabled and what header is used. The calls to `setting()` were hard to understand, as well as where I'd add this setting. - UserRepo's `registerNew` wasn't auto-adding my new user to the default role - `attachDefaultRole`'s call to `setting()` appeared to be returning nothing, but I didn't feel like tracking down why. I force-add the new user to the 'admin' role. - Redirects always force to home. ``` // Handle proxy authentication if (!auth()->check() && $request->header('X-Auth-User') !== null) { $proxyUsername = $request->header('X-Auth-User'); $existingUser = $this->userRepo->getByEmail($proxyUsername); if ($existingUser !== null) { auth()->login($existingUser); $path = baseUrl('/', true); return redirect($path); } // Create new $registerData = []; $registerData['name'] = $proxyUsername; $registerData['email'] = $proxyUsername; $registerData['password'] = sha1(rand()); $proxyUser = $this->userRepo->registerNew($registerData, true); $this->userRepo->attachSystemRole($proxyUser, "admin"); // TODO: Better? auth()->login($proxyUser); $path = baseUrl('/', true); return redirect($path); } ``` @ssddanbrown I welcome your input on this - is there a better place I can put this check?
Author
Owner

@ademxoy commented on GitHub (May 21, 2020):

On this note, I've written a kludge of a solution to do header-based auth since I also like doing SSO, though via Traefik and a forward authentication endpoint. Admittedly it's been a number of years since I used PHP regularly, so it's ugly... I welcome suggestions on improvement!

I edited app/Http/Controllers/Auth/LoginController.php to add the following in getLogin(). Be forewarned, it's lacking some niceties since it's for specifically my use-case.

* This needs a centralized setting to decide whether this is enabled and what header is used. The calls to `setting()` were hard to understand, as well as where I'd add this setting.

* UserRepo's `registerNew` wasn't auto-adding my new user to the default role - `attachDefaultRole`'s call to `setting()` appeared to be returning nothing, but I didn't feel like tracking down why. I force-add the new user to the 'admin' role.

* Redirects always force to home.
// Handle proxy authentication
        if (!auth()->check() && $request->header('X-Auth-User') !== null) {
                $proxyUsername = $request->header('X-Auth-User');
                $existingUser = $this->userRepo->getByEmail($proxyUsername);
                if ($existingUser !== null) {
                        auth()->login($existingUser);
                        $path = baseUrl('/', true);
                        return redirect($path);
                }
                // Create new
                $registerData = [];
                $registerData['name'] = $proxyUsername;
                $registerData['email'] = $proxyUsername;
                $registerData['password'] = sha1(rand());
                $proxyUser = $this->userRepo->registerNew($registerData, true);
                $this->userRepo->attachSystemRole($proxyUser, "admin"); // TODO: Better?
                auth()->login($proxyUser);
                $path = baseUrl('/', true);
                return redirect($path);
        }

@ssddanbrown I welcome your input on this - is there a better place I can put this check?

I am trying to implement this solution in our environment but I can't seem to get the header correctly. I have it set up in a docker. When I get to login, I print out all the headers (into a file) and it seems to be missing the headers.

Are you running this on a server or docker instance? Am i loosing the headers due to nginx proxy inside docker?

Thanks for the solution. If I can get it to work, it is exactly what we needed.

@ademxoy commented on GitHub (May 21, 2020): > On this note, I've written a kludge of a solution to do header-based auth since I also like doing SSO, though via Traefik and a forward authentication endpoint. Admittedly it's been a number of years since I used PHP regularly, so it's ugly... I welcome suggestions on improvement! > > I edited `app/Http/Controllers/Auth/LoginController.php` to add the following in `getLogin()`. Be forewarned, it's lacking some niceties since it's for specifically my use-case. > > * This needs a centralized setting to decide whether this is enabled and what header is used. The calls to `setting()` were hard to understand, as well as where I'd add this setting. > > * UserRepo's `registerNew` wasn't auto-adding my new user to the default role - `attachDefaultRole`'s call to `setting()` appeared to be returning nothing, but I didn't feel like tracking down why. I force-add the new user to the 'admin' role. > > * Redirects always force to home. > > > ``` > // Handle proxy authentication > if (!auth()->check() && $request->header('X-Auth-User') !== null) { > $proxyUsername = $request->header('X-Auth-User'); > $existingUser = $this->userRepo->getByEmail($proxyUsername); > if ($existingUser !== null) { > auth()->login($existingUser); > $path = baseUrl('/', true); > return redirect($path); > } > // Create new > $registerData = []; > $registerData['name'] = $proxyUsername; > $registerData['email'] = $proxyUsername; > $registerData['password'] = sha1(rand()); > $proxyUser = $this->userRepo->registerNew($registerData, true); > $this->userRepo->attachSystemRole($proxyUser, "admin"); // TODO: Better? > auth()->login($proxyUser); > $path = baseUrl('/', true); > return redirect($path); > } > ``` > > @ssddanbrown I welcome your input on this - is there a better place I can put this check? I am trying to implement this solution in our environment but I can't seem to get the header correctly. I have it set up in a docker. When I get to login, I print out all the headers (into a file) and it seems to be missing the headers. Are you running this on a server or docker instance? Am i loosing the headers due to nginx proxy inside docker? Thanks for the solution. If I can get it to work, it is exactly what we needed.
Author
Owner

@ryanc-me commented on GitHub (Aug 11, 2020):

Grafana has an "auth proxy" login type that seems fit the needs for quite a few people. I think this would be a great, low-cost addition for Bookstack:

  • Minimal code to get it functioning (@FrankPetrilli's working code above, with some checks against settings or .env?).
  • Used along with an auth proxy, like louketo, this enabled support for basically any OIDC IdP.
  • Sessions are effectively managed outside of Bookstack, which is likely desirable for people wanting no-login-page SSO.

@ssddanbrown would you accept a PR for this? I would be happy to get the ball rolling!


Also, @ademxoy, are you using an auth proxy? You will need something like louketo to perform the authn/authz, and add the headers. It sits between Bookstack and Keycloak (or whatever your IdP is), as Keycloak won't add the headers on its own.

I'm happy to help you with the setup if you like!

Edit: Some relevant discussion happening in #1157 also.

Edit: Another relevant issue - #2180

@ryanc-me commented on GitHub (Aug 11, 2020): Grafana has an "auth proxy" login type that seems fit the needs for quite a few people. I think this would be a great, low-cost addition for Bookstack: - Minimal code to get it functioning (@FrankPetrilli's working code above, with some checks against settings or `.env`?). - Used along with an auth proxy, like [louketo](https://github.com/louketo/louketo-proxy), this enabled support for basically any OIDC IdP. - Sessions are effectively managed outside of Bookstack, which is likely desirable for people wanting no-login-page SSO. @ssddanbrown would you accept a PR for this? I would be happy to get the ball rolling! --- Also, @ademxoy, are you using an auth proxy? You will need something like louketo to perform the authn/authz, and add the headers. It sits between Bookstack and Keycloak (or whatever your IdP is), as Keycloak won't add the headers on its own. I'm happy to help you with the setup if you like! **Edit:** Some relevant discussion happening in #1157 also. **Edit:** Another relevant issue - #2180
Author
Owner

@nelis249 commented on GitHub (Oct 9, 2020):

Hmm maybe I'm missing something but I tried this snippet of code and it throws an internal server error. Just doing some debug statements the $this->userRepo is null. Not sure how this code works for others if there's no user object initialized yet.

Undefined property: BookStack\Http\Controllers\Auth\LoginController::$userRepo in file /var/www/bookstack/app/Http/Controllers/Auth/LoginController.php

@nelis249 commented on GitHub (Oct 9, 2020): Hmm maybe I'm missing something but I tried this snippet of code and it throws an internal server error. Just doing some debug statements the $this->userRepo is null. Not sure how this code works for others if there's no user object initialized yet. Undefined property: BookStack\Http\Controllers\Auth\LoginController::$userRepo in file /var/www/bookstack/app/Http/Controllers/Auth/LoginController.php
Author
Owner

@ryanc-me commented on GitHub (Oct 12, 2020):

@nelis249 The code above is a bit old now, so it may not work with the current version of Bookstack.

There's a work-in-progress auth proxy implementation at ryanc-me/Bookstack. Use AUTH_METHOD=auth-proxy to enable it, and pass a header named X-Webauth-User with the user email (that can be configured with AUTH_PROXY_HEADER_NAME=X-My-Header-Name).

Please be careful with this though - it is currently working and accepting logins via header, but has not been tested properly yet, and is missing some checks. I'll be making a pull request once it's finished.

@ryanc-me commented on GitHub (Oct 12, 2020): @nelis249 The code above is a bit old now, so it may not work with the current version of Bookstack. There's a work-in-progress auth proxy implementation at [ryanc-me/Bookstack](https://github.com/ryanc-me/BookStack/). Use `AUTH_METHOD=auth-proxy` to enable it, and pass a header named `X-Webauth-User` with the user email (that can be configured with `AUTH_PROXY_HEADER_NAME=X-My-Header-Name`). Please be careful with this though - it is currently working and accepting logins via header, but has not been tested properly yet, and is missing some checks. I'll be making a pull request once it's finished.
Author
Owner

@ssddanbrown commented on GitHub (Nov 8, 2022):

I'm going to go ahead and close this off since the requests in this thread became a bit mixed, and I would not look to support NTLM as per the original request. We have since added OIDC support, upon auto-login for SAML2/OIDC options. It may also be possible to add custom handlers based on headers (Or other data) using our logical theme system.

@ssddanbrown commented on GitHub (Nov 8, 2022): I'm going to go ahead and close this off since the requests in this thread became a bit mixed, and I would not look to support NTLM as per the original request. We have since added OIDC support, upon auto-login for SAML2/OIDC options. It may also be possible to add custom handlers based on headers (Or other data) using our [logical theme system](https://github.com/BookStackApp/BookStack/blob/development/dev/docs/logical-theme-system.md).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/BookStack#1232