How to Whitelist Facebook IP Range in Nginx to Bypass HTTP Basic Authentication for OAuth Testing


1 views

When developing applications with Facebook Login (or other OAuth providers), the HTTP Basic Authentication layer protecting your staging environment creates a significant roadblock. Facebook's servers need to access your callback URLs directly without authentication prompts, but you still want to maintain security for other visitors.

The most efficient solution is using Nginx's geo module to create IP-based access rules. First, we need Facebook's current IP ranges:


# Facebook's IP ranges (updated as of 2023)
geo $auth_bypass {
    default 0;
    31.13.24.0/21 1;
    31.13.64.0/18 1;
    45.64.40.0/22 1;
    66.220.144.0/20 1;
    69.63.176.0/20 1;
    69.171.224.0/19 1;
    74.119.76.0/22 1;
    102.132.96.0/20 1;
    103.4.96.0/22 1;
    129.134.0.0/16 1;
    157.240.0.0/16 1;
    173.252.64.0/18 1;
    185.60.216.0/22 1;
    204.15.20.0/22 1;
}

Combine this with Nginx's if directive to create conditional authentication:


server {
    listen 443 ssl;
    server_name your-staging.example.com;

    # Basic Auth for everyone except Facebook
    if ($auth_bypass = 0) {
        auth_basic "Restricted Access";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    location /facebook-callback {
        # Facebook-specific handling
        proxy_pass http://your_app_server;
    }
}

For more complex scenarios, consider using the map module:


map $remote_addr $auth_type {
    default "Restricted Access";
    "~^31\.13\." off;
    "~^69\.171\." off;
    # Add other Facebook IP patterns
}

server {
    # ...
    auth_basic $auth_type;
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Remember to:

  • Regularly update Facebook's IP ranges (they change occasionally)
  • Monitor your access logs for authentication failures from legitimate Facebook IPs
  • Consider implementing a fail-safe mechanism that logs unexpected access attempts

Use curl to verify from different IP perspectives:


# Should prompt for credentials
curl -v https://your-staging.example.com

# Should bypass auth (if using a Facebook IP proxy)
curl -v --proxy facebook-ip-proxy:port https://your-staging.example.com

When developing applications with third-party integrations like Facebook Login, HTTP Basic Authentication can block legitimate requests from the service's IP ranges. This creates a testing challenge where you want to protect your staging environment but still allow Facebook's servers to communicate with your endpoints.

The most efficient approach uses NGINX's geo module to create conditional access rules. Here's how to implement it:


# In your http context (nginx.conf or included file)
geo $auth_bypass {
  default         1;
  31.13.0.0/16    0;  # Facebook's primary IP range
  157.240.0.0/16  0;  # Additional Facebook IP range
  129.134.0.0/16  0;  # Instagram IPs (might use same infrastructure)
}

server {
  listen 80;
  server_name yourdomain.com;
  
  location / {
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    # Conditional auth bypass
    if ($auth_bypass = 0) {
      auth_basic off;
    }
  }
}

Facebook's IP ranges change occasionally. You should periodically check their official documentation or WHOIS records. A more dynamic approach would be:


geo $auth_bypass {
  default         1;
  include        /etc/nginx/facebook_ips.conf;
}

Then maintain the IP ranges in a separate file that you can update independently.

For more complex scenarios, the map directive offers additional flexibility:


map $remote_addr $auth_type {
  default        "Restricted Access";
  31.13.0.0/16   off;
  157.240.0.0/16 off;
}

server {
  # ...
  auth_basic $auth_type;
  auth_basic_user_file /etc/nginx/.htpasswd;
}

Remember to:

  • Regularly update the IP range list
  • Monitor NGINX access logs for unexpected patterns
  • Consider additional protections like rate limiting
  • Test thoroughly before deploying to production

Always verify with:


sudo nginx -t
sudo systemctl reload nginx

Use curl to test from different IPs:


curl -I http://yourdomain.com
curl --user user:pass -I http://yourdomain.com