worker_jwt
JWT generation for wasm runtimes (Cloudflare Workers, Deno, browsers, Node.js 20+) backed by the Web Crypto API.
worker_jwt is a thin layer over crate: wasm_web_crypto that turns a PEM private key (or a shared secret for HMAC) plus a set of claims into a signed JWT string. All cryptography is delegated to the host runtime's Web Crypto implementation — no pure-Rust crypto is bundled.
Supported algorithms
| Algorithm | JWT name | Typical use |
|---|---|---|
| RSASSA-PKCS1-v1_5 + SHA-256 | RS256 |
GitHub App, Google Cloud |
| ECDSA P-256 + SHA-256 | ES256 |
Apple (Sign in with Apple, APNs) |
| HMAC + SHA-256 | HS256 |
Custom auth, Supabase |
Quick start
Core API
use ;
let signer = new.await?;
let claims = builder
.issuer
.subject
.expires_at
.extra
.build;
let jwt: String = signer.sign.await?;
Key format expected by JwtSigner::new:
Rs256/Es256— PKCS#8 PEM (-----BEGIN PRIVATE KEY-----). Convert legacy PKCS#1 / SEC1 PEMs with:openssl pkcs8 -topk8 -nocrypt -in in.pem -out out.pemHs256— raw shared-secret bytes.
Importing the key is the expensive step; one JwtSigner can sign any number of times.
GitHub App (feature = github)
use GitHubAppJwt;
let jwt = new.generate.await?;
// POST /app/installations/:id/access_tokens with `Authorization: Bearer {jwt}`
Claims are filled automatically: alg=RS256, iss=app_id, iat=now − 60s, exp=now + 600s (GitHub caps lifetime at 10 minutes).
Google service account (feature = google)
use GoogleServiceAccountJwt;
let jwt = new
.scope
.generate
.await?;
// POST https://oauth2.googleapis.com/token to exchange for an access_token
Claims are filled automatically: alg=RS256, iss=<email>, aud=https://oauth2.googleapis.com/token, iat=now, exp=now + 3600s. The private_key field in the service account JSON is already PKCS#8 PEM — pass it through unchanged.
Apple (Sign in with Apple, APNs)
No preset is provided — use the core API with ES256:
use ;
let signer = new.await?;
let claims = builder
.issuer
.subject
.audience
.issued_at
.expires_at
.build;
let jwt = signer.sign.await?;
Scope
This crate intentionally stays small:
- Only signing. Verification belongs on the API server, not on the Worker that calls outbound APIs.
- No HTTP. Exchanging the JWT for an installation/access token is the caller's job.
- No JWK / JWKS. Bring your own PEM.