jwt — JSON Web Tokens

A small implementation of the JSON Web Token (JWT) standard for MicroPython. JWT is a compact, URL-safe container for a JSON payload that the issuer signs so the verifier can detect tampering and expiry.

This MicroPython port is intentionally tiny:

  • Only HS256 (HMAC with SHA-256) is supported. RSA / ECDSA / EdDSA algorithms are not implemented; the issuer and verifier must share a symmetric secret key.

  • The optional exp (expiration) claim is honored. Other registered claims (nbf, iat, iss, aud, sub, jti) are passed through unchanged in the payload but not validated; the application checks them if it cares.

  • No key-rotation, JWKS, or audience-list handling.

Functions

jwt.encode(payload: dict, key: bytes | str, algorithm: str = 'HS256') str

Encode payload into a signed JWT and return the resulting compact serialization (a str of the form "header.payload.signature", each segment Base64-URL-encoded).

payload

A JSON-serializable dict of claims. Standard claims (exp, iat, sub, …) are passed through verbatim; custom application keys are allowed.

key

The shared HMAC secret. bytes is preferred; str is UTF-8-encoded automatically.

algorithm

Must be "HS256" (the default). Anything else raises exceptions.InvalidAlgorithmError.

jwt.decode(token: str, key: bytes | str, algorithms: list = ['HS256']) dict

Verify token’s signature and (if present) its exp claim, and return the decoded payload dict. Raises a subclass of exceptions.PyJWTError on any failure – the caller usually catches the base class.

token

The compact JWT string produced by encode() (or any compatible issuer).

key

The shared HMAC secret. Must match the key used at encode time.

algorithms

The list of algorithms the caller is willing to accept. HS256 must be present, and the token’s header alg must be in the list. Defaults to ["HS256"].

Raises:

Exceptions

All exceptions are nested under the module attribute jwt.exceptions.

exception exceptions.PyJWTError

Base class for every JWT failure. Catch this if you do not need to distinguish among the cases below.

exception exceptions.InvalidTokenError

The token is structurally invalid – wrong number of segments, a segment that fails Base64 decode, or JSON that fails to parse. Subclass of exceptions.PyJWTError.

exception exceptions.InvalidAlgorithmError

The token’s algorithm is not in the caller-accepted list, or the caller asked for an algorithm other than HS256. Subclass of exceptions.PyJWTError.

exception exceptions.InvalidSignatureError

The token’s signature does not match the HMAC computed from the header and payload using the supplied key. Subclass of exceptions.PyJWTError.

exception exceptions.ExpiredSignatureError

The token’s exp claim is in the past. Subclass of exceptions.PyJWTError. The camera’s wall-clock time must be set (via ntptime.settime()) for this check to be meaningful.

Example

A symmetric-secret issue/verify cycle:

import jwt
import time

SECRET = b"keep-this-out-of-source-control"

payload = {
    "sub": "kitchen-cam",
    "role": "admin",
    "exp": time.time() + 3600,                 # 1 hour from now
}

token = jwt.encode(payload, SECRET)
print("token:", token)

try:
    claims = jwt.decode(token, SECRET)
except jwt.exceptions.PyJWTError as e:
    print("rejected:", type(e).__name__)
else:
    print("subject:", claims["sub"])

The same secret is used to sign and verify, so the verifier must hold the key the issuer used. For services where the camera is the issuer (handing out tokens to a paired phone), keep the secret on the camera filesystem and treat it like any other long-lived credential – see Operations: keys, expiry, and troubleshooting.

Note

This module relies on hmac and hashlib, both of which are built into the camera. No external configuration is needed. Keys may be any length, but the HMAC construction is most useful with keys at least as long as the SHA-256 block size (32 bytes).