Q:

nginx_ldap_auth and custom authentication page

I found a nginx module (https://github.com/nginxinc/nginx-ldap-auth) that permits to authenticate an user using ldap.
I want to adapt it with a custom authentication page, that doesn't exist on the backend server. I do not understand all the interactions:
Should I create a cookie within the login page? How to pass the credentials to the ldap daemon? Maybe what I want to do is impossible? It's been few days I try to do it, now i'm nearly desperate...
All the time I have these messages on the ldap daemon:

using username/password from authorization header
"GET /auth-proxy HTTP/1.0" 401 -

Below, the sites-enabled/mywebsite:
server {
    listen 80;
    return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
        server_name mywebsite.com;

        ssl_certificate     /root/mywebsite.com.cer;
        ssl_certificate_key /root/mywebsite.com.key;

        ssl on;
        ssl_session_cache builtin:1000 shared:SSL:10m;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/oxidized.access.log;
        root /var/www/auth_ldap;
        index index.php index.html =404;

        # Pass PHP scripts to FastCGI server
        location ~ \.php$ {
          try_files $uri /index.php =404;
          fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
        }

        location / {
          auth_request /auth-proxy;

          # redirect 401 to login form
          # Comment them out if using HTTP basic authentication.
          # or authentication popup won't show
          error_page 401 =200 /login;

          proxy_set_header        Host $host;
          proxy_set_header        X-Real-IP $remote_addr;
          proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header        X-Forwarded-Proto $scheme;

          proxy_pass          http://localhost:8888;
          proxy_read_timeout  90;

          proxy_redirect      http://localhost:8888 https://mywebsite.com;
        }

        location /login {
          alias /var/www/auth_ldap/login;
        }

        location = /auth-proxy {
          internal;

          # The ldap-auth daemon listens on port 8081, as set
          # in nginx-ldap-auth-daemon.py.
          # Change the IP address if the daemon is not running on
          # the same host as NGINX/NGINX Plus.
          proxy_pass http://127.0.0.1:8081;

          proxy_pass_request_body off;
          proxy_set_header Content-Length "";
          proxy_cache auth_cache;
          proxy_cache_valid 200 10m;

          # The following directive adds the cookie to the cache key
          proxy_cache_key "$http_authorization$cookie_nginxauth";

          # As implemented in nginx-ldap-auth-daemon.py, the ldap-auth daemon
          # communicates with a LDAP server, passing in the following
          # parameters to specify which user account to authenticate. To
          # eliminate the need to modify the Python code, this file contains
          # 'proxy_set_header' directives that set the values of the
          # parameters. Set or change them as instructed in the comments.
          #
          # Parameter   Proxy header
          # ---------------------------
          # url         X-Ldap-URL
          # starttls    X-Ldap-Starttls
          # basedn      X-Ldap-BaseDN
          # binddn      X-Ldap-BindDN
          # bindpasswd  X-Ldap-BindPass
          # cookiename  X-CookieName
          # realm       X-Ldap-Realm
          # template    X-Ldap-Template

          # (Required) Set the URL and port for connecting to the LDAP server,
          # by replacing 'example.com'.
          # Do not mix ldaps-style URL and X-Ldap-Starttls as it will not work.
          proxy_set_header X-Ldap-URL "ldap://ad.mywebsite.com";

          # (Optional) Establish a TLS-enabled LDAP session after binding to the
          # LDAP server.
          # This is the 'proper' way to establish encrypted TLS connections, see
          # http://www.openldap.org/faq/data/cache/185.html
          #proxy_set_header X-Ldap-Starttls "true";

          # (Required) Set the Base DN, by replacing the value enclosed in
          # double quotes.
          proxy_set_header X-Ldap-BaseDN   "dc=mywebsite,dc=com";

          # (Required) Set the Bind DN, by replacing the value enclosed in
          # double quotes.
          proxy_set_header X-Ldap-BindDN   "cn=some_users,ou=LDAP Users,ou=Users,dc=mywebsite,dc=com";

          # (Required) Set the Bind password, by replacing 'secret'.
          proxy_set_header X-Ldap-BindPass "secret";

          # (Required) The following directives set the cookie name and pass
          # it, respectively. They are required for cookie-based
          # authentication. Comment them out if using HTTP basic
          # authentication.
          proxy_set_header X-CookieName "nginxauth";
          proxy_set_header Cookie nginxauth=$cookie_nginxauth;

          # (Required if using Microsoft Active Directory as the LDAP server)
          # Set the LDAP template by uncommenting the following directive.
          proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";

          # (May be required if using Microsoft Active Directory and
          # getting "In order to perform this operation a successful bind
          # must be completed on the connection." errror)
          #proxy_set_header X-Ldap-DisableReferrals "true";

          # (Optional if using OpenLDAP as the LDAP server) Set the LDAP
          # template by uncommenting the following directive and replacing
          # '(cn=%(username)s)' which is the default set in
          # nginx-ldap-auth-daemon.py.
          #proxy_set_header X-Ldap-Template "(cn=%(username)s)";

          # (Optional) Set the realm name, by uncommenting the following
          # directive and replacing 'Restricted' which is the default set
          # in nginx-ldap-auth-daemon.py.
          #proxy_set_header X-Ldap-Realm  "Restricted";
        }
}

And a sample of login page:
<?php
  if(isset($_POST['submit']))
  {
    $_SESSION['username'] = $_POST['login'];
    $_SESSION['password'] = $_POST['password'];
    header('Location: /');
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Login with LDAP</title>
</head>

<body>
  <form method="post">
    <label for="login">Login:</label>
    <input type="text" name="login" />
    <label for="password">Password:</label>
    <input type="password" name="password" />
    <input type="submit" name="submit" value="Log in" />
  </form>
</body>

</html>

Thank you in advance for any help on that subject.

A:

I found out how to pass my login/password to NginX: however, not using the authorization header, but a cookie.
Here is my new nginx virtual host:
# TO ADD in nginx.conf, in the "http" block:
# proxy_cache_path cache/ keys_zone=auth_cache:10m;

server {
    listen 80;
    return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name mywebsite.com;

  ssl_certificate     /root/mywebsite.com.cer;
  ssl_certificate_key /root/mywebsite.com.key;

  ssl on;
  ssl_session_cache builtin:1000 shared:SSL:10m;
  ssl_protocols TLSv1.1 TLSv1.2;
  ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
  ssl_prefer_server_ciphers on;

  access_log /var/log/nginx/oxidized.access.log;
  root /var/www/auth_ldap;
  index index.php index.html =404;

  # Pass PHP scripts to FastCGI server
  location ~ \.php$ {
    try_files $uri /index.php =404;
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }

  location / {
    auth_request /auth-proxy;

    # redirect 401 to login form
    # Comment them out if using HTTP basic authentication.
    # or authentication popup won't show
    error_page 401 =200 /login;

    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;

    proxy_pass          http://localhost:8888;
    proxy_read_timeout  90;

    proxy_redirect      http://localhost:8888 https://mywebsite.com;
  }

  location /login {
    alias /var/www/auth_ldap/login;
  }

  location = /auth-proxy {
    internal;

    # The ldap-auth daemon listens on port 8081, as set
    # in nginx-ldap-auth-daemon.py.
    # Change the IP address if the daemon is not running on
    # the same host as NGINX/NGINX Plus.
    proxy_pass http://127.0.0.1:8081;

    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_cache auth_cache;
    proxy_cache_valid 200 10m;

    # The following directive adds the cookie to the cache key
    proxy_cache_key "$http_authorization$cookie_nginxauth";

    # As implemented in nginx-ldap-auth-daemon.py, the ldap-auth daemon
    # communicates with a LDAP server, passing in the following
    # parameters to specify which user account to authenticate. To
    # eliminate the need to modify the Python code, this file contains
    # 'proxy_set_header' directives that set the values of the
    # parameters. Set or change them as instructed in the comments.
    #
    # Parameter   Proxy header
    # ---------------------------
    # url         X-Ldap-URL
    # starttls    X-Ldap-Starttls
    # basedn      X-Ldap-BaseDN
    # binddn      X-Ldap-BindDN
    # bindpasswd  X-Ldap-BindPass
    # cookiename  X-CookieName
    # realm       X-Ldap-Realm
    # template    X-Ldap-Template

    # (Required) Set the URL and port for connecting to the LDAP server,
    # by replacing 'example.com'.
    # Do not mix ldaps-style URL and X-Ldap-Starttls as it will not work.
    proxy_set_header X-Ldap-URL "ldap://ad.mywebsite.com";

    # (Optional) Establish a TLS-enabled LDAP session after binding to the
    # LDAP server.
    # This is the 'proper' way to establish encrypted TLS connections, see
    # http://www.openldap.org/faq/data/cache/185.html
    #proxy_set_header X-Ldap-Starttls "true";

    # (Required) Set the Base DN, by replacing the value enclosed in
    # double quotes.
    proxy_set_header X-Ldap-BaseDN   "dc=mywebsite,dc=com";

    # (Required) Set the Bind DN, by replacing the value enclosed in
    # double quotes.
    proxy_set_header X-Ldap-BindDN   "cn=some_users,ou=Users,dc=mywebsite,dc=com";

    # (Required) Set the Bind password, by replacing 'secret'.
    proxy_set_header X-Ldap-BindPass "secret";

    # (Required) The following directives set the cookie name and pass
    # it, respectively. They are required for cookie-based
    # authentication. Comment them out if using HTTP basic
    # authentication.
    proxy_set_header X-CookieName "nginxauth";
    proxy_set_header Cookie nginxauth=$cookie_nginxauth;

    # (Required if using Microsoft Active Directory as the LDAP server)
    # Set the LDAP template by uncommenting the following directive.
    proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";

    # (May be required if using Microsoft Active Directory and
    # getting "In order to perform this operation a successful bind
    # must be completed on the connection." errror)
    proxy_set_header X-Ldap-DisableReferrals "true";

    # (Optional if using OpenLDAP as the LDAP server) Set the LDAP
    # template by uncommenting the following directive and replacing
    # '(cn=%(username)s)' which is the default set in
    # nginx-ldap-auth-daemon.py.
    #proxy_set_header X-Ldap-Template "(cn=%(username)s)";

    # (Optional) Set the realm name, by uncommenting the following
    # directive and replacing 'Restricted' which is the default set
    # in nginx-ldap-auth-daemon.py.
    #proxy_set_header X-Ldap-Realm  "Restricted";
  }
}

And the authentication page:
<?php
  if(isset($_POST['submit']))
  {
    $auth = base64_encode($_POST['login'].':'.$_POST['password']);
    $expire = time() + 60 * 60 * 1; // 1 hour
    setcookie('nginxauth',$auth,$expire,'/');
    header('Location: /');
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Login with LDAP</title>
</head>

<body>
  <form method="post">
    <label for="login">Login:</label>
    <input type="text" name="login" />
    <label for="password">Password:</label>
    <input type="password" name="password" />
    <input type="submit" name="submit" value="Log in" />
  </form>
</body>

</html>

Then, for the record, I modified the default script nginx-ldap-auth-daemon.py (which send the credentials to the LDAP/AD server), because the cookie "urlencode" the base64 "login:password" field (So, the "=" become "%3D"). I had to import "urllib2" and to decode the cookie:
auth_cookie = urllib2.unquote(self.get_cookie(ctx['cookiename'])).decode('utf8')

I hope this will help people with the implementation of nginx_ldap_auth.
Regards.

