When the user needs to generate, validate, refresh, or debug JSON Web Tokens. Use when the user mentions "JWT," "access token," "refresh token," "token rotation," "token expiration," "token validation," "bearer token," or "decode JWT." Handles secure token lifecycle including signing, verification, refresh rotation, and revocation. For full auth system design, see auth-system-setup.
Implements secure JWT token lifecycle for web applications — generation, validation, refresh rotation, revocation, and debugging. Produces code that follows current security best practices including short-lived access tokens, one-time refresh rotation with family tracking, and proper key management.
When creating JWT tokens:
// Access token payload — keep it minimal
{
sub: "user_abc123",
roles: ["member"],
iat: 1708185600,
exp: 1708186500 // 15 minutes
}
Implement one-time rotation with reuse detection:
1. Extract token from Authorization header (Bearer scheme)
2. Verify signature using public key
3. Check expiration (exp claim)
4. Check issuer and audience if configured
5. Attach decoded payload to request context
6. Return 401 with specific error: expired, invalid, missing
Prompt: "Create a JWT token service with refresh rotation for my Express app"
Output:
// token.service.ts
import jwt from 'jsonwebtoken';
import crypto from 'crypto';
export class TokenService {
generateAccessToken(user: User): string {
return jwt.sign(
{ sub: user.id, roles: user.roles },
process.env.JWT_PRIVATE_KEY,
{ algorithm: 'RS256', expiresIn: '15m', issuer: 'app' }
);
}
async generateRefreshToken(userId: string, familyId?: string): Promise<string> {
const token = crypto.randomBytes(32).toString('hex');
const hash = crypto.createHash('sha256').update(token).digest('hex');
await db.refreshTokens.create({
tokenHash: hash,
userId,
familyId: familyId || crypto.randomUUID(),
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
});
return token;
}
async rotateRefreshToken(oldToken: string) {
const hash = crypto.createHash('sha256').update(oldToken).digest('hex');
const stored = await db.refreshTokens.findByHash(hash);
if (!stored || stored.revokedAt) {
// Reuse detected — revoke entire family
if (stored) await db.refreshTokens.revokeFamily(stored.familyId);
throw new TokenReuseError();
}
await db.refreshTokens.revoke(stored.id);
const newRefresh = await this.generateRefreshToken(stored.userId, stored.familyId);
const user = await db.users.findById(stored.userId);
const newAccess = this.generateAccessToken(user);
return { accessToken: newAccess, refreshToken: newRefresh };
}
}
Prompt: "This JWT isn't working, can you decode it? eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTcwODE4NTYwMH0.abc..."
Output:
Decoded JWT:
Header: { alg: "RS256" }
Payload: { sub: "user_123", exp: 1708185600 }
Issue found: Token expired at 2024-02-17T12:00:00Z (3 hours ago).
The token has no "iat" claim — consider adding it for audit logging.
No "iss" or "aud" claims — recommend adding these for multi-service setups.
npx skills add TerminalSkills/jwt-handler下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer