{"id":20825699,"url":"https://github.com/kjdev/nginx-auth-jwt","last_synced_at":"2025-05-07T20:35:05.155Z","repository":{"id":145636360,"uuid":"545777342","full_name":"kjdev/nginx-auth-jwt","owner":"kjdev","description":"Nginx module for the authenticate using JWT","archived":false,"fork":false,"pushed_at":"2025-02-21T22:00:45.000Z","size":338,"stargazers_count":43,"open_issues_count":5,"forks_count":18,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-07T20:34:15.485Z","etag":null,"topics":["authentication","jwt","nginx"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kjdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-05T00:45:55.000Z","updated_at":"2025-05-05T19:31:14.000Z","dependencies_parsed_at":"2023-11-13T00:27:23.551Z","dependency_job_id":"4d67cea9-92d5-458f-86d1-6d5c30e9336b","html_url":"https://github.com/kjdev/nginx-auth-jwt","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjdev%2Fnginx-auth-jwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjdev%2Fnginx-auth-jwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjdev%2Fnginx-auth-jwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjdev%2Fnginx-auth-jwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kjdev","download_url":"https://codeload.github.com/kjdev/nginx-auth-jwt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252953718,"owners_count":21830891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","jwt","nginx"],"created_at":"2024-11-17T23:06:25.138Z","updated_at":"2025-05-07T20:35:05.137Z","avatar_url":"https://github.com/kjdev.png","language":"C","readme":"nginx-auth-jwt\n==============\n\n[JSON Web Token]: https://datatracker.ietf.org/doc/html/rfc7519\n[JSON Web Signature]: https://datatracker.ietf.org/doc/html/rfc7515\n[JSON Web Key Set]: https://datatracker.ietf.org/doc/html/rfc7517#section-5\n[JOSE header]: https://datatracker.ietf.org/doc/html/rfc7515#section-4\n[JWT claim]: https://datatracker.ietf.org/doc/html/rfc7519#section-4\n\nThis nginx module implements client authorization by validating the provided\n[JSON Web Token][] (JWT) using the specified keys.\n\nThe module supports [JSON Web Signature][] (JWS).\n\nThe module can be used for\n[OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html)\nauthentication.\n\n\u003e This module is heavily inspired by the nginx original\n\u003e [http_auth_jwt_module](http://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html).\n\nDependency\n----------\n\n- [jansson](http://www.digip.org/jansson/) header and library.\n- [OpenSSL](http://www.openssl.org/) header and library.\n\nInstallation\n------------\n\n### Build install\n\n``` sh\n$ : \"clone repository\"\n$ git clone https://github.com/kjdev/nginx-auth-jwt\n$ cd nginx-auth-jwt\n$ : \"get nginx source\"\n$ NGINX_VERSION=1.x.x # specify nginx version\n$ wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz\n$ tar -zxf nginx-${NGINX_VERSION}.tar.gz\n$ cd nginx-${NGINX_VERSION}\n$ : \"build module\"\n$ ./configure --add-dynamic-module=../\n$ make \u0026\u0026 make install\n```\n\n### Docker\n\n``` sh\n$ docker build -t nginx-auth-jwt .\n$ : \"app.conf: Create nginx configuration\"\n$ docker run -p 80:80 -v $PWD/app.conf:/etc/nginx/http.d/default.conf nginx-auth-jwt\n```\n\n\u003e GitHub package: ghcr.io/kjdev/nginx-auth-jwt/nginx\n\nSupported Algorithms\n--------------------\n\nThe module supports the following JSON Web\n[Algorithms](https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms).\n\nJWS algorithms:\n\n- HS256, HS384, HS512\n- RS256, RS384, RS512\n- ES256, ES384, ES512\n- ~~EdDSA (Ed25519 and Ed448 signatures)~~\n\nConfiguration\n-------------\n\n### Example\n\n```\nlocation / {\n  auth_jwt          \"closed site\";\n  auth_jwt_key_file conf/keys.json;\n}\n```\n\n### Directives\n\n- [auth_jwt](#auth_jwt)\n- [auth\\_jwt\\_claim\\_set](#auth_jwt_claim_set)\n- [auth\\_jwt\\_header\\_set](#auth_jwt_header_set)\n- [auth\\_jwt\\_key\\_file](#auth_jwt_key_file)\n- [auth\\_jwt\\_key\\_request](#auth_jwt_key_request)\n- [auth\\_jwt\\_validate\\_exp](#auth_jwt_validate_exp)\n- [auth\\_jwt\\_validate\\_sig](#auth_jwt_validate_sig)\n- [auth\\_jwt\\_leeway](#auth_jwt_leeway)\n- [auth\\_jwt\\_phase](#auth_jwt_phase)\n- [auth\\_jwt\\_revocation\\_list\\_sub](#auth_jwt_revocation_list_sub)\n- [auth\\_jwt\\_revocation\\_list\\_kid](#auth_jwt_revocation_list_kid)\n- [auth\\_jwt\\_require](#auth_jwt_require)\n- [auth\\_jwt\\_require\\_claim](#auth_jwt_require_claim)\n- [auth\\_jwt\\_require\\_header](#auth_jwt_require_header)\n- [auth\\_jwt\\_allow\\_nested](#auth_jwt_allow_nested)\n\n\u003ca name=\"auth_jwt\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt string [token=$variable] | off;\nDefault: auth_jwt off;\nContext: server\nContext: http, server, location, limit_except\n```\n\nEnables validation of JSON Web Token. The specified string is used as a realm.\nParameter value can contain variables.\n\nThe optional `token` parameter specifies a variable that contains\nJSON Web Token.\nBy default, JWT is passed in the `Authorization` header as a\n[Bearer Token](https://datatracker.ietf.org/doc/html/rfc6750).\nJWT may also be passed as a cookie or part of a query string:\n\n\u003e ```\n\u003e auth_jwt \"closed site\" token=$cookie_auth_token;\n\u003e ```\n\nThe special value off cancels the effect of the auth_jwt directive inherited\nfrom the previous configuration level.\n\n\u003ca name=\"auth_jwt_claim_set\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_claim_set $variable name ...;\nDefault: -\nContext: http\n```\n\nSets the `variable` to a JWT claim parameter identified by key names.\nFor arrays, the variable keeps a list of array elements separated by commas.\n\n\u003e ```\n\u003e auth_jwt_claim_set $jwt_audience aud;\n\u003e ```\n\n\u003ca name=\"auth_jwt_header_set\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_header_set $variable name ...;\nDefault: -\nContext: http\n```\n\nSets the `variable` to a JOSE header parameter identified by key names.\nFor arrays, the variable keeps a list of array elements separated by commas.\n\n\u003ca name=\"auth_jwt_key_file\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_key_file file [jwks | keyval];\nDefault: -\nContext: http, server, location, limit_except\n```\n\nSpecifies a file for validating JWT signature.\nParameter value can contain variables.\n\nSpecify `jwks` (default) or `keyval` as the file format.\n\n- jwks: [JSON Web Key Set][] format\n\n- keyval: JSON in key-value format\n\n  \u003e Example: `{\"kid\": \"-----BEGIN PUBLIC KEY-----\\nxx..\"}`\n\nSeveral `auth_jwt_key_file` directives can be specified on the same level.\n\n\u003e ```\n\u003e auth_jwt_key_file conf/key.jwks;\n\u003e auth_jwt_key_file conf/keys.json keyval;\n\u003e ```\n\n\u003ca name=\"auth_jwt_key_request\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_key_request uri [jwks | keyval];\nDefault: -\nContext: http, server, location, limit_except\n```\n\nAllows retrieving a key from a subrequest for validating JWT signature and\nsets the URI where the subrequest will be sent to.\nParameter value can contain variables.\n\nSpecify `jwks` (default) or `keyval` as the key format.\n\n- jwks: [JSON Web Key Set][] format\n\n- keyval: JSON in key-value format\n\nTo avoid validation overhead, it is recommended to cache the key file:\n\n\u003e ```\n\u003e proxy_cache_path /data/nginx/cache levels=1 keys_zone=foo:10m;\n\u003e\n\u003e server {\n\u003e   ...\n\u003e   location / {\n\u003e     auth_jwt \"closed site\";\n\u003e     auth_jwt_key_request /jwks_uri;\n\u003e   }\n\u003e\n\u003e   location = /jwks_uri {\n\u003e     internal;\n\u003e     proxy_cache foo;\n\u003e     proxy_pass  http://idp.example.com/keys;\n\u003e   }\n\u003e }\n\u003e ```\n\nSeveral `auth_jwt_key_request` directives can be specified on the same level.\n\n\u003e ```\n\u003e auth_jwt_key_request /jwks_uri;\n\u003e auth_jwt_key_request /public_key keyval;\n\u003e ```\n\n\u003ca name=\"auth_jwt_validate_exp\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_validate_exp on | off;\nDefault: auth_jwt_validate_exp on;\nContext: http, server, location, limit_except\n```\n\nDetermines whether to validating the exp JWT claim.\n\n\u003e Do not process if verified by `auth_jwt_require_claim` directive\n\n\u003ca name=\"auth_jwt_validate_sig\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_validate_sig on | off;\nDefault: auth_jwt_validate_sig on;\nContext: http, server, location, limit_except\n```\n\nDetermines whether to validating JWT signature.\n\n\u003ca name=\"auth_jwt_leeway\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_leeway time;\nDefault: auth_jwt_leeway 0s;\nContext: http, server, location\n```\n\nSets the maximum allowable leeway to compensate clock skew\nwhen verifying the exp and nbf JWT claims.\n\n\u003ca name=\"auth_jwt_phase\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_phase preaccess | access;\nDefault: auth_jwt_phase access;\nContext: http, server, location\n```\n\nSpecifies the phase to be processed.\n\n\u003e ACCESS phase is not executed when a call is made from a subrequest.\n\u003e\n\u003e In the case of a call from a subrequest,\n\u003e [auth\\_jwt\\_key\\_request](#auth_jwt_key_request) cannot\n\u003e be processed. (nested in-memory subrequest)\n\n\u003ca name=\"auth_jwt_revocation_list_sub\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_revocation_list_sub file;\nDefault: -\nContext: http, server, location, limit_except\n```\n\nSpecifies a file with list of JWT sub claims that deny authentication.\n\nParameter value can contain only filepath to json file with objects.\nEvery object should have key(jwt sub) and any additional value, if it needed.\n\n\u003e File format:\n\u003e ```\n\u003e {\"sub\": any}\n\u003e ```\n\n\u003e Example of config:\n\u003e ```\n\u003e auth_jwt_revocation_list_sub /path/to/lockeduserslist.json;`\n\u003e ```\n\n\u003e Example of file:\n\u003e ```\n\u003e {\n\u003e   \"lockedsub1\": {\"locked_at\": \"2023\"},\n\u003e   \"lockedsub2\": {\"locked_reason\": \"bad user\"},\n\u003e   \"lockedsub3\": {\"any_other_property\": 1}\n\u003e }\n\u003e ```\n\n\u003ca name=\"auth_jwt_revocation_list_kid\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_revocation_list_kid file;\nDefault: -\nContext: http, server, location, limit_except\n```\n\nSpecifies a file with list of JWT kid headers that deny authentication.\n\nParameter value can contain only filepath to json file with objects.\nEvery object should have key(jwt header kid) and any additional value,\nif it needed.\n\n\u003e File format:\n\u003e ```\n\u003e {\"kid\": any}\n\u003e ```\n\n\u003e Example of config:\n\u003e ```\n\u003e auth_jwt_revocation_list_kid /path/to/lockedkidlist.json;`\n\u003e ```\n\n\u003e Example of file:\n\u003e ```\n\u003e {\n\u003e   \"test2kid\": {\"revocation_reason\": \"unknown\"}\n\u003e }\n\u003e ```\n\n**Note:** as we know, kid is OPTIONAL parameter by\n[rfc7515](https://datatracker.ietf.org/doc/html/rfc7515#page-11),\nbut if you are using\n[auth\\_jwt\\_revocation\\_list\\_kid](#auth_jwt_revocation_list_kid) directive\n- it means,\nthat kid will grow to **REQUIRED**\n\n\u003ca name=\"auth_jwt_require\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_require $value ... [error=401 | 403] ;\nDefault: -\nContext: http, server, location, limit_except\n```\n\nSpecifies additional checks for JWT validation.\nThe value can contain text, variables, and their combination,\nand must start with a variable.\nThe authentication will succeed only if all the values are not empty\nand are not equal to \"0\".\n\n\u003e ```\n\u003e map $jwt_claim_iss $valid_jwt_iss {\n\u003e     \"good\" 1;\n\u003e }\n\u003e ...\n\u003e\n\u003e auth_jwt_require $valid_jwt_iss;\n\u003e ```\n\nIf any of the checks fails, the 401 error code is returned.\nThe optional error parameter allows redefining the error code to 403.\n\n\u003ca name=\"auth_jwt_require_claim\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_require_claim claim_name operator $variable | json=string | string;\nDefault: -\nContext: http, server, location, limit_except\n```\n\nSpecifies a requirement for claim in jwt token.\n\n\u003e Example:\n\u003e ```\n\u003e http {\n\u003e   map $request_method $required_jwt_roles {\n\u003e     \"GET\"  '[\"SERVICE\", \"ADMINISTRATORS\"]';\n\u003e   }\n\u003e   server {\n\u003e     ...\n\u003e     location = /verify {\n\u003e       set $expected_less_than_iat 1697461110;\n\u003e\n\u003e       auth_jwt_require_claim jti eq 3949117906; # string\n\u003e       auth_jwt_require_claim iat eq json=1697461112; # integer\n\u003e       auth_jwt_require iat lt $expected_less_than_iat;\n\u003e       # auth_jwt_require iat lt json=1697461110;\n\u003e       auth_jwt_require_claim roles intersect $required_jwt_roles;\n\u003e       # auth_jwt_require_claim roles intersect json=[\"SERVICE\",\"ADMINISTRATORS\"];\n\u003e     }\n\u003e     ...\n\u003e ```\n\nSeveral `auth_jwt_require_claim` directives can be specified\non the same level for \"AND\" logic.\n\n`claim_name` - should be a name of jwt claim. (sub,roles,scope)\n\n`operator` - should be one of:\n```\neq = equal operator\nne = not equal operator\ngt = greater than operator\nge = greater or equal operator\nlt = less than operator\nle = less or equal operator\nintersect = has intersection operator\nnintersect = has not intersection operator\nin = in array operator\nnin = not in array operator\n```\n1. Two integer or real values are equal if their contained numeric values\n   are equal. An integer value is never equal to a real value, though.\n2. Two strings are equal if their contained UTF-8 strings are equal,\n   byte by byte. Unicode comparison algorithms are not implemented.\n3. Two arrays are equal if they have the same number of elements and each\n   element in the first array is equal to the corresponding element\n   in the second array.\n4. Two objects are equal if they have exactly the same keys and the value\n   for each key in the first object is equal to the value of the\n   corresponding key in the second object.\n\n`$variable` - should be a nginx variable, that provide\nrequired json[^json] value.\n\n\u003e Examples:\n\u003e ```\n\u003e set $expected_jti '\"3949117906\"';\n\u003e set $expected_iat 1697461112;\n\u003e set $expected_less_than_iat 1697461110;\n\u003e map $request_method $role_map_verify {\n\u003e   \"GET\"  '[\"SERVICE\", \"ADMINISTRATORS\"]';\n\u003e }\n\u003e ```\n\n[^json]: containing only single value is pretty valid.\n\n\u003ca name=\"auth_jwt_require_header\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_require_header header_name operator $variable;\nDefault: -\nContext: http, server, location, limit_except\n```\nSpecifies a requirement for header in jwt token.\n\nAll possibilities of this directive are the same as for\n[auth\\_jwt\\_require\\_claim](#auth_jwt_require_claim) above.\n\n\u003ca name=\"auth_jwt_allow_nested\"\u003e\u003c/a\u003e\n```\nSyntax: auth_jwt_allow_nested [delimiter=string] [quote=string];\nDefault: -\nContext: http, server, location\n```\nAllow access to nested claim/headers in jwt token.\n\nThe optional `delimiter` parameter sets the nesting delimiter\n(default value is `.`).\n\nThe optional `quote` parameter sets the quote character for the key\n(default value is `\"`).\n\n\u003e Examples:\n\u003e ```\n\u003e auth_jwt_allow_nested;\n\u003e auth_jwt_require_claim grants.access eq allow;\n\u003e auth_jwt_require_claim '\"grants.key\"' eq dot;\n\u003e ```\n\u003e\n\u003e JWT payload:\n\u003e ```\n\u003e {\n\u003e   \"grants\": {\n\u003e     \"access\": \"allow\"\n\u003e   },\n\u003e   \"grants.key\": \"dot\"\n\u003e }\n\u003e ```\n\n### Embedded Variables\n\nThe module supports embedded variables:\n\n```\n$jwt_header_\u003cname\u003e\n```\n\nreturns the value of a specified [JOSE header][].\n\n```\n$jwt_claim_\u003cname\u003e\n```\n\nReturns the value of a specified [JWT claim][].\nFor arrays, the variable keeps a list of array elements separated by commas.\n\n```\n$jwt_claims\n```\n\nReturns the value of [JWT claim][] (JSON).\n\n```\n$jwt_nowtime\n```\n\nReturns the value of now timestamp.\n\nExample\n-------\n\n- [OpenID Connect Authentication](example/README.md)\n\n\nTODO\n----\n\n- [ ] `auth_jwt_key_request` in subrequests (nested in-memory subrequest)\n- Support algorithms\n  - [ ] EdDSA (JWK key type: OKP)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjdev%2Fnginx-auth-jwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkjdev%2Fnginx-auth-jwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjdev%2Fnginx-auth-jwt/lists"}