JWT Security Tool

Generate JWT Secrets Instantly

Create cryptographically secure JWT signing secrets for your applications. Generate strong keys for JSON Web Token authentication and authorization.

Secret Strength Calculating...

JWT Secret Options

32
16 256

JWT Best Practices

Excludes characters that need URL encoding

Ensures maximum randomness for JWT signing

Output as base64 encoded string

Bulk Generation

JWT Security Best Practices

Learn how to properly secure your JWT implementations with strong signing secrets

Strong Secret Keys

Use cryptographically secure secrets with at least 256 bits of entropy. Never use predictable or short secrets.

Environment Variables

Store JWT secrets in environment variables, never hardcode them in your source code or configuration files.

Regular Rotation

Implement secret rotation policies. Change JWT secrets periodically and when security incidents occur.

Algorithm Selection

Use HS256 minimum, prefer HS384 or HS512 for higher security. Avoid 'none' algorithm and weak signing methods.

Short Expiration

Set appropriate expiration times. Use short-lived tokens with refresh token patterns for better security.

Secure Transmission

Always transmit JWTs over HTTPS. Use secure headers and implement proper CORS policies.

JWT Algorithm Comparison

Choose the right HMAC algorithm for your security requirements

Algorithm Secret Length Hash Output Security Level Use Case
HS256
HMAC-SHA256
32+ bytes 256 bits Standard General purpose, widely supported
HS384
HMAC-SHA384
48+ bytes 384 bits High Sensitive applications, compliance
HS512
HMAC-SHA512
64+ bytes 512 bits Maximum High-security environments

Implementation Examples

See how to properly use JWT secrets in popular frameworks and languages

Node.js with jsonwebtoken

// .env
JWT_SECRET=your-base64-encoded-secret-here

// main.js
"keyword">import { jwt } "keyword">from 'jsonwebtoken';

// Load your secret key "keyword">from environment variables
"keyword">const secretKey = process.env.JWT_SECRET; // e.g., 'your-base64-encoded-secret-here'

"keyword">const payload = {
  iss: 'my-app',
  sub: 'user123',
  name: 'John Doe',
  admin: true
};

// ✍️ Signing a token
"keyword">const token = jwt.sign(payload, secretKey, { 
  algorithm: 'HS256',
  expiresIn: '1h' 
});

console.log('Generated Token:', token);

// ✅ Verifying a token
"keyword">try {
  "keyword">const decoded = jwt.verify(token, secretKey, { algorithms: ['HS256'] });
  console.log('Decoded Payload:', decoded);
} "keyword">catch (err) {
  console.error('Invalid token:', err.message);
}

Python with PyJWT

# .env
JWT_SECRET=your-base64-encoded-secret-here

# main.py
import jwt
import os
import base64
from datetime import datetime, timedelta, timezone

# Load your secret key and decode it from Base64 to bytes
secret_key_b64 = os.getenv('JWT_SECRET') # e.g., 'your-base64-encoded-secret-here'
secret_key = base64.b64decode(secret_key_b64)

payload = {
    'iss': 'my-app',
    'sub': 'user123',
    'name': 'Jane Doe',
    'iat': datetime.now(timezone.utc),
    'exp': datetime.now(timezone.utc) + timedelta(hours=1)
}

# ✍️ Encoding (signing) a token
token = jwt.encode(payload, secret_key, algorithm='HS256')
print(f"Generated Token: {token}")

# ✅ Decoding (verifying) a token
try:
    decoded = jwt.decode(token, secret_key, algorithms=['HS256'])
    print(f"Decoded Payload: {decoded}")
except jwt.InvalidTokenError as e:
    print(f"Invalid token: {e}")
}

PHP with Firebase/JWT

# .env
JWT_SECRET=your-base64-encoded-secret-here

// main.php
<?php
require_once('vendor/autoload.php');

use FirebaseJWTJWT;
use FirebaseJWTKey;

// Load your secret key from an environment variable
// The key should be the raw bytes, so we decode the Base64 string
$secretKey = base64_decode(getenv('JWT_SECRET'));

$issuedAt   = time();
$expire     = $issuedAt + 3600; // 1 hour
$issuer     = "my-app";

$payload = [
    'iss' => $issuer,
    'iat' => $issuedAt,
    'exp' => $expire,
    'sub' => 'user123',
    'name' => 'Jim Doe'
];

// ✍️ Encoding (signing) a token
$token = JWT::encode($payload, $secretKey, 'HS256');
echo "Generated Token: " . $token . "
";

// ✅ Decoding (verifying) a token
try {
    $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
    print_r($decoded);
} catch (Exception $e) {
    echo 'Invalid token: ',  $e->getMessage(), "
";
}

Go with Golang-jwt

// .env
JWT_SECRET=your-base64-encoded-secret-here

// main.go
package main

import (
	"fmt"
	"os"
	"time"
	"github.com/golang-jwt/jwt/v5"
)

func main() {
	// Load your secret key from environment variables.
	// In a real app, this should be the raw bytes. For convenience,
	// we are using the Base64 string here but it's better to load raw bytes.
	var secretKey = []byte(os.Getenv("JWT_SECRET")) // e.g., 'your-secret-key-as-string'
                                                  // or base64.StdEncoding.DecodeString(...)
    
	// ✍️ Creating and signing a token
	claims := jwt.MapClaims{
		"iss":   "my-app",
		"sub":   "user123",
		"name":  "Go Gopher",
		"admin": true,
		"exp":   time.Now().Add(time.Hour * 1).Unix(),
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(secretKey)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Generated Token: %v
", tokenString)

	// ✅ Parsing and validating a token
	parsedToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		// Validate the signing algorithm
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		return secretKey, nil
	})

	if err != nil {
		fmt.Printf("Invalid token: %v
", err)
	} else if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok && parsedToken.Valid {
		fmt.Printf("Decoded Claims: Name=%v, Admin=%v
", claims["name"], claims["admin"])
	} else {
		fmt.Println("Invalid token")
	}
}