Giter Club home page Giter Club logo

nginx-jwt-module's Introduction

Nginx jwt auth module

License Build Status Build Status

This is an NGINX module to check for a valid JWT.

Inspired by TeslaGov, ch1bo and tizpuppi, this module intend to be as light as possible and to remain simple.

Module:

Example Configuration:

# nginx.conf
load_module /usr/lib/nginx/modules/ngx_http_auth_jwt_module.so;
# server.conf
server {
    auth_jwt_key "0123456789abcdef" hex; # Your key as hex string
    auth_jwt     off;

    location /secured-by-cookie/ {
        auth_jwt $cookie_MyCookieName;
    }

    location /secured-by-auth-header/ {
        auth_jwt on;
    }

    location /secured-by-auth-header-too/ {
        auth_jwt_key "another-secret"; # Your key as utf8 string
        auth_jwt on;
    }

    location /secured-by-rsa-key/ {
        auth_jwt_key /etc/keys/rsa-public.pem file; # Your key from a PEM file
        auth_jwt on;
    }

    location /not-secure/ {}
}

Note: don't forget to load the module in the main context:
load_module /usr/lib/nginx/modules/ngx_http_auth_jwt_module.so;

Directives:

auth_jwt

Syntax:	 auth_jwt $variable | on | off;
Default: auth_jwt off;
Context: http, server, location

Enables validation of JWT.

The auth_jwt $variable value can be used to set a custom way to get the JWT, for example to get it from a cookie instead of the default Authentication header: auth_jwt $cookie_MyCookieName;


auth_jwt_key

Syntax:	 auth_jwt_key value [encoding];
Default: ——
Context: http, server, location

Specifies the key for validating JWT signature (must be hexadecimal).
The encoding otpion may be hex | utf8 | base64 | file (default is utf8).
The file option requires the value to be a valid file path (pointing to a PEM encoded key).


auth_jwt_alg

Syntax:	 auth_jwt_alg any | HS256 | HS384 | HS512 | RS256 | RS384 | RS512 | ES256 | ES384 | ES512;
Default: auth_jwt_alg any;
Context: http, server, location

Specifies which algorithm the server expects to receive in the JWT.


auth_jwt_require

Syntax:	 auth_jwt_require $value ... [error=401 | 403];
Default: ——
Context: http, server, location

Specifies additional checks for JWT validation. The authentication will succeed only if all the values are not empty and are not equal to “0”.

These directives are inherited from the previous configuration level if and only if there are no auth_jwt_require directives defined on the current level.

If any of the checks fails, the 401 error code is returned. The optional error parameter allows redefining the error code to 403.

Example:

# server.conf

map $jwt_claim_role $jwt_has_admin_role {
    \"admin\"  1;
}

map $jwt_claim_scope $jwt_has_restricted_scope {
    \"restricted\"  1;
}

server {
  # ...

  location /auth-require {
    auth_jwt_require $jwt_has_admin_role error=403;
    # ...
  }

  location /auth-compound-require {
    auth_jwt_require $jwt_has_admin_role $jwt_has_restricted_scope error=403;
    # ...
  }
}

Note that as $jwt_claim_ returns a JSON-encoded value, so we have to check \"value\" (and not value)

Embedded Variables:

The ngx_http_auth_jwt_module module supports embedded variables:

  • $jwt_header_name returns the specified header value
  • $jwt_claim_name returns the specified claim value
  • $jwt_headers returns headers
  • $jwt_payload returns payload

Note that as all returned values are JSON-encoded, so string will be surrounded by " character

Image:

Image is generated with Github Actions (see nginx-jwt-module:latest)

docker pull ghcr.io/max-lt/nginx-jwt-module:latest

Simply create your image from Github's generated one

FROM ghcr.io/max-lt/nginx-jwt-module:latest

# Copy your nginx conf
# Don't forget to include this module in your configuration
# load_module /usr/lib/nginx/modules/ngx_http_auth_jwt_module.so;
COPY my-nginx-conf /etc/nginx

EXPOSE 8000

STOPSIGNAL SIGTERM

CMD ["nginx", "-g", "daemon off;"]

Build:

This module is built inside a docker container, from the nginx-alpine image.

make build # Will create a "jwt-nginx" image
# or
docker build -f Dockerfile -t jwt-nginx .

Test:

Default usage:

make test # Will build a test image & run test suite

nginx-jwt-module's People

Contributors

dependabot[bot] avatar jijeesh avatar kahuna-celsius avatar mawi12345 avatar max-lt avatar rekgrpth avatar yelijah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nginx-jwt-module's Issues

limit_req_zone with jwt embedded variables

Hi there,

I'm trying to set rate limits using jwt embedded variables. But it doesn't work.
Configuration example:

http {
...

  limit_req_zone $jwt_claim_id zone=lreq_user:10m rate=1r/m;
  ...
  server {
    auth_jwt off;
    auth_jwt_key /etc/nginx/certs/jwt.pem file;
    ...
    location /api/ {
      auth_jwt on;
      limit_req zone=lreq_user;
      ...
    }
  }
}

It looks like $jwt_claim_id is defined as an empty value in the limit_req_zone directive, because with this configuration, the rate limit worked:

http {
...
  map $jwt_claim_id $test {
     \"100172\" 0;
     "" 1;
    }

  limit_req_zone $test zone=lreq_user:10m rate=1r/m;
  ...
  server {
    auth_jwt off;
    auth_jwt_key /etc/nginx/certs/jwt.pem file;
    ...
    location /api/ {
      auth_jwt on;
      limit_req zone=lreq_user;
      ...
    }
  }
}

Also strange behavior when using the auth_jwt_require directive, with this configuration nginx responds with a 403 code:

http {
...

  limit_req_zone $jwt_claim_id zone=lreq_user:10m rate=1r/m;
  ...
  server {
    auth_jwt off;
    auth_jwt_key /etc/nginx/certs/jwt.pem file;
    ...
    location /api/ {
      auth_jwt on;
      limit_req zone=lreq_user;
      auth_jwt_require $jwt_claim_id error=403;
      ...
    }
  }
}

Without the line limit_req zone=lreq_user; nginx works fine

jwt parse error

Hi,
I'm trying to get this working, but it isn't really clear to me as what format should be the auth_jwt_key.
Obviously I'm doing something wrong, cause I'm getting "JWT: failed to parse jwt" error.

let's say that my secret key is "HELLO WORLD". What should put into the auth_jwt_key?
just copy & paste the string? Or should I convert it into hex -> "48454c4c4f20574f524c44"
and then copy it and paste there?

Add explicit auth_jwt_alg

Should there maybe be an explicit (optional) auth_jwt_alg config setting to specify the expected algorithm for the JWT?

Including the module without setting directive blocks all requests

Including the module without setting directive blocks all requests.

Currently if no auth_jwt directive is set the jwt_flag variable stays set to -1 (which is an incorrect state) and all requests (whose context is not overwritten) are rejected.


A workaround is to set auth_jwt=off on http context.

(No such file or directory) in /etc/nginx/test-jwt-nginx.conf:41

I am using this dockerfile to build the image

FROM jwt-nginx

# Get nginx ready to run
COPY nginx /etc/nginx

EXPOSE 8000

STOPSIGNAL SIGTERM

CMD ["nginx", "-g", "daemon off;"]

build: docker build -f Dockerfile -t jwt-custom .
run: docker container run -p 8080:8000 jwt-custom

Error

...
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/12/29 08:24:24 [error] 1#1: No such file or directory (2: No such file or directory) in /etc/nginx/test-jwt-nginx.conf:41
nginx: [error] No such file or directory (2: No such file or directory) in /etc/nginx/test-jwt-nginx.conf:41

I have verified that the file is indeed present in /etc/nginx folder

Build is not compiling auth_jwt module

Hello @Maxx-T!

Thanks for sharing this repo. This is what I was looking for to do not need to buy a nginx plus or going for caddy.

I ran ./build and started my container with the following:

docker run -d --rm --name proxy -v /html/:/var/www/html -v /etc/nginx:/etc/nginx -p "80:80" jwt-nginx

In the nginx.conf file I had a very basic settings, but when addind the auth_jwt option and reloading nginx I get the message:

unknown directive "auth_jwt" in /etc/nginx/nginx.conf

I just added this options to server block as in README file:

server {

       auth_jwt_key "9e588fb43b6a1248531156e284c2bea7" hex;
       auth_jwt off;
[...]

Could you please confirm if there is anything we must enable before using this directive?

Thanks!

jwt_get_alg(jwt) returns 0

Hi there,

I am really confused, because I always get 401, because I receive an error that token algorithm is not valid. I found out, that it is always returning 0. My config looks like this

location = /jwt/secured {
    auth_jwt on;
    auth_jwt_alg any;
    return 200;
}

It happens here:
https://github.com/max-lt/nginx-jwt-module/blob/master/src/ngx_http_auth_jwt_module.c#L162

If I comment this block out it works fine

It seems to be an error in jwtlib:
benmcollins/libjwt#156
so a workarround is necessary. Or do you have any other idea?

Cookie description in documentation

I have been trying to use the cookie variant for authentication, but keep getting a JWT parse error. Using the default header option works as expected.

I couldn’t find a good reference how that cookie should look like and tried prefixing the JWT with Bearer e... and also tried without, but neither worked. Could you please enlighten me if I need to encode the cookie value somehow?

Thank you!

Merge auth_jwt_key_file and auth_jwt_key

Suggested in #3:

Directives auth_jwt_key_file and auth_jwt_key may be merged since this are two conflicting options defining the same variable.

The syntax could be auth_jwt_key (value | file)=(value or file path) [encoding]

Small improvements to documentation

Could you please add another sentence to the README regarding auth_jwt_key_file? I am assuming right that it is basically just a replacement for auth_jwt_key, which reads the key from a file, but it's not immediately obvious if either or both can be provided.

Maybe it would be even better to get rid of auth_jwt_key_file all together and just check if auth_jwt_key could be a file path.

auth_jwt with variables does not work

Hi,
I'm trying to configure the jwt check depending on the request method:

http {
...
  map $request_method $jwt_validate {
          POST  on;
          default    off;
  }

  ...
  server {
    auth_jwt off;
    auth_jwt_key /etc/nginx/certs/jwt.pem file;
    ...
    location /api/ {
      auth_jwt $jwt_validate;
      ...
    }
  }
}

But I get a 401 response code with any request method

Handle auth_request directive double check

The auth_request directive sould not be triggered when the auth_jwt one successfully authenticates the request:

  • auth_jwt must be executed before auth_request (because it is fastest).
  • auth_request must be called only if auth_jwt is disabled or failed to authenticates the request.

This behavior must be optional:

  • add a directive to enable it (auth_jwt_options [handle_auth_request]?)

$jwt_claim_* not set in `rewrite` or `if`

Might be related to #28, but doing something like this causes an error:

if ($jwt_claim_p != "some_str") {
  return 503;
}

This gives me an error in the nginx logs *1 invalid size "".

Similarly you can't use $jwt_claim_* in rewrite or proxy_pass (they're empty), so you cannot use it to verify that the URI is actually allowed to be used, by adding the URI itself as a claim ($jwt_claim_allowed_uri). That seems like an important use case of JWTs to me!

Dynamically toggle `auth_jwt`

auth_jwt $variable

Is it possible for the $variable to be on or off? I tried it and it didn't work but I'm wondering if I can achieve this somehow.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.