Setting Up Basic HTTP Authentication with NGINX for Secure Access Control
HTTP Basic Authentication is a simple method to restrict access to web resources by requiring a username and password. The client sends encoded credentials with each request, which NGINX verifies against a password file to allow or deny access.
A common use case is protecting a staging environment (e.g., staging.example.com
) to prevent public access while allowing easy authentication.
How It Works #
- Client sends a
Authorization: Basic <base64(username:password)>
header with each request. - NGINX verifies the credentials against a password file.
- Access is granted or denied based on the result.
Security Considerations #
HTTP Basic Authentication is only suitable for simple, low-risk scenarios and must always run over HTTPS. For stronger security or complex access control, use more advanced methods.
1. Lack of Encryption
Base64 encoding is not encryption and can be easily decoded. When sent over HTTP, credentials are exposed to anyone monitoring the network, such as on public Wi-Fi or unsecured internal networks.
Mitigation: Always use HTTPS (TLS) to encrypt the entire request, including the Authorization
header.
2. No Session Management
- Credentials are sent with every request, increasing risk if intercepted.
- Browsers may cache credentials without a logout option, so access persists until the browser is closed.
3. Static Credential Storage
- Passwords are stored in an
.htpasswd
file, usually hashed with bcrypt or SHA-based algorithms. - Managing this file requires manual updates or automation.
Use strong, unique passwords hashed with bcrypt (e.g., via htpasswd -B
).
4. No Built-in Protection Against Brute Force
Basic Auth does not prevent repeated login attempts or brute force attacks.
Mitigation:
- Use NGINX features like
limit_req
or tools likefail2ban
to limit repeated attempts. - Apply firewall rules (e.g., iptables, ufw) to restrict access to sensitive endpoints.
5. Audit and Logging
- NGINX logs record accessed URLs but not credentials.
- Avoid logging full headers or request bodies to prevent accidental exposure of sensitive data.
Workflow #
Step 1: Install Required Packages #
Install apache2-utils
, which includes the htpasswd
utility:
sudo apt install apache2-utils -y
Step 2: Create Credentials File #
Generate the .htpasswd
file with a strong password, storing it outside the web root:
sudo htpasswd -c -B /etc/nginx/.htpasswd <user>
Explanation:
-c
: Create a new password file (overwriting if it exists)-B
: Use bcrypt hashing for stronger security/etc/nginx/.htpasswd
: Path to the password file<user>
: Username to add or update
You will be prompted to enter and confirm the password.
Managing Users
Add another user:
sudo htpasswd -B /etc/nginx/.htpasswd <another_user>
View credentials file:
sudo cat /etc/nginx/.htpasswd
- Each line contains a username and hashed password
- Do not store this file in your web root
Change an existing user’s password:
sudo htpasswd -B /etc/nginx/.htpasswd <user>
- You will be prompted to enter and confirm the new password
- Updates the password without affecting other users
Delete a user:
sudo vim /etc/nginx/.htpasswd
- Delete the line starting with the username
- Save and exit
Step 3: Configure NGINX #
Edit site configuration:
sudo vim /etc/nginx/sites-available/<site>
Add the following inside the relevant location
block to enable Basic Auth:
location / {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
...
}
Optional: Restrict Access by IP
Add IP restrictions for an extra security layer:
location / {
allow 123.4.567.8; # Replace with your static IP
deny all;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Optional: Add rate limiting to reduce brute-force attacks
Limit requests per IP to reduce brute-force risks:
http {
limit_req_zone $binary_remote_addr zone=authlimit:10m rate=5r/m;
server {
location / {
limit_req zone=authlimit;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
}
Explanation:
limit_req_zone
creates a 10-minute zone tracking IPs, allowing 5 requests per minute.limit_req
enforces this limit in the location.- This slows repeated requests, adding security alongside Basic Auth with minimal setup.
Step 4: Secure the Credentials File #
Set ownership and permissions to restrict access:
sudo chown root:www-data /etc/nginx/.htpasswd
sudo chmod 640 /etc/nginx/.htpasswd
Verify:
ll /etc/nginx/.htpasswd
Step 5: Validate and Reload Nginx #
Run:
sudo nginx -t && sudo systemctl reload nginx
Step 6: Test Access #
Open your site in a browser:
https://example.com/
- You should see a Basic Auth login prompt
- Enter your credentials to access the site
Notes
- No session or timeout: Basic Auth credentials are cached by the browser
- To "log out", close the browser or clear its authentication cache
- Use a private/incognito window to verify the login prompt is working
- On failed login, NGINX returns:
401 Authorization Required