Limit http request methods in Nginx (authentication except for GET)

Written by - 0 comments

Published on - Listed in Nginx Linux

Was looking for a way to tell Nginx to let all GET requests through but all other requests (e.g. POST, PUT, etc) should be authenticated.

On my research I found a lot of examples using "if", like this one (found here):

if ($request_method !~ ^(GET|HEAD|POST)$ )
    return 444;

However there are two problems.

1) if is evil

2) basic auth does not work within an if clause in Nginx. So the following snippet doesn't work:

if ($request_method !~ ^GET$ )
  auth_basic "Login required";
  auth_basic_user_file /etc/nginx/auth/.htpasswd;

Belive me, I tried it and fell on my nose... On my research WHY it fails, I came across this page which explains it nicely:

The reason why it fails is because if is not part of the general configuration module as one should believe. if is part of the rewrite module and auth_basic is another module. That’s one of the reason why the Nginx community thinks if is evil.

Eventually I came across the limit_except method, which is part of the Nginx core module. By using this method, one can define special limits for http request methods. The documentation describes the method in a bizarre way though:

Limits allowed HTTP methods inside a location. The method parameter can be one of the following: GET, HEAD, POST, PUT, DELETE, MKCOL, COPY, MOVE, OPTIONS, PROPFIND, PROPPATCH, LOCK, UNLOCK, or PATCH. Allowing the GET method makes the HEAD method also allowed. Access to other methods can be limited using the ngx_http_access_module and ngx_http_auth_basic_module modules directives

What I mean with bizarre: It's not clear whether the limitation is now for the mentioned request methods or for the unlisted request methods. But a configuration change quickly showed me that it works the following way:

  location /api/ {

    # Only allow GET, all other methods require basic auth
    limit_except GET {
      auth_basic           "Login required";
      auth_basic_user_file /etc/nginx/auth/.htpasswd;

    include /etc/nginx/proxy.conf;

The comment I added just above limit_except explains it: Set a limit for all http request methods (load the auth_basic stuff) EXCEPT the request method is GET.

Works nicely and I didn't have to use "if" either.

Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.