The nginx-ldap-auth software is a reference implementation of a method for authenticating users who request protected resources from servers proxied by NGINX Plus. It includes a daemon (ldap-auth) that communicates with an authentication server, and a sample daemon that stands in for an actual back-end server during testing, by generating an authentication cookie based on the user’s credentials. The daemons are written in Python for use with a Lightweight Directory Access Protocol (LDAP) authentication server (OpenLDAP or Microsoft Windows Active Directory 2003 and 2012).

The ldap-auth daemon, which mediates between NGINX Plus and the LDAP server, is intended to serve as a model for “connector” daemons written in other languages, for different authentication systems, or both. NGINX, Inc. Professional Services is available to assist with such adaptations.

Reference implementation of method for authenticating users on behalf of servers proxied by NGINX or NGINX Plus.

Note: For ease of reading, this document refers to NGINX Plus, but it also applies to open source NGINX. The prerequisite ngx_http_auth_request_module module is included both in NGINX Plus packages and prebuilt open source NGINX binaries.

Using NGINX Plus and NGINX to Authenticate Application Users with LDAP

Customers frequently ask us how they can use NGINX Plus and NGINX to secure protected resources or applications by authenticating the users who request them. Today we’re announcing a reference implementation of such an authentication system, and making it available in the NGINX, Inc. repository on GitHub. In this post we describe how the implementation works, how to install it, and how to use it as a model for your own authentication system.

The solution takes advantage of the ngx_http_auth_request_module module in NGINX Plus and NGINX, which forwards authentication requests to an external service. In the reference implementation, that service is a daemon we call ldap‑auth. It’s written in Python and communicates with a Lightweight Directory Access Protocol (LDAP) authentication server – OpenLDAP by default, but we have tested the ldap‑auth daemon against default configurations of Microsoft® Windows® Server Active Directory as well (both the 2003 and 2012 versions).

The ldap‑auth daemon serves as a model for your own “connector” app, which you might write in other languages, deploy with different authentication systems, or both. The NGINX Professional Services team is available to assist with such adaptations.

Note: For ease of reading, the rest of this article refers to NGINX Plus, but the reference implementation also works with the open source NGINX software. The prerequisite http_auth_request module is included in both NGINX Plus packages and prebuilt NGINX binaries.

How Authentication Works in the Reference Implementation

To perform authentication, the http_auth_request module makes an HTTP subrequest to the ldap‑auth daemon, which acts as intermediary and interprets the subrequest for the LDAP server – it uses HTTP for communication with NGINX Plus and the appropriate API for communication with the LDAP server.

We assume that if you’re interested in the reference implementation, you already have an application or other resources you want to protect by requiring authentication. To make it easier to test the reference implementation, however, we’re providing a sample backend daemon, also written in Python, which listens on port 9000. It can stand in for an actual HTTP application during testing, by prompting for user credentials and creating a cookie based on them.

Here’s a step‑by‑step description of the authentication process in the reference implementation. The details are determined by settings in the nginx-ldap-auth.conf configuration file; see Configuring the Reference Implementation below. The flowchart below the steps summarizes the process.

  • A client sends an HTTP request for a protected resource hosted on a server for which NGINX Plus is acting as reverse proxy.
  • NGINX Plus (specifically, the http_auth_request module) forwards the request to the ldap‑auth daemon, which responds with HTTP code 401 because no credentials were provided.
  • NGINX Plus forwards the request to http://backend/login, which corresponds to the backend daemon. It writes the original request URI to the X-Target header of the forwarded request.
  • The backend daemon sends the client a login form (the form is defined in the Python code for the daemon). As configured by the error_page directive, NGINX sets the HTTP code on the login form to 200.
  • The user fills in the Username and Password fields on the form and clicks the Login button. Per the code in the form, the client generates an HTTP POST request directed to /login, which NGINX Plus forwards to the backend daemon.
  • The backend daemon constructs a string of the format username:password, applies Base64 encoding, generates a cookie called nginxauth with its value set to the encoded string, and sends the cookie to the client. It sets the httponly flag to prevent use of JavaScript to read or manipulate the cookie (protecting against the cross‑site scripting [XSS] vulnerability).
  • The client retransmits its original request (from Step 1), this time including the cookie in the Cookie field of the HTTP header. NGINX Plus forwards the request to the ldap‑auth daemon (as in Step 2).
  • The ldap‑auth daemon decodes the cookie, and sends the username and password to the LDAP server in an authentication request.
  • The next action depends on whether the LDAP server successfully authenticates the user:
  • If authentication succeeds, the ldap‑auth daemon sends HTTP code 200 to NGINX Plus. NGINX Plus requests the resource from the backend daemon. In the reference implementation, the backend daemon returns the following text:
  • Hello, world! Requested URL: URL
    The nginx-ldap-auth.conf file includes directives for caching the results of the authentication attempt; to disable caching, see Caching below.
  • If authentication fails, the ldap‑auth daemon sends HTTP code 401 to NGINX Plus. NGINX Plus forwards the request to the backend daemon again (as in Step 3), and the process repeats.

Tell us about a new Kubernetes application

Newsletter

Never miss a thing! Sign up for our newsletter to stay updated.

About

Discover and learn about everything Kubernetes

Navigation