How to Implement Basic Auth with Nginx Reverse Proxy for Tomcat Apps (JIRA/Confluence)


10 views

When implementing basic authentication with Nginx in front of Tomcat applications like JIRA or Confluence, you'll often encounter the "AUTHENTICATION_DENIED" error. This occurs because Nginx forwards the Authorization header to Tomcat, which then attempts to authenticate the same credentials against its own authentication system.

# This is what causes the 401 conflict
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
# Missing crucial header modification

The key is to prevent Nginx from forwarding the basic auth credentials to Tomcat while still maintaining your frontend authentication. Here's the proper configuration:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;
    proxy_set_header Authorization "";  # This clears the auth header
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

For more complex setups where you need to bypass authentication for certain paths (like API endpoints), use this pattern:

location / {
    # Standard proxy directives
    proxy_pass http://127.0.0.1:8080;
    
    # Only apply basic auth to non-API paths
    location ~ ^/(?!rest/api) {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
    
    # Always clear auth header before reaching Tomcat
    proxy_set_header Authorization "";
}

Here's how to properly set up your password file with appropriate permissions:

# Create password file (use -B for bcrypt hashing)
sudo htpasswd -cB /etc/nginx/.htpasswd username

# Set secure permissions
sudo chown root:nginx /etc/nginx/.htpasswd
sudo chmod 640 /etc/nginx/.htpasswd

When troubleshooting, these Nginx directives can help identify authentication issues:

# Add to your server block
error_log /var/log/nginx/auth_debug.log debug;

# Test config and reload
sudo nginx -t
sudo systemctl reload nginx

For high-traffic instances, consider these optimizations:

# Cache authentication results
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic_cache_timeout 1h;
auth_basic_cache_size 1000;

When implementing Basic Authentication with Nginx in front of Tomcat applications like JIRA or Confluence, you'll often encounter the "HTTP Status 401 - Basic Authentication Failure" error. This occurs because:

  • The authentication headers get passed through to Tomcat
  • Tomcat tries to authenticate the same credentials again
  • Tomcat's authentication mechanism conflicts with Nginx's

Here's how to properly configure Nginx to prevent the authentication conflict:

server {
    listen 443 ssl;
    server_name jira.example.com;

    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;

    # Basic Auth configuration
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://localhost:8080;
        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;
        
        # Remove the Authorization header before passing to Tomcat
        proxy_set_header Authorization "";
    }
}

The critical part is removing the Authorization header before it reaches Tomcat:

proxy_set_header Authorization "";

This prevents the authentication credentials from being passed through to the Tomcat application, avoiding the double authentication attempt.

To create the .htpasswd file:

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

For additional users (without overwriting existing ones):

sudo htpasswd /etc/nginx/.htpasswd anotheruser

After making changes:

sudo nginx -t
sudo systemctl reload nginx

If you prefer to handle it at the Tomcat level, modify your server.xml:

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           proxyName="jira.example.com"
           proxyPort="443"
           scheme="https"
           secure="true"
           tomcatAuthentication="false" />

The key parameter here is tomcatAuthentication="false" which tells Tomcat not to process authentication headers.

When implementing this solution:

  • Always use HTTPS with Basic Auth
  • Consider IP whitelisting for additional security
  • Regularly rotate passwords in your .htpasswd file
  • Monitor access logs for brute force attempts