Skip to content

smartgic/nginx-jwt-module

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Alpine version Nginx version Docker pulls Discord

Nginx JWT authentication module

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

Inspired by TeslaGov and max-lt repositories.

docker run -d \
  --name nginx \
  -v type=bind,source=/home/goldyfruit/infrastructure/nginx-jwt-module/jwt_redirect_ssl.conf,target=/etc/nginx/conf.d/jwt.conf smartgic/ \
  -p 80:80 \
  -p 443:443 \
  nginx-jwt-module

Supported architectures

Architecture Information
amd64 Such as AMD and Intel processors
arm/v6 Such as Raspberry Pi 1
arm/v7 Such as Raspberry Pi 2/3/4
arm64 Such as Raspberry Pi 4 64-bit

These are examples, many other boards use these CPU architectures.

NGINX Directives

This module requires several new nginx.conf directives, which can be specified in on the main, server or location level.

auth_jwt_key "646f6e2774207472792c206974277320612066616b6520736563726574203a29"; # see docs below for format based on algorithm
auth_jwt_loginurl "https://yourdomain.com/loginpage";
auth_jwt_enabled on;
auth_jwt_algorithm HS256; # or RS256
auth_jwt_validate_email on;  # or off
auth_jwt_use_keyfile off; # or on
auth_jwt_keyfile_path "/app/pub_key";

The default algorithm is HS256, for symmetric key validation. When using HS256, the value for auth_jwt_key should be specified in hex format. It is recommended to use at least 256-bits of data (32 pairs of hex characters or 64 characters in total) as in the example above. Note that using more than 512-bits will not increase the security. For key guidelines please see NIST Special Publication 800-107 Recommendation for Applications Using Approved Hash Algorithms, Section 5.3.2 The HMAC Key.

The configuration also supports the auth_jwt_algorithm RS256, for RSA 256-bit public key validation. If using auth_jwt_algorithm RS256;, then the auth_jwt_key field must be set to your public key OR auth_jwt_use_keyfile should be set to on with the auth_jwt_keyfile_path set to the public key path (Nginx won't start if the auth_jwt_use_keyfile is set to on without a keyfile).

That is the public key, rather than a PEM certificate. I.e.:

auth_jwt_key "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0aPPpS7ufs0bGbW9+OFQ
RvJwb58fhi2BuHMd7Ys6m8D1jHW/AhDYrYVZtUnA60lxwSJ/ZKreYOQMlNyZfdqA
rhYyyUkedDn8e0WsDvH+ocY0cMcxCCN5jItCwhIbIkTO6WEGrDgWTY57UfWDqbMZ
4lMn42f77OKFoxsOA6CVvpsvrprBPIRPa25H2bJHODHEtDr/H519Y681/eCyeQE/
1ibKL2cMN49O7nRAAaUNoFcO89Uc+GKofcad1TTwtTIwmSMbCLVkzGeExBCrBTQo
wO6AxLijfWV/JnVxNMUiobiKGc/PP6T5PI70Uv67Y4FzzWTuhqmREb3/BlcbPwtM
oQIDAQAB
-----END PUBLIC KEY-----";

OR

auth_jwt_use_keyfile on;
auth_jwt_keyfile_path "/etc/nginx/pub_key.pem";

A typical use would be to specify the key and loginurl on the main level and then only turn on the locations that you want to secure (not the login page). Unauthorized requests are given 302 "Moved Temporarily" responses with a location of the specified loginurl.

auth_jwt_redirect off;

If you prefer to return 401 Unauthorized, you may turn auth_jwt_redirect to off.

auth_jwt_validation_type AUTHORIZATION;
auth_jwt_validation_type COOKIE=rampartjwt;

By default the authorization header is used to provide a JWT for validation. However, you may use the auth_jwt_validation_type configuration to specify the name of a cookie that provides the JWT.

auth_jwt_validate_email off;

By default, the module will attempt to validate the email address field of the JWT, then set the x-email header of the session, and will log an error if it isn't found. To disable this behavior, for instance if you are using a different user identifier property such as sub, set auth_jwt_validate_email to the value off.

Example

In this example, the route / from push.smartgic.io listening on port 80 is protected by a JWT authentication. If the JWT is valid then, the request is redirected to https://pushgateway.appdomain.cloud. Only the POST is allowed.

server {
    listen 80;
    server_name push.smartgic.io;

    location / {
        if ($request_method ~ ^(GET|PATCH|PUT|DELETE|OPTIONS|HEAD)$) {
            return 403;
        }

        auth_jwt_key "646f6e2774207472792c206974277320612066616b6520736563726574203a29";
        auth_jwt_enabled on;
        auth_jwt_redirect off;
        auth_jwt_validate_email off;

        proxy_set_header Host pushgateway.appdomain.cloud;
        proxy_pass       https://pushgateway.appdomain.cloud;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Host $remote_addr;
        proxy_buffering  off;
    }
}

There is a complete example of JWT and TLS (via Let's Encrypt) in the examples directory.

Encode a string to hex using Python.

key = "don't try, it's a fake secret :)".encode("utf-8")
print(key.hex())
646f6e2774207472792c206974277320612066616b6520736563726574203a29