NGINX rate limitting by decoded values from JWT token

3k Views Asked by At

I have a question regarding NGINX rate limiting.

Is it possible to do rate limiting based on the decoded value of JWT token? I cannot find any information like this in the docs.

Or even if there is a way of doing rate limiting by creating pure custom variable (using LuaJIT) which will be assigned with a value from my decoded JWT - will also do the job. The thing is that the limit_req module seems to execute way before the request reaches the luaJIT stage so its already too late!

A solution will be appreciated.

2

There are 2 best solutions below

1
On BEST ANSWER

As you may know that rate limit is applied through unique ip address for best result you should use unique jwt value or token to rate limit.

You can follow any of these 3 methods

  1. Method

You can directly use jwt token in limit_req_zone.

http {
    ...
    limit_req_zone $http_authorization zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($http_authorization = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $http_authorization;
    }
    ...
}
  1. Method

You can send decoded jwt value from frontend in reqest header like http_x_jwt_decode_value and then you can use that in limit_req_zone.

http {
    ...
    limit_req_zone $http_x_jwt_decode_value zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($http_x_jwt_decode_value = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $http_x_jwt_decode_value;
    }
    ...
}
  1. Method

You can decode jwt token in nginx though njs javascript module or perl module or lua module and assign it to variable then use that to rate limit.

Description: here i just decoded jwt value and checked if its not empty you can use it to work with and jwt decoded value.

jwt_example.js

function jwt(data) {
  var parts = data.split('.').slice(0,2)
    .map(v=>String.bytesFrom(v, 'base64url'))
    .map(JSON.parse);
  return { headers:parts[0], payload: parts[1] };
}

function jwt_payload_sub(r) {
  return jwt(r.headersIn.Authorization.slice(7)).payload.sub;
}

export default {jwt_payload_sub}

nginx.conf


# njs module
load_module modules/ngx_http_js_module.so;

http {
    ...
    include /etc/nginx/conf.d/*.conf;

    js_import main from jwt_example.js;

    js_set $jwt_payload_sub main.jwt_payload_sub;

    limit_req_zone $jwt_payload_sub zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($jwt_payload_sub = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $jwt_payload_sub;
    }
    ...
}
1
On

JWT Auth for Nginx

nginx-jwt is a Lua script for the Nginx server (running the HttpLuaModule) that will allow you to use Nginx as a reverse proxy in front of your existing set of HTTP services and secure them (authentication/authorization) using a trusted JSON Web Token (JWT) in the Authorization request header, having to make little or no changes to the backing services themselves.

IMPORTANT: nginx-jwt is a Lua script that is designed to run on Nginx servers that have the HttpLuaModule installed. But ultimately its dependencies require components available in the OpenResty distribution of Nginx. Therefore, it is recommended that you use OpenResty as your Nginx server, and these instructions make that assumption.

Configuration

At the moment, nginx-jwt only supports symmetric keys (alg = hs256), which is why you need to configure your server with the shared JWT secret below.

1.Export the JWT_SECRET environment variable on the Nginx host, setting it equal to your JWT secret. Then expose it to Nginx server:

# nginx.conf:

env JWT_SECRET;

2.If your JWT secret is Base64 (URL-safe) encoded, export the JWT_SECRET_IS_BASE64_ENCODED environment variable on the Nginx host, setting it equal to true. Then expose it to Nginx server:

# nginx.conf:

env JWT_SECRET_IS_BASE64_ENCODED;

JWT Auth for Nginx