RS256 JWT Algorithm
RS256 signs tokens with an RSA private key and verifies them with the corresponding public key. This asymmetric design means the public key can be shared openly — resource servers and third parties can verify tokens without access to the signing secret. RS256 is the most widely adopted JWT algorithm in OAuth 2.0 and OpenID Connect deployments.
Key Requirements
RSA key pair of at least 2048 bits. RSA-2048 is the minimum; RSA-3072 or RSA-4096 recommended for new systems. Generate: openssl genrsa -out private.pem 3072
JWT Header
Every JWT using RS256 has this header (base64url-encoded as the first segment):
{
"alg": "RS256",
"typ": "JWT"
}Code Examples
Node.js — Sign (jose library)
import { SignJWT, importPKCS8 } from 'jose'
// Load private key once at startup
const privateKey = await importPKCS8(process.env.RSA_PRIVATE_KEY!, 'RS256')
export async function signToken(payload: Record<string, unknown>) {
return new SignJWT(payload)
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('1h')
.sign(privateKey)
}Node.js — Verify (jose library)
import { jwtVerify, importSPKI, createRemoteJWKSet } from 'jose'
// Option A: load public key from PEM
const publicKey = await importSPKI(process.env.RSA_PUBLIC_KEY!, 'RS256')
// Option B: load from JWKS endpoint (recommended for OIDC)
const JWKS = createRemoteJWKSet(new URL('https://your-auth-server/.well-known/jwks.json'))
export async function verifyToken(token: string) {
const { payload } = await jwtVerify(token, JWKS, {
algorithms: ['RS256'],
})
return payload
}Python — PyJWT
import jwt
from cryptography.hazmat.primitives import serialization
# Load keys
with open("private.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
with open("public.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
# Sign
token = jwt.encode({"sub": "1234567890"}, private_key, algorithm="RS256")
# Verify
payload = jwt.decode(token, public_key, algorithms=["RS256"])When to Use RS256
The standard choice for OAuth 2.0, OIDC identity providers, and multi-service architectures where resource servers must verify tokens issued by a separate auth server — without sharing the signing secret. Auth0, Okta, AWS Cognito, and Google all default to RS256.
Security Considerations
RS256 uses PKCS#1 v1.5 padding which has known theoretical vulnerabilities (Bleichenbacher's attack). For new systems, prefer PS256 which uses the provably-secure RSA-PSS padding. Keys must be at least RSA-2048; RSA-1024 is insecure and rejected by modern libraries.
Related Algorithms
Standardised in RFC 7518 §3.3 — JSON Web Algorithms (JWA).
Decode a real JWT
Paste any JWT into the debugger to inspect the header, payload, and verify an RS256 signature.
Open JWT DebuggerFrequently Asked Questions
Can the same RSA key pair be used for both RS256 and PS256?
Yes. RS256 and PS256 use the same RSA key format (PKCS#8 PEM for private keys, SPKI PEM for public keys). The difference is in the padding scheme applied during signing — PKCS#1 v1.5 for RS256, PSS for PS256. You can reuse existing RSA keys when migrating from RS256 to PS256.
What minimum key size should I use for RSA JWT signing?
2048-bit RSA minimum. 3072-bit is recommended for new systems as it provides a higher security margin at modest performance cost. 4096-bit if using RS512 or PS512 to match the SHA-512 security level. RSA-1024 is insecure and rejected by modern JWT libraries.
How do I expose my public key for token verification?
Publish your public key as a JWKS (JSON Web Key Set) at a well-known URL, typically /.well-known/jwks.json. Clients use createRemoteJWKSet() (jose library) or similar to fetch and cache the public keys, automatically handling key rotation.
