TeslaGov / ngx-http-auth-jwt-module

Secure your NGINX locations with JWT
MIT License
308 stars 118 forks source link

Not able to use variables for if-statements or in redirect uris #112

Open mariosdimitradis opened 8 months ago

mariosdimitradis commented 8 months ago

First of all, thank you for this module. I currently facing some issues and need some help to make it work for me.

The JWT-Token looks like this: Header:

{
  "typ": "JWT",
  "alg": "RS256"
}

Payload:

{
  "exp": 1698974933,
  "iat": 1698938933,
  "scope": "read write",
  "custgroup": "B2B, PreSale"
  ...
}

The Nginx vHost configurations looks like this:

location / {
  auth_jwt_location HEADER=Authorization;
  auth_jwt_enabled on;
  auth_jwt_algorithm RS256;
  auth_jwt_use_keyfile on;
  auth_jwt_keyfile_path /etc/nginx/jwtPub.key;
  auth_jwt_extract_request_claims custgroup;
}

This is working fine without any issues. When I try to access $http_jwt_custgroup in if-statement or return it is not working.

Example:

location / {
  ...
  return 307 /$http_jwt_custgroup;
  ...
}
location / {
  ...
  if ($http_jwt_custgroup ~* "B2B") {
    return 307 /b2b-access;
  }
  ...
}

The above httpjwt* variables works also can be also added to the header with add_header. I also tried to set a new variable with set $myVar $http_jwt_custgroup;, but also not working.

Are any limitations? The Example from the README.md file is also not working for me.

location /profile/me {
    auth_jwt_extract_request_claims sub;

    return 301 /profile/$http_jwt_sub;
}
JoshMcCullough commented 8 months ago

In the past I've tried very hard to get this working, but it appears to be a limitation of NGINX.

mgilham commented 7 months ago

Here is a workaround, if you're willing to use njs.

Define a JS function to extract the desired field from the JWT, like in the nginx njs example.

Then you can use this ngx-http-auth-jwt-module to validate the JWT, and use the JS to extract the variable in a usable form. For example, this applies authorization based on the sub claim:

    js_path "/etc/nginx/njs/";
    js_import main from /etc/nginx/your.js;
    js_set $jwt_payload_sub main.jwt_payload_sub;

    map $jwt_payload_sub $authorized_user {
        default 0;
        include /etc/nginx/auth/users;
    }

    server {
        listen 8173;

        auth_jwt_use_keyfile on;
        auth_jwt_algorithm RS256;
        auth_jwt_keyfile_path "/etc/nginx/auth/pub_key.pem";
        auth_jwt_location COOKIE=__Secure-auth;
        auth_jwt_validate_sub on;

        location / {
            auth_jwt_enabled on;
            if ($authorized_user = 0) {
                return 403;
            }
            proxy_pass ...
        }

I imagine the performance is terrible compared to native code, but it seems to work well enough for my present purposes.

mgilham commented 7 months ago

I raised a PR to make this work in-module, and extended the tests to cover: https://github.com/TeslaGov/ngx-http-auth-jwt-module/pull/113