{"id":28403638,"url":"https://github.com/juliaweb/jwts.jl","last_synced_at":"2026-03-09T08:32:01.385Z","repository":{"id":45404296,"uuid":"164989697","full_name":"JuliaWeb/JWTs.jl","owner":"JuliaWeb","description":"JSON Web Tokens (JWT) for Julia","archived":false,"fork":false,"pushed_at":"2025-10-10T05:22:45.000Z","size":57,"stargazers_count":18,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-18T07:41:57.364Z","etag":null,"topics":["julialang","jwkset","jwt","jwt-authentication","signing"],"latest_commit_sha":null,"homepage":null,"language":"Julia","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuliaWeb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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,"zenodo":null}},"created_at":"2019-01-10T04:27:40.000Z","updated_at":"2025-10-10T05:05:39.000Z","dependencies_parsed_at":"2024-06-18T01:42:53.660Z","dependency_job_id":"57cdaea2-efd5-478e-93b5-92c2468df1d0","html_url":"https://github.com/JuliaWeb/JWTs.jl","commit_stats":{"total_commits":22,"total_committers":3,"mean_commits":7.333333333333333,"dds":0.09090909090909094,"last_synced_commit":"dece86f6a9f74258c7c5b463e8f71992cefa6ebc"},"previous_names":["tanmaykm/jwts.jl"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/JuliaWeb/JWTs.jl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FJWTs.jl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FJWTs.jl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FJWTs.jl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FJWTs.jl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuliaWeb","download_url":"https://codeload.github.com/JuliaWeb/JWTs.jl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FJWTs.jl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30287831,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["julialang","jwkset","jwt","jwt-authentication","signing"],"created_at":"2025-06-01T18:38:15.856Z","updated_at":"2026-03-09T08:32:01.357Z","avatar_url":"https://github.com/JuliaWeb.png","language":"Julia","readme":"# JWTs\n\n[![Build Status](https://github.com/JuliaWeb/JWTs.jl/workflows/CI/badge.svg)](https://github.com/JuliaWeb/JWTs.jl/actions?query=workflow%3ACI+branch%3Amaster)\n[![codecov](https://codecov.io/gh/JuliaWeb/JWTs.jl/branch/master/graph/badge.svg?token=VK7JZ2hMQx)](https://codecov.io/gh/JuliaWeb/JWTs.jl)\n\nJSON Web Tokens (JWT) are an open, industry standard [RFC 7519](https://tools.ietf.org/html/rfc7519) method for representing and transferring claims securely between two parties.\n\n## Keys and Key Sets\n\n**JWK** represents a JWK Key (either for signing or verification). JWK can be either a **JWKRSA** or **JWKSymmetric**. A RSA key can represent either the public or private key. Ref: https://datatracker.ietf.org/doc/html/rfc7517\n\n**JWKSet** holds a set of keys, fetched from a OpenId key URL, each key identified by a key id. The OpenId key URL is usually found in the OpenId configuration (e.g. `jwks_uri` element in \u003chttps://accounts.google.com/.well-known/openid-configuration\u003e).\n\nTo create or verify JWT, using a JWKSet is preferred as it provides mechanism of dealing with key rotation. To refresh a JWKSet, or to load keys for the first time, call the `refresh!` method on it.\n\n```julia\njulia\u003e using JWTs\n\njulia\u003e keyset = JWKSet(\"https://www.googleapis.com/oauth2/v3/certs\")\nJWKSet 0 keys (https://www.googleapis.com/oauth2/v3/certs)\n\njulia\u003e refresh!(keyset)\n\njulia\u003e keyset\nJWKSet 2 keys (https://www.googleapis.com/oauth2/v3/certs)\n\njulia\u003e for (k,v) in keyset.keys\n           println(\"    \", k, \" =\u003e \", v.key)\n       end\n    7978a91347261a291bd71dcab4a464be7d279666 =\u003e MbedTLS.RSA(Ptr{MbedTLS.mbedtls_rsa_context} @0x0000000001e337e0)\n    8aad66bdefc1b43d8db27e65e2e2ef301879d3e8 =\u003e MbedTLS.RSA(Ptr{MbedTLS.mbedtls_rsa_context} @0x0000000001d77390)\n```\n\nWhile symmetric keys for signing can simply be read from a jwk file into a `JWKSet`, creating a JWKSet for asymmetric key signing needs to be done by the calling code. The process may vary depending on where the private key is stored, but as an example below is a snippet of code that picks up private keys from file corresponding to each key in a jwk file.\n\n```julia\nkeyset = JWKSet(keyset_url)\nrefresh!(keyset)\nsigningkeyset = deepcopy(keyset)\nfor k in keys(signingkeyset.keys)\n    signingkeyset.keys[k] = JWKRSA(signingkeyset.keys[k].kind, MbedTLS.parse_keyfile(joinpath(dirname(keyset_url), \"$k.private.pem\")))\nend\n```\n\nThe `alg` method on a JWK returns the algorithm used for the key.\n\n```julia\njulia\u003e JWTs.alg(keyset.keys[\"7978a91347261a291bd71dcab4a464be7d279666\"])\n\"RS256\"\n```\n\n## Tokens\n\n**JWT** represents a JSON Web Token containing the payload at the minimum. When signed, it holds the header (with key id and algorithm used) and signature too. The parts are stored in encoded form.\n\n```julia\njulia\u003e using JSON\n\njulia\u003e using JWTs\n\njulia\u003e payload = JSON.parse(\"\"\"{\n           \"iss\": \"https://auth2.juliacomputing.io/dex\",\n           \"sub\": \"ChUxjfgsajfurjsjdut0483672kdhgstgy283jssZQ\",\n           \"aud\": \"example-audience\",\n           \"exp\": 1536080651,\n           \"iat\": 1535994251,\n           \"nonce\": \"1777777777777aaaaaaaaabbbbbbbbbb\",\n           \"at_hash\": \"222222-G-JJJJJJJJJJJJJ\",\n           \"email\": \"user@example.com\",\n           \"email_verified\": true,\n           \"name\": \"Example User\"\n       }\"\"\");\n\njulia\u003e jwt = JWT(; payload=payload)\neyJuYW1lIjoiRXhhbXBsZSBVc2VyIiwiZXhwIjoxNTM2MDgwNjUxLCJhdWQiOiJleGFtcGxlLWF1ZGllbmNlIiwic3ViIjoiQ2hVeGpmZ3NhamZ1cmpzamR1dDA0ODM2NzJrZGhnc3RneTI4M2pzc1pRIiwiaWF0IjoxNTM1OTk0MjUxLCJpc3MiOiJodHRwczovL2F1dGgyLmp1bGlhY29tcHV0aW5nLmlvL2RleCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhdF9oYXNoIjoiMjIyMjIyLUctSkpKSkpKSkpKSkpKSiIsIm5vbmNlIjoiMTc3Nzc3Nzc3Nzc3N2FhYWFhYWFhYWJiYmJiYmJiYmIiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20ifQ\n```\n\nA JWT can be signed using the `sign!` method, passing a key set and a key id to sign it with.\n\n```julia\njulia\u003e issigned(jwt)\nfalse\n\njulia\u003e keyset = JWKSet(\"file:///my/secret/location/jwkkey.json\");\n\njulia\u003e refresh!(keyset)\n\njulia\u003e keyid = first(first(keyset.keys)) # using the first key in the key set\n\"4Fytp3LfBhriD0eZ-k3aNS042bDiCZXg6bQNJmYoaE\"\n\njulia\u003e sign!(jwt, keyset, keyid)\n\njulia\u003e issigned(jwt)\ntrue\n\njulia\u003e jwt # note the additional header and signature\neyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjRGeXRwM0xmQmhyaUQwZVotazNhTlMwNDJiRGlDWlhnNmJRTkptWW9hRSJ9.eyJuYW1lIjoiRXhhbXBsZSBVc2VyIiwiZXhwIjoxNTM2MDgwNjUxLCJhdWQiOiJleGFtcGxlLWF1ZGllbmNlIiwic3ViIjoiQ2hVeGpmZ3NhamZ1cmpzamR1dDA0ODM2NzJrZGhnc3RneTI4M2pzc1pRIiwiaWF0IjoxNTM1OTk0MjUxLCJpc3MiOiJodHRwczovL2F1dGgyLmp1bGlhY29tcHV0aW5nLmlvL2RleCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhdF9oYXNoIjoiMjIyMjIyLUctSkpKSkpKSkpKSkpKSiIsIm5vbmNlIjoiMTc3Nzc3Nzc3Nzc3N2FhYWFhYWFhYWJiYmJiYmJiYmIiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20ifQ.zfq-DT4Ft_MSU34pwFrMaealWGs0j7Ynhs9iKjf5Uf4\n```\n\nThe `kid` method shows the key id used to sign a JWT. This is useful while validating a JWT.\n\n```julia\njulia\u003e kid(jwt)\n\"4Fytp3LfBhriD0eZ-k3aNS042bDiCZXg6bQNJmYoaE\"\n```\n\nThe `alg` method shows the algorithm used to sign a JWT.\n\n```julia\njulia\u003e alg(jwt)\n\"RS256\"\n```\n\n## Validation\n\nTo validate a JWT against a key, call the `validate!` method, passing a key set and the key id to use.\n\nThe `isvalid` method can be used to check if a JWT is valid (or has been validated at all). It returns `nothing` if validation has not been attempted and a `Bool` indicating validity if it has been validated earlier.\n\n```julia\njulia\u003e isvalid(jwt2)\n\njulia\u003e validate!(jwt, keyset, keyname)\ntrue\n\njulia\u003e isvalid(jwt)\ntrue\n```\n\nThe `with_valid_jwt` method can be used to Run `f` with a valid JWT. The validated JWT is passed as an argument to `f`. If the JWT is invalid, an `ArgumentError` is thrown.\n\n```julia\njulia\u003e with_valid_jwt(jwt2, keyset) do valid_jwt\n           @info(\"claims\", claims(valid_jwt))\n       end\n┌ Info: claims\n│   claims(valid_jwt) =\n│    Dict{String, Any} with 10 entries:\n│      \"name\"           =\u003e \"Example User\"\n│      \"exp\"            =\u003e 1536080651\n│      \"aud\"            =\u003e \"example-audience\"\n...\n└      \"email\"          =\u003e \"user@example.com\"\n```\n\nBoth `validate!` and `with_valid_jwt` methods can optionally take an `algorithms` argument, which is a list of algorithms to validate against. If the JWT's algorithm is not in the list, the validation will fail.\n\n```julia\njulia\u003e validate!(jwt, keyset, keyname; algorithms=[\"RS256\"])\ntrue\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaweb%2Fjwts.jl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuliaweb%2Fjwts.jl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaweb%2Fjwts.jl/lists"}