Skip to Content

Deny HTTP request methods in Nginx

Posted on

In certain situations you might need to restrict access to your web application based on the request method. Maybe because the method isn’t implemented, or you need to deny certain actions as part of your security policy.

If you search for answers to this problem on StackOverflow or Google, you will find a lot of examples that use an if statement to check the value of $request_method. But there’s a better way!

Nginx features the limit_except directive, which allows you to limit HTTP methods inside location blocks. For example, to only allow POST requests to the /api URL, use this:

location /api {
    limit_except POST {
        deny all;     
    }
}

This will return a 403 - Forbidden status if you try anything else but a POST request:

$ curl -X GET http://yourwebsite.com/api/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

Note that allowing the GET method also makes the HEAD method allowed.

You can still grant access to certain IPs and IP ranges using the allow directive:

limit_except POST {
    allow 192.168.1.1/24;
    deny all;     
}

Nginx now allows full access again to any IP in the 192.168.1.1 to 192.168.1.254 range.

Alternatively, it’s possible to require a username and password via basic auth for the limited request methods. Instead of using allow and deny, you can use auth_basic:

limit_except POST {
    auth_basic "Restricted access";
    auth_basic_user_file /etc/nginx/htpasswd;
}

If you try the previous GET request, the response is no longer 403 Forbidden but 401 Authorization Required. Passing in a username and password will now succeed:

$ curl -X GET --user username:password http://yourwebsite.com/api/
{'result': 'your API response to a GET request'}

Easy!

comments powered by Disqus