Free · Private · Client-side

Generate Production-Ready JWT Secrets in One Click

Create cryptographically secure JWT signing secrets instantly. Get 256-bit, 384-bit, or 512-bit secrets ready for immediate use in your authentication system.

Generated values never leave this device.

HMAC · HMAC with SHA-256 (most common)

Estimated entropy: 256 bits · 32 random bytes · base64 encoded~132,943,112,026,157,700,000,000,000,000 quintillion times the age of the universe to crack
Weak · <50 bitsFairGood · 70+Strong · 100+

In plain terms: a gaming PC guessing a million passwords per second would need 132,943,112,026,157,700,000,000,000,000,000,000 quintillion times the age of the universe. Even someone renting every cloud server on Earth — a trillion guesses per second — would need 132,943,112,026,157,700,000,000,000,000 quintillion times the age of the universe. Nobody is guessing this password; the only realistic risks are it being reused or phished.

Generated secrets

Strong256 bits
Strong256 bits
Strong256 bits
Strong256 bits

Interactive JWT Decoder & Encoder

Decode existing JWTs to inspect their structure, or build new ones with custom claims.

JWT Decoder

JWT Builder

JWT Expiration Calculator

Calculate precise expiration times for your JWT tokens with various time formats and validation.

Expiration Settings

Quick Presets

Expiration Preview

Unix Timestamp (exp claim)
1787249486
Human Readable
8/20/2026, 6:11:26 PM
ISO 8601
2026-08-20T18:11:26.902Z
Time Until Expiry
1d 0h 0m
json
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1787163086,
  "exp": 1787249486
}

Expiration Best Practices

  • Short-lived tokens: Use 15-30 minutes for sensitive operations
  • Session tokens: 1-24 hours for user sessions
  • API tokens: Consider 1-7 days for automated systems
  • Refresh strategy: Implement token refresh for better UX
  • Clock skew: Account for time differences between servers

JWT Debugger & Validator

Debug JWT tokens, validate structure, and analyze potential security issues.

JWT Algorithm Comparison

AlgorithmTypeKey LengthSecurityPerformanceUse Cases
HS256HMAC-SHA256256 bits (32 bytes)GoodFastestMost common, good for web apps
HS384HMAC-SHA384384 bits (48 bytes)BetterMediumHigher security requirements
HS512HMAC-SHA512512 bits (64 bytes)BestSlowerMaximum security, critical systems
RS256RSA-SHA2562048+ bitsHighSlowPublic key verification
ES256ECDSA-SHA256256 bitsHighFastModern alternative to RSA

Current selection

HS256 offers hmac with sha-256 (most common) with 256 bits of security. Perfect for most web applications.

JWT Claims Builder

Build standard JWT claims with validation and examples.

Standard Claims

Custom Claims

Generated Claims Preview

{
  "iss": "your-app.com",
  "sub": "user-123",
  "aud": "api.example.com",
  "iat": 1787163086,
  "exp": 1787249486,
  "scope": "read:profile write:posts",
  "role": "user",
  "email": "[email protected]"
}

Usage Examples

.env
JWT_SECRET=your-secret-here
Node.js (jsonwebtoken)
const jwt = require('jsonwebtoken');

const token = jwt.sign(
  { userId: '123', role: 'admin' },
  process.env.JWT_SECRET,
  { algorithm: 'HS256', expiresIn: '24h' }
);

JWT Secret Security Best Practices

Secure Secret Storage

  • Environment Variables: Store secrets in environment variables, never in source code
  • Secret Management: Use dedicated services like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault
  • File Permissions: If storing in files, use strict permissions (600 or 640)
  • Version Control: Never commit secrets to Git repositories
  • Container Security: Use Docker secrets or Kubernetes secrets in containerized environments

Secret Rotation Strategy

✓ Do

  • Rotate secrets regularly (every 90 days minimum)
  • Support multiple active secrets during rotation
  • Use automated rotation tools when possible
  • Log secret usage for audit trails
  • Test rotation procedures regularly

✗ Don't

  • Wait for security incidents to rotate
  • Use the same secret across environments
  • Forget to update all services simultaneously
  • Leave old secrets active indefinitely
  • Skip testing after rotation

Choosing the Right Algorithm

AlgorithmSecurity LevelPerformanceRecommendation
HS256GoodFastDefault choice for most applications
HS384BetterMediumUse for higher security requirements
HS512BestSlowerMaximum security, slight performance cost

Production Deployment Checklist

  • Generate unique secrets for each environment (dev, staging, prod)
  • Implement proper secret storage (environment variables or secret manager)
  • Set up monitoring for failed JWT validation attempts
  • Configure appropriate token expiration times
  • Test secret rotation procedure
  • Audit code for hardcoded secrets

Complete Implementation Examples

Express.js Middleware with Security

middleware/auth.js
const jwt = require('jsonwebtoken');
const rateLimit = require('express-rate-limit');

// Rate limiting for token endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5,
  message: 'Too many authentication attempts'
});

class JWTService {
  constructor() {
    this.secret = process.env.JWT_SECRET;
    this.algorithm = 'HS256';

    if (!this.secret) {
      throw new Error('JWT_SECRET environment variable is required');
    }
  }

  generateToken(payload) {
    return jwt.sign({
      ...payload,
      iat: Math.floor(Date.now() / 1000),
      jti: require('crypto').randomBytes(16).toString('hex')
    }, this.secret, {
      algorithm: this.algorithm,
      expiresIn: '24h',
      issuer: 'your-app',
      audience: 'your-users'
    });
  }

  verifyToken(token) {
    try {
      return jwt.verify(token, this.secret, {
        algorithms: [this.algorithm],
        issuer: 'your-app',
        audience: 'your-users'
      });
    } catch (error) {
      throw new Error('Invalid token: ' + error.message);
    }
  }
}

// Authentication middleware
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  try {
    const jwtService = new JWTService();
    req.user = jwtService.verifyToken(token);
    next();
  } catch (error) {
    return res.status(403).json({ error: 'Invalid token' });
  }
};

module.exports = { authenticateToken, authLimiter };

Python Flask with Error Handling

jwt_auth.py
import jwt
import os
from datetime import datetime, timedelta, timezone
from functools import wraps
from flask import request, jsonify

class JWTAuth:
    def __init__(self):
        self.secret = os.getenv('JWT_SECRET')
        self.algorithm = 'HS256'

        if not self.secret:
            raise ValueError('JWT_SECRET environment variable required')

    def generate_token(self, user_data):
        payload = {
            'user_id': user_data['id'],
            'email': user_data['email'],
            'role': user_data.get('role', 'user'),
            'exp': datetime.now(timezone.utc) + timedelta(hours=24),
            'iat': datetime.now(timezone.utc),
            'iss': 'your-app',
            'aud': 'your-users'
        }
        return jwt.encode(payload, self.secret, algorithm=self.algorithm)

    def verify_token(self, token):
        try:
            return jwt.decode(
                token, self.secret,
                algorithms=[self.algorithm],
                options={"verify_aud": True, "verify_iss": True}
            )
        except jwt.ExpiredSignatureError:
            raise ValueError('Token has expired')
        except jwt.InvalidTokenError:
            raise ValueError('Invalid token')

# Decorator for protected routes
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth_header = request.headers.get('Authorization')

        if not auth_header:
            return jsonify({'error': 'Token missing'}), 401

        try:
            token = auth_header.split(' ')[1]
            jwt_auth = JWTAuth()
            payload = jwt_auth.verify_token(token)
            request.current_user = payload
        except (IndexError, ValueError) as e:
            return jsonify({'error': str(e)}), 401

        return f(*args, **kwargs)
    return decorated

JWT Security Audit Checklist

Secret & Configuration

Implementation Security

Quick Security Test

Test your JWT implementation:

  • • Try using 'none' algorithm → should be rejected
  • • Send expired token → should return 401
  • • Modify token signature → should be invalid
  • • Test with wrong audience/issuer → should be rejected

Bulk Generation

secrets

Implementation Examples

Node.js with Express.js

auth-middleware.js
const jwt = require('jsonwebtoken');

// Generate token (login)
function generateToken(user) {
  const payload = {
    userId: user.id,
    email: user.email,
    role: user.role
  };

  return jwt.sign(payload, process.env.JWT_SECRET, {
    algorithm: 'HS256',
    expiresIn: '24h',
    issuer: 'your-app-name',
    audience: 'your-app-users'
  });
}

// Verify token (middleware)
function verifyToken(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET, {
      algorithms: ['HS256']
    });
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

Python with Flask

jwt_utils.py
import jwt
import os
from datetime import datetime, timedelta
from functools import wraps
from flask import request, jsonify

JWT_SECRET = os.getenv('JWT_SECRET')
JWT_ALGORITHM = 'HS256'

def generate_token(user_data):
    payload = {
        'user_id': user_data['id'],
        'email': user_data['email'],
        'exp': datetime.utcnow() + timedelta(hours=24),
        'iat': datetime.utcnow(),
        'iss': 'your-app-name'
    }

    return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)

def verify_token(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization')

        if not token:
            return jsonify({'error': 'Token missing'}), 401

        try:
            token = token.split(' ')[1]  # Remove 'Bearer '
            decoded = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
            request.user = decoded
        except jwt.ExpiredSignatureError:
            return jsonify({'error': 'Token expired'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'error': 'Invalid token'}), 401

        return f(*args, **kwargs)
    return decorated

Java with Spring Boot

JwtUtil.java
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class JwtUtil {

    @Value("${jwt.secret}")
    private String jwtSecret;

    private final int jwtExpirationMs = 86400000; // 24 hours

    public String generateToken(String username, String role) {
        return Jwts.builder()
                .setSubject(username)
                .claim("role", role)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + jwtExpirationMs))
                .signWith(Keys.hmacShaKeyFor(jwtSecret.getBytes()), SignatureAlgorithm.HS256)
                .compact();
    }

    public Claims extractClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(Keys.hmacShaKeyFor(jwtSecret.getBytes()))
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    public boolean isTokenExpired(String token) {
        return extractClaims(token).getExpiration().before(new Date());
    }

    public boolean validateToken(String token) {
        try {
            extractClaims(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}

Go with Gin Framework

jwt_middleware.go
package middleware

import (
    "net/http"
    "strings"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt/v4"
)

var jwtSecret = []byte("your-secret-here")

type Claims struct {
    UserID string `json:"user_id"`
    Role   string `json:"role"`
    jwt.RegisteredClaims
}

func GenerateToken(userID, role string) (string, error) {
    claims := Claims{
        UserID: userID,
        Role:   role,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            Issuer:    "your-app",
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(jwtSecret)
}

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        authHeader := c.GetHeader("Authorization")
        if authHeader == "" {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"})
            c.Abort()
            return
        }

        tokenString := strings.TrimPrefix(authHeader, "Bearer ")

        claims := &Claims{}
        token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
            return jwtSecret, nil
        })

        if err != nil || !token.Valid {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }

        c.Set("userID", claims.UserID)
        c.Set("role", claims.Role)
        c.Next()
    }
}

C# with .NET Core

JwtService.cs
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public class JwtService
{
    private readonly string _secret = "your-secret-here";
    private readonly string _issuer = "your-app";

    public string GenerateToken(string userId, string role)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, userId),
            new Claim(ClaimTypes.Role, role),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(JwtRegisteredClaimNames.Iat,
                DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
        };

        var token = new JwtSecurityToken(
            issuer: _issuer,
            audience: _issuer,
            claims: claims,
            expires: DateTime.UtcNow.AddHours(24),
            signingCredentials: credentials
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    public ClaimsPrincipal ValidateToken(string token)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret));
        var tokenHandler = new JwtSecurityTokenHandler();

        var validationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = key,
            ValidateIssuer = true,
            ValidIssuer = _issuer,
            ValidateAudience = true,
            ValidAudience = _issuer,
            ClockSkew = TimeSpan.Zero
        };

        return tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
    }
}

PHP with Laravel

JwtHelper.php
<?php

namespace App\Helpers;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Exception;

class JwtHelper
{
    private static $secret = 'your-secret-here';
    private static $issuer = 'your-app';
    private static $algorithm = 'HS256';

    public static function generateToken($userId, $role)
    {
        $payload = [
            'iss' => self::$issuer,
            'sub' => $userId,
            'role' => $role,
            'iat' => time(),
            'exp' => time() + (24 * 60 * 60) // 24 hours
        ];

        return JWT::encode($payload, self::$secret, self::$algorithm);
    }

    public static function validateToken($token)
    {
        try {
            $decoded = JWT::decode($token, new Key(self::$secret, self::$algorithm));
            return (array) $decoded;
        } catch (Exception $e) {
            throw new Exception('Invalid token: ' . $e->getMessage());
        }
    }

    public static function refreshToken($token)
    {
        try {
            $decoded = self::validateToken($token);

            // Check if token expires in next hour
            if ($decoded['exp'] - time() < 3600) {
                return self::generateToken($decoded['sub'], $decoded['role']);
            }

            return $token; // No refresh needed
        } catch (Exception $e) {
            throw new Exception('Cannot refresh token: ' . $e->getMessage());
        }
    }
}

// Laravel Middleware
class JwtMiddleware
{
    public function handle($request, Closure $next)
    {
        $token = $request->bearerToken();

        if (!$token) {
            return response()->json(['error' => 'Token not provided'], 401);
        }

        try {
            $decoded = JwtHelper::validateToken($token);
            $request->merge(['user' => $decoded]);
            return $next($request);
        } catch (Exception $e) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
    }
}

Implementation Security Tips

  • Always validate the algorithm to prevent algorithm confusion attacks
  • Set appropriate expiration times - shorter is more secure but less convenient
  • Include audience and issuer claims for additional validation
  • Use HTTPS only in production to prevent token interception
  • Implement proper error handling without exposing sensitive information
  • Consider implementing token blacklisting for logout functionality

Generate in Terminal

For production systems, generate secrets locally:

OpenSSL (256-bit, base64)

$openssl rand -base64 32

OpenSSL (256-bit, hex)

$openssl rand -hex 32

Python secrets module

$python3 -c "import secrets; print(secrets.token_urlsafe(32))"

Node.js crypto

$node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

How to Generate a Secure JWT Secret Key

01
Choose JWT Algorithm
Select your JWT signing algorithm (HS256, HS384, or HS512) based on your security requirements.
02
Generate Secret Key
Click the generate button to create a cryptographically secure random secret key.
03
Copy Secret Key
Copy the generated secret key and store it securely in your application's environment variables.
04
Implement in Code
Use the secret key in your JWT library configuration for token signing and verification.