std/jwt

JSON Web Tokens (RFC 7519), signed as JWS in the compact form (RFC 7515), and read back only when their signature, their algorithm, and their claims hold.

import "std/jwt"

JwtKey key = hmac_key(secret)
str token = jwt_encode(claims, "HS256", key)?

JwtOptions options = JwtOptions(["ES256", "RS256"])
options.issuer = "https://auth.example.com"
options.audience = "api"
Json verified = jwt_decode(token, jwks_keys(published), options)?

The algorithms are HS256, HS384, and HS512 (HMAC); RS256, RS384, and RS512 (RSA PKCS#1 v1.5); PS256, PS384, and PS512 (RSA-PSS); ES256 and ES384 (ECDSA on P-256 and P-384); and EdDSA (Ed25519). The public-key ones are std/publickey's, so std/jwt links with libcrypto as it does.

Function Result
hmac_key(secret, id), signing_key(private_key, id), verifying_key(public_key, id) a JwtKey; id is its "kid"
jwks_keys(jwks) the keys of a JWK Set, as an issuer publishes it, with their "kid"; keys of other kinds are passed over
jwt_encode(claims, algorithm, key, header) a token, with "alg", "typ", the key's "kid", and what header adds
jwt_decode(token, keys, options) its claims, when one of keys verifies it with one of the options' algorithms and its claims hold
jwt_parts(token) its header and claims unchecked, to find its "kid", never to trust

JwtOptions(algorithms) takes only those algorithms, and a key only for its own kind, so a token cannot choose "none" nor HMAC with a public key as its secret. issuer and audience, when given, must be the token's "iss" and among its "aud"; leeway (60) is how many seconds clocks may disagree by for "exp", "nbf", and "iat"; require_expiry (true) refuses a token without "exp"; now (0, for now) is the time checked against. The errors are of kind "invalid_token", "invalid_signature", "expired", and "invalid_claims".