Guide Updated

JWT HS256 (HMAC-SHA256)

JWT HS256 (HMAC with SHA-256) is the symmetric signing algorithm: one secret signs and verifies. Learn key requirements, sign/verify code in Node.js and Python, and when HS256 is the right choice.

HS256 is HMAC with SHA-256: the symmetric JWT signing algorithm. The same secret key signs the token and verifies it. It is the simplest correct choice when the token issuer and all verifiers live in the same trust boundary. Defined in RFC 7518 §3.2.

Key facts and signature size

Property HS256
Type Symmetric (HMAC)
Key 256-bit (32-byte) shared secret minimum
Signature size 32 bytes
Security Key-dependent: depends entirely on secret entropy
Compatibility Universal: every JWT library supports HS256

When to use

Use HS256 for monoliths, single-backend APIs, and any system where only one service or a tightly controlled cluster needs to verify tokens and can securely share the secret through a secrets manager. It is the simplest correct choice with no key infrastructure (no JWKS, no key pairs).

When not to use

Avoid HS256 in multi-service architectures where you would need to share the secret across teams, or when third parties need to verify your tokens: anyone who can verify an HS256 token can also forge one. Switch to RS256, PS256, or ES256 (asymmetric) instead.

Code examples

Sign and verify (Node.js: jsonwebtoken)

          const jwt = require("jsonwebtoken");
const secret = process.env.JWT_SECRET; // 32+ bytes of random data

// Sign
const token = jwt.sign(
  { sub: "user_123", role: "user" },
  secret,
  {
    algorithm: "HS256",
    expiresIn: "15m",
    issuer: "https://auth.example.com",
    audience: "https://api.example.com",
  }
);

// Verify: hardcode the algorithm, validate iss + aud + exp
const payload = jwt.verify(token, secret, {
  algorithms: ["HS256"],
  issuer: "https://auth.example.com",
  audience: "https://api.example.com",
});
        

Generate a secure secret

          # OpenSSL
openssl rand -base64 32

# Node.js
const crypto = require("crypto");
const secret = crypto.randomBytes(32).toString("base64url");

# Python
import secrets
secret = secrets.token_urlsafe(32)
        

Frequently asked questions

  • What is HS256 in JWT?

    HS256 is HMAC with SHA-256: the symmetric JWT signing algorithm. The same secret key signs and verifies the token. The signature is 32 bytes, the smallest of any JWT algorithm. The security depends entirely on the secret's entropy: a 32-byte cryptographically random secret is effectively unbreakable; a weak or guessed secret can be brute-forced offline with hashcat once an attacker obtains any valid token.

  • How long should an HS256 secret be?

    At least 32 bytes (256 bits) of cryptographically random data from a CSPRNG: not a password, UUID, or memorable phrase. Generate it with openssl rand -base64 32, crypto.randomBytes(32) in Node.js, or secrets.token_urlsafe(32) in Python. Shorter or low-entropy secrets can be brute-forced offline with hashcat (mode 16500) in seconds to minutes on a modern GPU.

  • Is HS256 or RS256 better for JWT?

    HS256 is better when one service both issues and verifies its own tokens: it is simpler with no key infrastructure. RS256 is better when tokens are verified by multiple independent services or third parties: the private key signs, the public key verifies, so verifiers cannot forge tokens. If you integrate with Auth0, Okta, or AWS Cognito, use RS256 (their default). Never use both in the same algorithms array unless you have a documented reason.

Related