Aarunya AppsAarunya Apps

HS256 JWT Algorithm

HS256 signs tokens using a shared secret key and SHA-256 hashing. Both the token issuer and every verifier must hold the same secret. This symmetric design makes HS256 the simplest JWT algorithm to implement, and the fastest to verify — but it means you cannot share a public key with third parties for independent verification.

Family
HMAC
Hash
SHA-256
Key type
symmetric
Performance
Fast (< 0.1ms)

Key Requirements

A shared secret of at least 256 bits (32 bytes) — matching the SHA-256 output size. Generate a secure key with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

JWT Header

Every JWT using HS256 has this header (base64url-encoded as the first segment):

{
  "alg": "HS256",
  "typ": "JWT"
}

Code Examples

Node.js — Sign (jose library)
import { SignJWT } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET) // 32+ bytes

export async function signToken(payload: Record<string, unknown>) {
  return new SignJWT(payload)
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('2h')
    .sign(secret)
}
Node.js — Verify (jose library)
import { jwtVerify } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET)

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, secret, {
    algorithms: ['HS256'],
  })
  return payload
}
Python — PyJWT
import jwt  # pip install PyJWT

SECRET = "your-256-bit-secret"  # 32+ bytes

# Sign
token = jwt.encode(
    {"sub": "1234567890", "name": "John Doe"},
    SECRET,
    algorithm="HS256",
)

# Verify
payload = jwt.decode(token, SECRET, algorithms=["HS256"])

When to Use HS256

Best for monolithic applications and microservices within the same trust boundary that share a secret (for example, a single backend service issuing and verifying its own session tokens). Avoid HS256 when different organisations or services need to independently verify tokens — use RS256 or ES256 instead.

Security Considerations

The secret must stay private on every host that verifies tokens. Compromise of the secret lets an attacker forge arbitrary tokens. Store secrets in a secrets manager (AWS Secrets Manager, HashiCorp Vault, Doppler) — never hard-code or commit them.

Related Algorithms

Standardised in RFC 7518 §3.2 — JSON Web Algorithms (JWA).

Decode a real JWT

Paste any JWT into the debugger to inspect the header, payload, and verify an HS256 signature.

Open JWT Debugger

Frequently Asked Questions

Can I verify an HMAC JWT without knowing the secret?

No. HMAC-family algorithms (HS256, HS384, HS512) are symmetric — the same secret is used to both sign and verify. Without the secret, you can decode the header and payload (they're just base64url-encoded) but cannot verify the signature's authenticity.

How long should my HMAC secret be?

At least as long as the hash output — 32 bytes (256 bits) for HS256, 48 bytes for HS384, 64 bytes for HS512. Generate with Node.js: require('crypto').randomBytes(32).toString('hex'). Never use passwords or guessable strings as JWT secrets.

When should I use HS256 vs RS256?

Use HS256 when all services that verify the token are in your trust boundary and can share the secret securely (e.g., a single backend service). Use RS256 when you need to share the public key with external services (OAuth resource servers, third-party clients) without sharing the signing secret.