X
Popular Searches

How to Set Up Basic HTTP Authentication in NGINX

Nginx logo.

Basic username and password authentication is an easy and simple way to secure administrative 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, certain routes on the server are locked and require a username and password to access them. For example, the admin panels of most home routers are secured this way; when you attempt to access them, the browser opens a dialog asking for credentials.

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

Because basic HTTP authentication requires sending passwords down the wire, you need to have HTTPS/TLS set up on your server, or else anyone in the middle could sniff out the plaintext password. HTTPS will encrypt the connection, making it safe to transmit. You can set up a free certificate with LetsEncrypt, or if you’re looking to secure a private server, create and sign one yourself.

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

Generate a Password File

You can use the htpasswd to generate password files. This is most likely 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 user “admin”:

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

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

Turn on Basic HTTP Authentication

You can protect any route in nginx by using the auth_basic directive inside a location. For example, to password protect /admin, you would place this location block inside the server block in your main nginx config 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 directive must point towards the password file you created in the first step. This doesn’t have to be named anything special, so you can create different password files for different routes.

Nginx should handle 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 for a password, and denied access if you can’t provide it.

Using Proxy Authentication

A common use case of basic auth is securing an external resource with an nginx reverse proxy. This works perfectly with auth_basic, and 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://<ip-address>;
  proxy_redirect default;
}

This works by denying any entry to the proxy before a user authenticates. Once they’re authenticated, nginx works as normal.

However, if you want to perform the auth on the server behind the reverse proxy, the configuration is more complicated. You’ll instead want nginx to proxy your input to the web server, which could, for example, query a database or perform more complex checking than a simple password file.

You’ll need to use the headers-more 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://<ip-address>;
  proxy_redirect default;

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

The proxy configuration is the same, except it’s missing auth_basic because we don’t want to do the authentication with nginx. The more_set_input_headers directive is doing the magic here, and setting the header for when it communicates with the web server to include the $http_authorization variable it got from the client. This way the username and password are passed through nginx to the backend.

The next line is more complicated; the regular way of setting headers will overwrite the realm variable when it’s proxied through nginx, which is not ideal. Using more_set_headers will preserve this and show the client correct information.

Anthony Heddings Anthony Heddings
Anthony Heddings is the resident cloud engineer for LifeSavvy Media, a technical writer, programmer, and an expert at Amazon's AWS platform. He's written hundreds of articles for How-To Geek and CloudSavvy IT that have been read millions of times. Read Full Bio »

The above article may contain affiliate links, which help support CloudSavvy IT.