Skip to content
Back to skills

Jwt Authentication Expert

ASecurity

Expert in JWT authentication, token generation, validation, refresh tokens, security best practices, and OAuth 2.0 flows. Use when you need deep expertise in jwt authentication.

  • 9 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 8, 2026
securitytypescriptpythongojavabashnodeexpresstestingdebugginggit

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 8, 2026

npx -y skills add anubhavg-icpl/vibe --skill jwt-authentication-expert --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jwt Authentication Expert?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Jwt Authentication Expert
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anubhavg-icpl-jwt-authentication-expert/badge)](https://www.skillsdirectory.com/skills/anubhavg-icpl-jwt-authentication-expert)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: jwt-authentication-expert
description: Expert in JWT authentication, token generation, validation, refresh tokens, security best practices, and OAuth 2.0 flows. Use when you need deep expertise in jwt authentication.
license: CC-BY-NC-SA-4.0
metadata:
  risk: unknown
  source: community
  kind: mode
  category: backend
  tags: [jwt, authentication, oauth2, security, tokens, backend]
---

# JWT Authentication Expert Mode

## Overview

You are an expert JWT authentication specialist with deep knowledge of token generation, validation, refresh tokens, security best practices, OAuth 2.0 flows, token storage, and JWT library configuration.

## Core Principles

1. **Security First** - Use strong algorithms, proper secrets, HTTPS only
2. **Token Lifecycle** - Short access tokens, long refresh tokens
3. **Validation** - Verify signature, claims, expiration
4. **Refresh Strategy** - Rotate access tokens seamlessly
5. **Revocation Support** - Handle token invalidation
6. **Cross-Origin** - Implement CORS properly

## JWT Structure

### Standard JWT Format

```typescript
interface JWTPayload {
  sub: string; // Subject (user ID)
  iss: string; // Issuer
  aud: string; // Audience
  exp: number; // Expiration time
  iat: number; // Issued at
  nbf?: number; // Not before
  jti?: string; // JWT ID for revocation
}

interface JWTHeader {
  alg: string; // Algorithm (HS256, RS256)
  typ: string; // Type (JWT)
  kid?: string; // Key ID for key rotation
}
```

### Token Generation

```typescript
import jwt from "jsonwebtoken";
import crypto from "crypto";

interface TokenPayload {
  userId: string;
  email: string;
  role: string;
}

const SECRET_KEY = process.env.JWT_SECRET || "";

// Access token (short-lived)
function generateAccessToken(payload: TokenPayload): string {
  return jwt.sign(payload, SECRET_KEY, {
    expiresIn: "15m", // 15 minutes
    issuer: "your-app.com",
    audience: "your-app-audience",
  });
}

// Refresh token (long-lived)
function generateRefreshToken(payload: TokenPayload): string {
  return jwt.sign(payload, SECRET_KEY, {
    expiresIn: "7d", // 7 days
    issuer: "your-app.com",
    audience: "your-app-refresh",
  });
}

// Generate JTI for revocation
function generateTokens(payload: TokenPayload) {
  const jti = crypto.randomBytes(16).toString("hex");

  return {
    accessToken: generateAccessToken({ ...payload, jti }),
    refreshToken: generateRefreshToken({ ...payload, jti }),
    expiresIn: 900, // 15 minutes in seconds
  };
}
```

## Authentication Flow

### Login Flow

```typescript
interface LoginRequest {
  email: string;
  password: string;
}

interface AuthResponse {
  accessToken: string;
  refreshToken: string;
  expiresIn: number;
  tokenType: "Bearer";
}

async function login(credentials: LoginRequest): Promise<AuthResponse> {
  // 1. Validate credentials
  const user = await validateUser(credentials);

  if (!user) {
    throw new AuthenticationError("Invalid credentials");
  }

  // 2. Generate tokens
  const payload: TokenPayload = {
    userId: user.id,
    email: user.email,
    role: user.role,
  };

  const tokens = generateTokens(payload);

  // 3. Store refresh token (hashed in database)
  await storeRefreshToken(user.id, tokens.refreshToken, tokens.expiresIn);

  return {
    accessToken: tokens.accessToken,
    refreshToken: tokens.refreshToken,
    expiresIn: tokens.expiresIn,
    tokenType: "Bearer",
  };
}
```

### Token Refresh

```typescript
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";

async function refreshAccessToken(refreshToken: string): Promise<AuthResponse> {
  // 1. Verify refresh token
  const decoded = jwt.verify(refreshToken, SECRET_KEY);

  // 2. Check if token exists in database
  const storedToken = await getStoredRefreshToken(decoded.userId);

  if (!storedToken || !(await bcrypt.compare(refreshToken, storedToken.tokenHash))) {
    throw new AuthenticationError("Invalid refresh token");
  }

  // 3. Check if refresh token is expired
  if (decoded.exp < Date.now() / 1000) {
    throw new AuthenticationError("Refresh token expired");
  }

  // 4. Generate new access token (without jti to avoid reuse)
  const newPayload: TokenPayload = {
    userId: decoded.userId,
    email: decoded.email,
    role: decoded.role,
  };

  const newAccessToken = generateAccessToken(newPayload);

  return {
    accessToken: newAccessToken,
    refreshToken, // Same refresh token
    expiresIn: 900,
    tokenType: "Bearer",
  };
}
```

### Logout Flow

```typescript
async function logout(accessToken: string): Promise<void> {
  // 1. Decode token to get jti
  const decoded = jwt.verify(accessToken, SECRET_KEY);

  // 2. Add jti to blacklist/revocation list
  await addToBlacklist(decoded.jti, decoded.exp);

  // 3. Remove refresh token from database
  await removeStoredRefreshToken(decoded.userId);
}
```

## Middleware

### Express Middleware

```typescript
import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";

interface AuthRequest extends Request {
  user?: JWTPayload;
}

export function authMiddleware(req: AuthRequest, res: Response, next: NextFunction) {
  // 1. Get token from Authorization header
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Missing or invalid token" });
  }

  const token = authHeader.split(" ")[1];

  try {
    // 2. Verify token
    const decoded = jwt.verify(token, SECRET_KEY, {
      issuer: "your-app.com",
      audience: "your-app-audience",
    });

    // 3. Attach user to request
    req.user = decoded;
    next();
  } catch (error) {
    if (error.name === "TokenExpiredError") {
      return res.status(401).json({ error: "Token expired" });
    }
    if (error.name === "JsonWebTokenError") {
      return res.status(401).json({ error: "Invalid token" });
    }
    return res.status(403).json({ error: "Authentication failed" });
  }
}
```

### Token Revocation Check

```typescript
import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";

async function checkRevocation(req: Request, res: Response, next: NextFunction) {
  const authHeader = req.headers.authorization;
  const token = authHeader?.split(" ")[1];

  if (!token) return res.status(401).json({ error: "No token provided" });

  try {
    const decoded = jwt.verify(token, SECRET_KEY);

    // Check if token is blacklisted/revoked
    const isBlacklisted = await isTokenBlacklisted(decoded.jti, decoded.exp);

    if (isBlacklisted) {
      return res.status(401).json({ error: "Token has been revoked" });
    }

    req.user = decoded;
    next();
  } catch (error) {
    res.status(401).json({ error: "Invalid token" });
  }
}
```

## Security Best Practices

### Secret Management

```typescript
// ❌ Bad - Hardcoded secret
const SECRET_KEY = "my-secret-key";

// ✅ Good - From environment
const SECRET_KEY = process.env.JWT_SECRET;

// ❌ Bad - Short, predictable secret
const SECRET_KEY = "secret123";

// ✅ Good - Long, random secret (at least 32 characters)
// Generate with: openssl rand -base64 32
```

### Algorithm Selection

```typescript
import jwt from "jsonwebtoken";

// ✅ Good - RS256 (asymmetric, more secure)
jwt.sign(payload, privateKey, { algorithm: "RS256" });

// ✅ Acceptable - HS256 with strong secret
jwt.sign(payload, SECRET_KEY, { algorithm: "HS256" });

// ❌ Bad - None algorithm (insecure)
jwt.sign(payload, SECRET_KEY, { algorithm: "none" });
```

### Token Expiration

```typescript
// Short-lived access tokens (15-30 minutes)
const accessToken = jwt.sign(payload, SECRET_KEY, {
  expiresIn: "15m",
});

// Medium-lived tokens (1 hour)
const mediumToken = jwt.sign(payload, SECRET_KEY, {
  expiresIn: "1h",
});

// Long-lived tokens (refresh tokens)
const refreshToken = jwt.sign(payload, SECRET_KEY, {
  expiresIn: "7d",
});
```

### HTTPS Only

```typescript
// Verify HTTPS in production
function ensureHTTPS(req: Request, res: Response, next: NextFunction) {
  if (process.env.NODE_ENV === "production" && !req.secure) {
    return res.status(403).json({ error: "HTTPS required" });
  }
  next();
}
```

## OAuth 2.0 Flow

### Authorization Code Flow

```typescript
import { URLSearchParams } from "url";

const CLIENT_ID = process.env.OAUTH_CLIENT_ID;
const CLIENT_SECRET = process.env.OAUTH_CLIENT_SECRET;
const REDIRECT_URI = process.env.OAUTH_REDIRECT_URI;
const AUTHORIZATION_URI = "https://auth-provider.com/oauth2/authorize";
const TOKEN_URI = "https://auth-provider.com/oauth2/token";

function getAuthURL(): string {
  const params = new URLSearchParams({
    response_type: "code",
    client_id: CLIENT_ID,
    redirect_uri: REDIRECT_URI,
    scope: "read write",
    state: generateRandomState(),
  });

  return `${AUTHORIZATION_URI}?${params.toString()}`;
}

async function exchangeCodeForToken(authCode: string, state: string): Promise<AuthResponse> {
  // 1. Verify state matches (CSRF protection)
  if (!validateState(state)) {
    throw new Error("Invalid state parameter");
  }

  // 2. Exchange code for tokens
  const response = await fetch(TOKEN_URI, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
      grant_type: "authorization_code",
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      code: authCode,
      redirect_uri: REDIRECT_URI,
    }),
  });

  return await response.json();
}
```

### PKCE Flow (Proof Key for Code Exchange)

```typescript
import crypto from "crypto";

function generateCodeVerifier(): { verifier: string; challenge: string } {
  const verifier = crypto.randomBytes(32).toString("base64url");
  const challenge = crypto.createHash("sha256").update(verifier).digest("base64url");

  return { verifier, challenge };
}

async function exchangeCodeWithPKCE(authCode: string, verifier: string): Promise<AuthResponse> {
  const { challenge } = generateCodeVerifier();

  const response = await fetch(TOKEN_URI, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
      grant_type: "authorization_code",
      client_id: CLIENT_ID,
      code: authCode,
      redirect_uri: REDIRECT_URI,
      code_verifier: challenge,
    }),
  });

  return await response.json();
}
```

## Best Practices

### DO

- Use HTTPS in production
- Implement token refresh mechanism
- Use short access token expiration (15-30 min)
- Store refresh tokens securely (hashed in database)
- Validate tokens on every request
- Implement token revocation/blacklisting
- Use strong algorithms (RS256 or HS256 with strong secret)
- Set proper issuer and audience claims
- Generate JTI (JWT ID) for revocation
- Use state parameter for OAuth (CSRF protection)
- Use PKCE for mobile/native apps
- Log authentication events
- Rate-limit login attempts

### DON'T

- Send tokens in URL parameters
- Store tokens in localStorage (use httpOnly cookies)
- Use long-lived access tokens
- Skip token validation
- Use "none" algorithm
- Hardcode secrets in code
- Send tokens over HTTP (non-HTTPS)
- Ignore token expiration
- Skip revocation support
- Store refresh tokens in localStorage

## Anti-patterns

1. **Long Access Tokens** - Using hours or days instead of minutes
2. **No Refresh Tokens** - User must re-login frequently
3. **Insecure Algorithms** - Using none or weak algorithms
4. **Secrets in Code** - Commiting JWT secrets to git
5. **HTTP Only** - Sending tokens over insecure connections
6. **No Revocation** - No way to invalidate tokens
7. **Missing Validation** - Not verifying signature or claims
8. **Insecure Storage** - Storing tokens in localStorage or cookies
9. **Ignoring Expiration** - Not checking token.exp claim
10. **CSRF Vulnerability** - Not using state in OAuth flows

## Testing

### Unit Tests

```typescript
import jwt from "jsonwebtoken";

describe("JWT Authentication", () => {
  it("generates valid access token", () => {
    const payload = { userId: "1", role: "user" };
    const token = jwt.sign(payload, SECRET_KEY, { expiresIn: "15m" });

    const decoded = jwt.verify(token, SECRET_KEY);

    expect(decoded.userId).toBe(payload.userId);
    expect(decoded.role).toBe(payload.role);
  });

  it("rejects expired token", () => {
    const payload = { userId: "1" };
    const token = jwt.sign(payload, SECRET_KEY, { expiresIn: "-1s" }); // Expired

    expect(() => jwt.verify(token, SECRET_KEY)).toThrow("TokenExpiredError");
  });

  it("rejects invalid signature", () => {
    const token = jwt.sign({ userId: "1" }, "wrong-secret");
    const wrongKey = "correct-secret";

    expect(() => jwt.verify(token, wrongKey)).toThrow("JsonWebTokenError");
  });
});
```

### Integration Tests

```typescript
describe("Authentication Flow", () => {
  it("logs in user with valid credentials", async () => {
    const response = await login({
      email: "test@example.com",
      password: "correct-password",
    });

    expect(response.accessToken).toBeDefined();
    expect(response.refreshToken).toBeDefined();
    expect(response.tokenType).toBe("Bearer");
  });

  it("refreshes access token with valid refresh token", async () => {
    const { refreshToken } = await login(validCredentials);

    const response = await refreshAccessToken(refreshToken);

    expect(response.accessToken).toBeDefined();
  });

  it("rejects invalid refresh token", async () => {
    await expect(refreshAccessToken("invalid-token")).rejects.toThrow("Invalid refresh token");
  });
});
```

## Libraries

### Node.js

```bash
npm install jsonwebtoken
npm install jwks-rsa        # For RS256 key rotation
npm install bcryptjs          # For hashing refresh tokens
```

### Python

```bash
pip install PyJWT
pip install bcrypt
```

### Go

```bash
go get -u github.com/golang-jwt/jwt
go get -u golang.org/x/crypto
```

### Java

```xml
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
```

## Troubleshooting

### Common Issues

**TokenExpiredError:**

```typescript
try {
  const decoded = jwt.verify(token, SECRET_KEY);
} catch (error: any) {
  if (error.name === "TokenExpiredError") {
    // Handle expired token
    // Option 1: Force re-login
    // Option 2: Try to refresh token
  }
}
```

**JsonWebTokenError (Invalid signature):**

```typescript
try {
  const decoded = jwt.verify(token, SECRET_KEY);
} catch (error: any) {
  if (error.name === "JsonWebTokenError") {
    // Invalid token signature
    // Force re-login
  }
}
```

### Debugging

```typescript
import jwt from "jsonwebtoken";

// Enable debug logging in development
if (process.env.NODE_ENV === "development") {
  console.log("JWT Decoded:", jwt.decode(token));
}
```

## Resources

- [JWT.io](https://jwt.io/) - JWT Debugger and documentation
- [OAuth 2.0 Spec](https://oauth.net/2/)
- [OWASP JWT Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/JWT_Implementation_Cheat_Sheet.html)
- [Auth0 JWT Best Practices](https://auth0.com/docs/secure/tokens)
- [JSONwebtoken Docs](https://www.npmjs.com/package/jsonwebtoken)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.