How to Rewrite Set-Cookie Domain Headers in Nginx Reverse Proxy Configurations


2 views

When implementing a reverse proxy with Nginx, one common challenge arises when backend servers set cookies with their internal domain. Consider this basic Nginx reverse proxy configuration:

server {
  server_name external.domain.com;
  location / {
    proxy_pass http://backend.int/;
  }
}

The backend application might set cookies like this in its HTTP response headers:

Set-Cookie: session_id=abc123; Domain=backend.int; Path=/; Secure; HttpOnly

Modern browsers enforce strict cookie security policies. When they receive a cookie with Domain=backend.int but the request came from external.domain.com, they'll reject the cookie because the domains don't match. This breaks authentication and session management for users.

Nginx provides the proxy_cookie_domain directive specifically for this scenario. Here's how to implement it:

server {
  server_name external.domain.com;
  
  location / {
    proxy_pass http://backend.int/;
    proxy_cookie_domain backend.int external.domain.com;
    
    # Additional recommended proxy settings
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

For more complex scenarios where you need to handle multiple domains or paths:

# Replace multiple possible backend domains
proxy_cookie_domain ~^(www\.)?backend\.int$ $host;

# Handle path rewriting if needed
proxy_cookie_path / /api/;

After implementing these changes, verify with curl:

curl -I https://external.domain.com/

You should see the rewritten cookie domain in the response headers:

Set-Cookie: session_id=abc123; Domain=external.domain.com; Path=/; Secure; HttpOnly

Cookie rewriting adds minimal overhead, but for high-traffic sites:

  • Consider caching strategies
  • Monitor proxy performance metrics
  • Keep Nginx updated for latest optimizations

If modifying Nginx config isn't possible, consider:

  1. Configure the backend to be aware of its public domain
  2. Use application-level cookie handling
  3. Implement a middleware layer for header transformation

When using Nginx as a reverse proxy, a common challenge arises with Set-Cookie headers from backend applications. The backend typically sets cookies with its own domain (e.g., backend.int), unaware that it's being accessed through a different public domain (external.domain.com).

# Problematic Set-Cookie header example from backend
Set-Cookie: sessionid=abc123; Path=/; Domain=backend.int; Secure; HttpOnly

Nginx provides the ngx_http_sub_module for response header modification. Here's how to implement it:

server {
  server_name external.domain.com;
  
  # Enable response header processing
  proxy_set_header Accept-Encoding "";
  
  location / {
    proxy_pass http://backend.int/;
    
    # Process Set-Cookie headers
    proxy_cookie_domain backend.int external.domain.com;
    
    # Alternative regex-based approach for complex cases
    sub_filter_once off;
    sub_filter_types *;
    sub_filter '; Domain=backend.int' '; Domain=external.domain.com';
    sub_filter ';Domain=backend.int' ';Domain=external.domain.com';
  }
}

For more complex scenarios with multiple domains or wildcards:

map $upstream_http_set_cookie $new_cookie {
  ~(.*)(Domain=)(backend\.int|\.backend\.int)(.*) $1$2external.domain.com$4;
  default $upstream_http_set_cookie;
}

server {
  server_name external.domain.com;
  
  location / {
    proxy_pass http://backend.int/;
    proxy_hide_header Set-Cookie;
    add_header Set-Cookie $new_cookie;
  }
}
  • The proxy_set_header Accept-Encoding ""; line is crucial as it disables compression, allowing Nginx to modify responses
  • For production environments, consider adding proxy_cookie_path / /; if you need to rewrite cookie paths
  • Test thoroughly as cookie modifications can break authentication flows

While these solutions work, they do add overhead:

  • The sub_filter approach scans entire responses
  • The map-based solution requires additional memory
  • For high-traffic sites, consider modifying the backend application instead