Prerequisites
- Target system, dependencies and environment configured.
Usage
Purpose
JWTs and similar tokens carry identity and claims that servers trust, so the cryptography that protects them — the signature — is what stands between a valid session and a forged one. The JWT footguns are well-known and keep recurring: alg:none, algorithm confusion, weak HMAC secrets. This skill covers the cryptographic side of tokens (signing algorithm and key management) so tokens can't be forged; the API jwt-attacks skill covers testing them from the attacker's side, and this is the build-it-right counterpart.
When to use it
Designing or reviewing how an application signs and verifies tokens. It focuses on the crypto choices — the surrounding validation logic (claims, expiry, audience) lives in the API jwt-attacks and IAM oidc-validation skills, which this complements.
Procedure
- Choose the signing scheme deliberately, and pin it.
- Asymmetric (RS256, ES256, EdDSA) — the issuer signs with a private key; verifiers hold only the public key. Preferred when tokens are verified by parties other than the issuer (multiple services, third parties), because verifiers can't mint tokens.
- Symmetric (HS256) — signed and verified with a shared secret. Fine for a single service that both issues and verifies, but every verifier that holds the secret can also forge, and the secret must be strong.
Pin the accepted algorithm server-side; accept exactly the one you issue.
- Kill the algorithm footguns:
- Reject
alg:none — never accept an unsigned token.
- Prevent algorithm confusion — a verifier that accepts both RS256 and HS256 can be tricked into verifying an HS256 token using the RS256 public key as the HMAC secret. Pin one algorithm; don't let the token's header choose.
- Use strong keys. For HMAC, a long high-entropy secret (not a word, not the app name) — weak HMAC secrets are crackable offline (the jwt-attacks skill shows this). For asymmetric, adequate key sizes (RSA-2048+, or ES256/EdDSA) and proper private-key protection (key-management skill).
- Manage the signing keys like any high-value key — store the private/signing key in a KMS/HSM or secret manager, never hardcoded, and enable rotation. A leaked signing key means an attacker can mint valid tokens for anyone.
- Support key rotation with a key ID (
kid) — include a key identifier so verifiers can select the right key and you can rotate signing keys without downtime (and publish public keys via a JWKS endpoint for asymmetric schemes).
- Consider whether the token needs encryption too — JWTs are signed (integrity/authenticity) but not encrypted by default; anyone can read the claims. If claims are sensitive, don't put them in a plain JWT, or use JWE — but usually the answer is to keep sensitive data out of the token.
Cheatsheet
choose + PIN the algorithm
asymmetric (RS256/ES256/EdDSA) verifiers hold only public key -> can't forge
-> use when others verify your tokens
symmetric (HS256) shared secret; every holder can forge; single-service
server pins ONE accepted alg (don't let the token header choose)
footguns (recurring)
alg:none -> reject unsigned tokens, always
alg confusion -> accepting RS256+HS256 lets attacker sign HS256 with the
RS256 PUBLIC key -> pin one algorithm
weak HMAC secret -> long high-entropy secret (crackable offline otherwise)
keys
store signing/private key in KMS/HSM/secret manager (NEVER hardcoded)
rotate ; use `kid` for key selection ; JWKS endpoint for public keys
leaked signing key = attacker mints valid tokens for anyone
remember: JWT is SIGNED, not ENCRYPTED -> claims are readable. Keep secrets OUT.
Reading the design
alg:none accepted = total forgery; any token is valid. Critical — reject unsigned tokens.
- Multiple algorithms accepted (RS256 + HS256) = algorithm-confusion forgery using the public key as HMAC secret. Pin one algorithm.
- A weak/guessable HMAC secret = offline-crackable, then the attacker mints tokens at will. Use a long high-entropy secret, or asymmetric signing.
- The signing key hardcoded or poorly stored = a leaked signing key is catastrophic (mint any token). Store it in a KMS/HSM and rotate.
- Sensitive data in a plain JWT = readable by anyone holding the token (it's signed, not encrypted). Keep secrets out or use JWE.
- Pinned algorithm, strong/asymmetric keys in a KMS,
kid+JWKS rotation, no secrets in claims = cryptographically sound tokens.
The fix / best practice
- Pin the signing algorithm and reject
alg:none and any algorithm you don't issue — this kills the two classic forgery paths.
- Prefer asymmetric signing (RS256/ES256/EdDSA) when tokens are verified beyond the issuer, so verifiers can't forge; use HS256 only for single-service cases with a strong secret.
- Use strong keys and protect the signing key in a KMS/HSM/secret manager, never hardcoded.
- Rotate signing keys with
kid/JWKS so rotation is seamless and a leaked key can be retired.
- Keep sensitive data out of tokens — JWTs are readable; don't rely on them for confidentiality.
- Pair with proper claim validation (API jwt-attacks / IAM oidc-validation skills).
Pitfalls
- Accepting
alg:none or multiple algorithms. The recurring JWT forgery bugs; pin one algorithm and reject unsigned.
- Weak HMAC secrets. Offline-crackable, then tokens are forgeable. Long high-entropy secret, or go asymmetric.
- Poorly stored / never-rotated signing keys. A leaked signing key mints tokens for anyone; protect it like the crown-jewel key it is and support rotation.
- Assuming JWTs are encrypted. They're signed, not encrypted — claims are readable by anyone with the token. Keep secrets out.
- Only fixing the crypto, not the claims. A perfectly-signed token that isn't validated for expiry/audience is still exploitable (see the API/IAM skills).
References
- RFC 8725 (JWT Best Current Practices), RFC 7519 (JWT), RFC 7517 (JWK)
- OWASP JSON Web Token Cheat Sheet
- The API jwt-attacks, IAM oidc-validation, and key-management skills
- CWE-347 (improper signature verification), CWE-321 (hardcoded key)
Inputs
- Relevant source code, logs, network traces, or system specifications.
Outputs
- Analysis findings, security audit report, or generated code artifacts.
1---2name: jwt-and-token-crypto3description: Use when signing and verifying JWTs or similar tokens — choosing the algorithm, managing signing keys, and avoiding the cryptographic footguns that let tokens be forged.4---5678## Prerequisites9- Target system, dependencies and environment configured.1011## Usage12### Purpose1314JWTs and similar tokens carry identity and claims that servers trust, so the cryptography that protects them — the signature — is what stands between a valid session and a forged one. The JWT footguns are well-known and keep recurring: `alg:none`, algorithm confusion, weak HMAC secrets. This skill covers the cryptographic side of tokens (signing algorithm and key management) so tokens can't be forged; the API `jwt-attacks` skill covers testing them from the attacker's side, and this is the build-it-right counterpart.1516### When to use it1718Designing or reviewing how an application signs and verifies tokens. It focuses on the crypto choices — the surrounding validation logic (claims, expiry, audience) lives in the API jwt-attacks and IAM oidc-validation skills, which this complements.1920### Procedure21221. **Choose the signing scheme deliberately, and pin it.**23 - **Asymmetric (RS256, ES256, EdDSA)** — the issuer signs with a private key; verifiers hold only the public key. Preferred when tokens are verified by parties other than the issuer (multiple services, third parties), because verifiers can't mint tokens.24 - **Symmetric (HS256)** — signed and verified with a shared secret. Fine for a single service that both issues and verifies, but every verifier that holds the secret can also forge, and the secret must be strong.25 Pin the accepted algorithm server-side; accept exactly the one you issue.262. **Kill the algorithm footguns:**27 - **Reject `alg:none`** — never accept an unsigned token.28 - **Prevent algorithm confusion** — a verifier that accepts both RS256 and HS256 can be tricked into verifying an HS256 token using the RS256 *public* key as the HMAC secret. Pin one algorithm; don't let the token's header choose.293. **Use strong keys.** For HMAC, a long high-entropy secret (not a word, not the app name) — weak HMAC secrets are crackable offline (the jwt-attacks skill shows this). For asymmetric, adequate key sizes (RSA-2048+, or ES256/EdDSA) and proper private-key protection (key-management skill).304. **Manage the signing keys** like any high-value key — store the private/signing key in a KMS/HSM or secret manager, never hardcoded, and enable rotation. A leaked signing key means an attacker can mint valid tokens for anyone.315. **Support key rotation with a key ID (`kid`)** — include a key identifier so verifiers can select the right key and you can rotate signing keys without downtime (and publish public keys via a JWKS endpoint for asymmetric schemes).326. **Consider whether the token needs encryption too** — JWTs are signed (integrity/authenticity) but not encrypted by default; anyone can read the claims. If claims are sensitive, don't put them in a plain JWT, or use JWE — but usually the answer is to keep sensitive data out of the token.3334### Cheatsheet3536```37choose + PIN the algorithm38 asymmetric (RS256/ES256/EdDSA) verifiers hold only public key -> can't forge39 -> use when others verify your tokens40 symmetric (HS256) shared secret; every holder can forge; single-service41 server pins ONE accepted alg (don't let the token header choose)4243footguns (recurring)44 alg:none -> reject unsigned tokens, always45 alg confusion -> accepting RS256+HS256 lets attacker sign HS256 with the46 RS256 PUBLIC key -> pin one algorithm47 weak HMAC secret -> long high-entropy secret (crackable offline otherwise)4849keys50 store signing/private key in KMS/HSM/secret manager (NEVER hardcoded)51 rotate ; use `kid` for key selection ; JWKS endpoint for public keys52 leaked signing key = attacker mints valid tokens for anyone5354remember: JWT is SIGNED, not ENCRYPTED -> claims are readable. Keep secrets OUT.55```5657### Reading the design5859- **`alg:none` accepted** = total forgery; any token is valid. Critical — reject unsigned tokens.60- **Multiple algorithms accepted (RS256 + HS256)** = algorithm-confusion forgery using the public key as HMAC secret. Pin one algorithm.61- **A weak/guessable HMAC secret** = offline-crackable, then the attacker mints tokens at will. Use a long high-entropy secret, or asymmetric signing.62- **The signing key hardcoded or poorly stored** = a leaked signing key is catastrophic (mint any token). Store it in a KMS/HSM and rotate.63- **Sensitive data in a plain JWT** = readable by anyone holding the token (it's signed, not encrypted). Keep secrets out or use JWE.64- **Pinned algorithm, strong/asymmetric keys in a KMS, `kid`+JWKS rotation, no secrets in claims** = cryptographically sound tokens.6566### The fix / best practice6768- **Pin the signing algorithm** and reject `alg:none` and any algorithm you don't issue — this kills the two classic forgery paths.69- **Prefer asymmetric signing** (RS256/ES256/EdDSA) when tokens are verified beyond the issuer, so verifiers can't forge; use HS256 only for single-service cases with a strong secret.70- **Use strong keys** and protect the signing key in a KMS/HSM/secret manager, never hardcoded.71- **Rotate signing keys** with `kid`/JWKS so rotation is seamless and a leaked key can be retired.72- **Keep sensitive data out of tokens** — JWTs are readable; don't rely on them for confidentiality.73- Pair with proper claim validation (API jwt-attacks / IAM oidc-validation skills).7475### Pitfalls7677- **Accepting `alg:none` or multiple algorithms.** The recurring JWT forgery bugs; pin one algorithm and reject unsigned.78- **Weak HMAC secrets.** Offline-crackable, then tokens are forgeable. Long high-entropy secret, or go asymmetric.79- **Poorly stored / never-rotated signing keys.** A leaked signing key mints tokens for anyone; protect it like the crown-jewel key it is and support rotation.80- **Assuming JWTs are encrypted.** They're signed, not encrypted — claims are readable by anyone with the token. Keep secrets out.81- **Only fixing the crypto, not the claims.** A perfectly-signed token that isn't validated for expiry/audience is still exploitable (see the API/IAM skills).8283### References8485- RFC 8725 (JWT Best Current Practices), RFC 7519 (JWT), RFC 7517 (JWK)86- OWASP JSON Web Token Cheat Sheet87- The API jwt-attacks, IAM oidc-validation, and key-management skills88- CWE-347 (improper signature verification), CWE-321 (hardcoded key)8990## Inputs91- Relevant source code, logs, network traces, or system specifications.9293## Outputs94- Analysis findings, security audit report, or generated code artifacts.