9

My problem is the exact same one as described here: Disable authentication for HTTP OPTIONS method (preflight request). I'm trying to use CORS and HTTP passwords at the same time. When the browser see an bounced OPTIONS (status code 401), for some reason it'll immediate check for the CORS headers (which will be absent) and reject the request.

Here's my config:

location /api/ {
    proxy_pass http://127.0.0.1:14000;
    proxy_set_header Host $host;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type";
    add_header Access-Control-Allow-Credentials true;
    auth_basic            "Restricted Area";
    auth_basic_user_file  /var/www/admin.htpasswd;
}
cleong
  • 281
  • 1
  • 2
  • 8

3 Answers3

8

Here's the solution I came up with. It insolves duplicating all the CORS add_header directives though.

location /api/ {
    proxy_pass http://127.0.0.1:14000;
    proxy_set_header Host $host;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type";
    add_header Access-Control-Allow-Credentials true;
    if ($request_method = OPTIONS) {
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type";
        add_header Access-Control-Allow-Credentials true;
        return 200;
    }
    auth_basic            "Restricted Area";
    auth_basic_user_file  /var/www/admin.htpasswd;
}
cleong
  • 281
  • 1
  • 2
  • 8
  • If you use the headers_more module, you'll be able to avoid redundancy and configure this in more clean way: https://gist.github.com/anonymous/b843bd579041188441f51a7805cf537e – Jan Koriťák Dec 09 '16 at 16:27
4

I found a cleaner solution which lets node manage the request:

Put the following configuration inside "location" and remove any auth_basic from server. This will work.

  location / {
    # Your node proxy configuration for example #

    # Make options requests work #
    limit_except OPTIONS {
      auth_basic "Restricted access zone";
      auth_basic_user_file /etc/nginx/pass/protected;
    }
  }
Andrew Schulman
  • 8,561
  • 21
  • 31
  • 47
Poyoman
  • 141
  • 4
1

Following information at limit_except/if blocks problems, I'd suggest using map:

map $request_method $auth_basic_value {
    default "Restricted";
    "OPTIONS" "off";
}


location / {
        auth_basic $auth_basic_value;
}

Keep in mind, that if you have some try_files in that location, that may rewrite the query to another location, then you may also need to set auth_basic $auth_basic_value.

Dale C. Anderson
  • 577
  • 1
  • 5
  • 13
Mios
  • 111
  • 3
  • Submitted an [edit](https://serverfault.com/review/suggested-edits/525801) for your solution, which does work (after the edit), and is by far the simplest I've seen. – Dale C. Anderson Jul 20 '22 at 18:06