PS256 is the JWT algorithm identifier for RSA-PSS signatures using SHA-256. It is an asymmetric signing algorithm: a private key signs the token, while the matching public key verifies it. section 8.2
Unlike RS256, PS256 uses probabilistic signatures, so the same input can produce different signatures. This substantially reduces the risk of attackers cracking the signing key and forging tokens. FAPI recommends PS256 and EdDSA as stronger alternatives to RS256, whose incorrect implementations have enabled signature-forgery attacks. section 8.2 section 7.2.2
Issuing a PS256 JWT
Generate an RSA key pair with OpenSSL, load private_key.pem through Python’s cryptography library, and pass the resulting private key to PyJWT with algorithm="PS256". The payload can contain issuer, subject, audience, issued-at, and expiration claims. section 8.2
Listing 8.6 Issuing a JWT with PS256 signature using PyJWT
# file: ch08/jwt_generator_pyjwt_ps256.py
from pathlib import Path
import jwt
from cryptography.hazmat.primitives import serialization
private_key_text = Path("private_key.pem").read_text()
private_key = serialization.load_pem_private_key(
data=private_key_text.encode(), password=None
)
payload = {...} # same as in listing 8.3
print(
jwt.encode(payload=payload, key=private_key, algorithm="PS256")
) #1
Shows the focused PyJWT code for loading a PEM private key and issuing a JWT with PS256. section 8.2
Validation uses the corresponding public key and must constrain the accepted algorithm to PS256. Also validate the audience and issuer claims and reject expired tokens. Try changing the audience or allowed-algorithm list to observe validation errors. section 8.3
Secure PS256 integration checks:
- Use a maintained JWT library with PS256 support and protection against algorithm confusion. section 8.3
- Keep the private key for signing and distribute the public key for verification. section 8.2
- Validate every access token on every request, preferably in server middleware. section 8.7
Listing 8.8 Validating tokens with a PS256 signature
# file: ch08/jwt_validator_pyjwt_ps256.py
from pathlib import Path
import jwt
from cryptography.hazmat.primitives.serialization \
import load_pem_public_key
public_key = load_pem_public_key( #1
Path("public_key.pem").read_text().encode()
)
def validate_token(token):
return jwt.decode(
jwt=token,
key=public_key, #2
algorithms=["PS256"], #3
audience="https://apithreats.com/api",
issuer="https://auth.apithreats.com",
)
token = <token>
print(validate_token(token))
Shows PyJWT validation with a loaded public key, an explicit PS256 algorithm allowlist, and fixed audience and issuer values. section 8.3

