10

Does nginx support ldap authentication? I have just migrated from apache and would like to move all of my authentications which are based on openldap and mod_auth_ldap to nginx. Let me know if that is possible.

From this page listing all the modules nginx has, i don't see any mention about LDAP. Thanks,

womble
  • 95,029
  • 29
  • 173
  • 228
Adam Benayoun
  • 1,138
  • 2
  • 14
  • 26

5 Answers5

6

nginx doesn't do LDAP: you have to use xsendfile with a 3rd party script you create to handle LDAP authentication

http://wiki.nginx.org/NginxXSendfile

warren
  • 17,829
  • 23
  • 82
  • 134
Mike
  • 21,910
  • 7
  • 55
  • 79
6

There is an unofficial LDAP module for nginx : nginx-auth-ldap.

Yohann
  • 285
  • 2
  • 11
6

There is a 3rd party module nginx-auth-ldap that you can use. I have not tried it yet, but I may update my answer later.

using nginx X-accel

The documentation for X-accel just explains that a page may use a header to have nginx serve a file (rather than PHP or django or ruby or name-your-not-as-efficient-as-nginx-stack-here).

e.g. workflow:

  • user visits /download.php?path=/data/file1.txt,
  • download.php returns WWW-Authenticate + 401 Unauthorized,
  • user's browser shows the authentication form and retries,
  • user visits /download.php?path=/data/file1.txt but now nginx has the credentials,
  • nginx may pass $remote_user and $http_authorization to fastcgi script,
  • download.php does the authentication and decides whether to return 403 Forbidden or set the header X-Accel-Redirect header.

setting nginx internal location

While you can use X-Accel to serve static assets, the use case here is we want the requests to be authenticated, which is why we use internal.

location /protected/data/ {
    internal;
    alias /path/to/data/files/;
}

setting up the download script

Here we go:

location /download.php$ {
    fastcgi_pass  unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /scripts/download.php;
    fastcgi_param PHP_AUTH_USER $remote_user;
    fastcgi_param PHP_AUTH_PW $http_authorization;
    include fastcgi_params;
}

please note: the PHP script uses PHP_AUTH_USER and PHP_AUTH_PW, which is captured by nginx, so in order to use them in the PHP script, we need to give to provide them explicitly.

cooking up an ldap authentication in PHP

For my use case, I installed php-fpm and php-ldap on my system.

Here is a decent authenticate function:

function authenticate() {
    // I'm watching you.
    error_log("authreq: " . $_SERVER['REMOTE_ADDR']);
    // mark that we're seeing the login box.
    $_SESSION['AUTH'] = 1;
    // browser shows login box
    Header("WWW-Authenticate: Basic realm=LDAP credentials.");
    Header("HTTP/1.0 401 Unauthorized");
    die('Unauthorized.');
}

Here is a decent code path for forbidden access:

function forbidden() {
    error_log("forbidden: " . $_SERVER['REMOTE_ADDR'] . ', user: ' . $_SERVER['PHP_AUTH_USER']);
    // avoid brute force attacks
    sleep(rand(0, 3));
    // re-display login form
    session_destroy();
    // don't give too much info (e.g. user does not exist / password is wrong)
    Header("HTTP/1.0 403 Forbidden");
    // yes I did put the same message.
    die('Unauthorized.');
}

And for the meat of the LDAP authentication:

function ldap_auth() {
    $ldap_server = 'ldap://ldap.example.com/';
    $ldap_domain = 'dc=example,dc=com';
    $ldap_userbase = 'ou=Users,' . $ldap_domain;
    $ldap_user = 'uid=' . $_SERVER['PHP_AUTH_USER'] . ',' . $ldap_userbase;
    $ldap_pass = $_SERVER['PHP_AUTH_PW'];

    // connect to ldap server
    $ldapconn = ldap_connect($ldap_server)
        or die("Could not connect to LDAP server.");
    ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3) ;
    if ($ldapconn) {
        // try to bind/authenticate against ldap
        $ldapbind = @ldap_bind($ldapconn, $ldap_user, $ldap_pass) || forbidden();
        // "LDAP bind successful...";
        error_log("success: " . $_SERVER['REMOTE_ADDR'] . ', user: ' . $_SERVER['PHP_AUTH_USER']);
    }
    ldap_close($ldapconn);
}

Here you have the main body of the script which uses the request uri.

if (@$_SESSION['AUTH'] != 1) {
    authenticate();
}

if (empty($_SERVER['PHP_AUTH_USER'])) {
    authenticate();
}

// check credentials on each access
ldap_auth();

// Get requested file name
// you can use the query string or a parameter
// or the full request uri if you like.
$path = $_GET["path"];

error_log("serving: " . $_SERVER['REMOTE_ADDR'] . ', user: ' . $_SERVER['PHP_AUTH_USER'] . ', path: ' . $path);

header("Content-Type: ", true);
header("X-Accel-Redirect: /protected" . $path);

semi-transparent file browsing

I also published this as a gist:

location /protected/data/ {
    internal;
    autoindex on;
    alias /path/to/data/files/;
}

location /data/ {
    fastcgi_pass  unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /scripts/auth.php;
    fastcgi_param PHP_AUTH_USER $remote_user;
    fastcgi_param PHP_AUTH_PW $http_authorization;
    include fastcgi_params;
}

and pretty much the same PHP script except the body:

// Get requested file name
$path = $_SERVER["REQUEST_URI"];
error_log("serving: " . $_SERVER['REMOTE_ADDR'] . ', user: ' . $_SERVER['PHP_AUTH_USER'] . ', path: ' . $path);
header("Content-Type: ", true);
header("X-Accel-Redirect: /protected" . $path);
dnozay
  • 251
  • 3
  • 7
2

In short: Yes, NGINX supports LDAP. There are two add-on modules available: NGINX has one, and there is another one available on github. The NGINX solution seemed rather complex at first glance, so I went with the latter choice, which is called nginx-auth-ldap. I put up some installation notes regarding my experience in the following thread:

Add ldap authentication to nginx on RHEL 7

Felix
  • 51
  • 1
  • 1
  • 5
  • Howdy Felix, welcome to ServerFault. https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers Can you make your answer here stand on its own? – chicks Apr 14 '17 at 15:48
  • Is this better ? I just didn't want to regurgitate the same spiel over and over again, which seemed closer to cross-posting to me... ;-) – Felix Apr 15 '17 at 19:30
-1

Looks like somebody got answer to your question on http://forum.nginx.org/read.php?2,18552

Zimbabao
  • 117
  • 2