Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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

share|improve this question
add comment

4 Answers

up vote 4 down vote accepted

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

share|improve this answer
    
How does that answer my question - I specifically want to talk to ldap directly. –  Adam Benayoun Aug 8 '10 at 13:46
3  
nginx doesn't do ldap.. you have to use xsendfile with a 3rd party script you create to handle ldap auth –  Mike Aug 8 '10 at 13:47
    
thanks for the answer. –  Adam Benayoun Aug 8 '10 at 14:33
add comment

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

share|improve this answer
add comment

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);
share|improve this answer
add comment

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

share|improve this answer
    
How does that answer my question? –  Adam Benayoun Aug 8 '10 at 13:45
    
Its talking about using Xsendfile and a script .. read replies to the question in above link. If it doesn't may be I got your question wrong. –  Zimbabao Aug 10 '10 at 14:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.