How to Set Up Basic HTTP Authentication in NGINX

Nginx logo.

Basic authentication of user names and passwords is a simple and secure way to secure administration panels and backend services. Nginx can be configured to protect certain areas of your website, or even used as a reverse proxy to secure other services.

How does HTTP authentication work?

In basic HTTP authentication, some routes on the server are locked and require a user name and password to access them. For example, the administration panels of most home routers are secured this way; when you try to access it, the browser opens a dialog box asking for credentials.

When a user attempts to access a protected resource, the server sends the user a WWW-Authenticate header with a 401 Unauthorized reply. The client returns the appropriate username and password, stored in the Authorization and if it matches a key file, they are allowed to connect.

Since basic HTTP authentication requires passwords to be sent along the cable, you must configure HTTPS / TLS on your server, or anyone else could smell the password in clear. HTTPS will encrypt the connection, making transmission secure. You can configure a free certificate with LetsEncrypt, or if you are looking to secure a private server, create and sign yourself.

Basic username / password authentication is just one of many authentication schemes; another common scheme is the support tokens, used for OAuth 2.0 flows. You can use this scheme with Nginx using the JSON Web Tokens module, but the full configuration is much more complex than authentication by username / password.

Generate password file

You can use the htpasswd to generate password files. It’s probably already installed on your system, but if it isn’t, you can install it from the apache2-utils package. (Nginx uses the same password format as Apache):

sudo apt-get install apache2-utils

Generate a new password file by running htpasswd with the -c flag, in this case, for the user “admin”:

sudo htpasswd -c /etc/nginx/.htpasswd admin

You will be asked to enter a password, which will be hashed and stored in /etc/nginx/.htpasswd. If you want to add multiple users, omit the -c to add new entries.

Enable basic HTTP authentication

You can protect any route in nginx using the auth_basic directive inside a location. For example, to protect with a password /admin, you would place this location block inside the server block in your main nginx configuration file (usually located at /etc/nginx/nginx.conf):

location /admin {
  try_files $uri $uri/ =404;
  auth_basic "Restricted Content";
  auth_basic_user_file /etc/nginx/.htpasswd;
}

the auth_basic_user_file The directive should point to the password file that you created in the first step. It doesn’t have to be named special, so you can create different password files for different routes.

Nginx should do the rest for you. Restart to apply the changes:

sudo service nginx restart

And check the protected route in your browser. You should be asked to enter a password and deny access if you cannot provide it.

Using proxy authentication

A common use case for basic authentication is securing an external resource with a nginx reverse proxy. It works perfectly with auth_basicand is as simple as using the two together:

location / {
  #//turn on auth for this location
  auth_basic "Restricted Content";
  auth_basic_user_file /etc/nginx/.htpasswd;

  #//normal proxy configuration
  proxy_http_version 1.1;
  proxy_pass_request_headers on;
  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 Accept-Encoding "";

  proxy_pass https://;
  proxy_redirect default;
}

This works by denying any entry to the proxy before a user authenticates. Once authenticated, nginx works normally.

However, if you want to perform authentication on the server behind the reverse proxy, the configuration is more complicated. Rather, you want nginx to proxy your entries on the web server, which could, for example, query a database or perform more complex verification than a simple password file.

You will need to use the plus-headers module to be able to modify the headers more directly:

location / {
  proxy_http_version 1.1;
  proxy_pass_request_headers on;
  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 Accept-Encoding "";

  proxy_pass https://;
  proxy_redirect default;

  more_set_input_headers 'Authorization: $http_authorization';
  more_set_headers -s 401 'WWW-Authenticate: Basic realm="your_server.com"';
}

Proxy configuration is the same, except that it is missing auth_basic because we don’t want to authenticate with nginx. the more_set_input_headers The directive does the magic here and sets the header when it communicates with the web server to include the $http_authorization variable obtained from the client. In this way, the username and password are transmitted via nginx to the backend.

The next line is more complicated; the regular way of defining the headers will replace the realm variable when mandated via nginx, which is not ideal. Using more_set_headers will keep this and show the customer the correct information.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.