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.
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
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;
}
...
}
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;
}
...
}
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;
}
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With