Skip to content

jwt

stable

Create and verify HMAC-signed JSON Web Tokens (HS256, HS384, HS512) and inspect their claims.

use plugin jwt::{encode, verify, decode_parts, …}
7 functions Cryptography
/ filter jk navigate Esc clear
Functions (7)
  1. encode Sign a payload and return a JWT string
  2. verify Verify a token's HMAC signature
  3. decode_parts Decode header, payload, and signature strings
  4. decode_header Decode the header and return alg and typ
  5. decode_payload Decode and return the raw payload JSON
  6. get_claim Read a single claim value from a token
  7. is_expired Check if the token's exp claim has passed

Overview

jwt creates and verifies HMAC-signed JSON Web Tokens entirely in-process, with no external service or key infrastructure. A token is a compact string of three base64url sections — header.payload.signature — and every function here is stateless: you pass the token (and, when signing or verifying, a shared secret string) and get back a plain value. Payloads are handled as raw JSON strings rather than tables, so you keep full control over claim ordering and formatting.

Three symmetric algorithms are supported: HS256 (the default), HS384, and HS512. Reach for jwt when you need lightweight, self-contained auth tokens for sessions, API keys, or signed links, and you control both the signing and verifying side with the same secret. The typical flow is: build a JSON payload, encode it, hand the token to the client, then later verify the signature and read claims with get_claim / decode_payload / is_expired.

Common patterns

Issue a token, then verify it and read a claim back out:

use plugin jwt::{encode, verify, get_claim}

let secret = "my-secret-key"
let token = encode('{"sub": "user_42", "role": "admin"}', secret)

if verify(token, secret) {
  print("signed in as {get_claim(token, "sub")}")
  print("role: {get_claim(token, "role")}")
}

Verify a token and reject it if it has expired:

use plugin jwt::{encode, verify, is_expired}

let secret = "session-secret"
let token = encode('{"sub": "alice", "exp": 1700000000}', secret)

let now = 1700500000
if verify(token, secret) and !is_expired(token, now) {
  print("token accepted")
} else {
  print("token rejected")
}

Inspect a token's metadata without trusting it, then verify before use:

use plugin jwt::{encode, decode_header, decode_payload, verify}

let token = encode('{"sub": "bob"}', "secret", "HS384")
let hdr = decode_header(token)
print("algorithm: {hdr["alg"]}")
print("unverified payload: {decode_payload(token)}")
print("trusted: {verify(token, "secret")}")

Sign a payload and return a JWT string

Signs a JSON payload string with the given secret and returns a compact JWT (header.payload.signature). Supported algorithms: "HS256" (default), "HS384", "HS512".

use plugin jwt::{encode}

let payload = '{"sub": "user_42", "role": "admin", "exp": 9999999999}'
let token = encode(payload, "my-secret-key")
print(token)
use plugin jwt::{encode}

let payload = '{"sub": "user_1"}'
let token = encode(payload, "secret", "HS512")
print(token)

Verify a token's HMAC signature

Verifies the HMAC signature of a JWT against the given secret. Returns true if valid. The algorithm is auto-detected from the token header unless overridden.

use plugin jwt::{encode, verify}

let token = encode('{"sub": "alice"}', "secret")
let ok = verify(token, "secret")
print(ok)

let bad = verify(token, "wrong-secret")
print(bad)

Pin the algorithm explicitly instead of trusting the header's alg field — a hardening step that prevents a forged header from selecting a weaker algorithm:

use plugin jwt::{encode, verify}

let token = encode('{"sub": "carol"}', "secret", "HS512")
print(verify(token, "secret", "HS512"))
print(verify(token, "secret", "HS256"))

Decode header, payload, and signature strings

Splits the token and base64url-decodes each section. Returns {header, payload, signature} as JSON strings (header and payload) and the raw base64url signature.

use plugin jwt::{encode, decode_parts}

let token = encode('{"sub": "alice", "role": "admin"}', "secret")
let parts = decode_parts(token)
print(parts["header"])
print(parts["payload"])

Decode the header and return alg and typ

Decodes the JWT header and returns {alg, typ} as a table.

use plugin jwt::{encode, decode_header}

let token = encode('{"sub": "bob"}', "secret", "HS384")
let hdr = decode_header(token)
print(hdr["alg"])
print(hdr["typ"])

Decode and return the raw payload JSON

Returns the raw payload JSON string without verifying the signature. Useful for inspection when the signature has already been verified separately.

use plugin jwt::{encode, decode_payload}

let token = encode('{"sub": "alice", "role": "editor"}', "secret")
let payload_json = decode_payload(token)
print(payload_json)

Read a single claim value from a token

Reads a single claim from the payload by name and returns its value as a string. Returns nil if the claim is absent.

use plugin jwt::{encode, get_claim}

let token = encode('{"sub": "user_7", "role": "admin", "exp": 9999999999}', "secret")
print(get_claim(token, "sub"))
print(get_claim(token, "role"))
print(get_claim(token, "exp"))

Numbers and booleans are returned as their string form, and a missing claim yields nil — handy for branching on optional claims:

use plugin jwt::{encode, get_claim}

let token = encode('{"sub": "dana", "active": true}', "secret")
print(get_claim(token, "active"))
print(get_claim(token, "missing"))

Check if the token's exp claim has passed

Checks whether the token's exp claim is less than or equal to now_unix (a Unix timestamp number). Returns false if the token has no exp claim (treated as never-expiring).

use plugin jwt::{encode, is_expired}

let past_token   = encode('{"sub": "alice", "exp": 1000000}', "secret")
let future_token = encode('{"sub": "bob",   "exp": 9999999999}', "secret")

let now = 1700000000
print(is_expired(past_token, now))
print(is_expired(future_token, now))
enespt-br