spring-projects/spring-security · error · JwtEncodingException
Failed to encode the JWT due to signing error: Failed to sig
Error message
Failed to encode the JWT due to signing error: Failed to sign the JWT -> + ex.getMessage()
What it means
NimbusJwtEncoder wraps JOSEException thrown by nimbus-jose-jwt's SignedJWT.sign() into a JwtEncodingException with this message. It means the JWS was fully constructed (header + claims) but the actual cryptographic signing operation failed, e.g. the signer rejected the key or algorithm at sign time. The library throws it rather than letting a raw JOSEException escape, so callers always see JwtEncodingException from encode().
Source
Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java:221
}
if (jwks.size() == 1) {
return jwks.get(0);
}
return this.jwkSelector.convert(jwks);
}
private String serialize(JwsHeader headers, JwtClaimsSet claims, JWK jwk) {
JWSHeader jwsHeader = convert(headers);
JWTClaimsSet jwtClaimsSet = convert(claims);
JWSSigner jwsSigner = this.jwsSigners.computeIfAbsent(jwk, NimbusJwtEncoder::createSigner);
SignedJWT signedJwt = new SignedJWT(jwsHeader, jwtClaimsSet);
try {
signedJwt.sign(jwsSigner);
}
catch (JOSEException ex) {
throw new JwtEncodingException(
String.format(ENCODING_ERROR_MESSAGE_TEMPLATE, "Failed to sign the JWT -> " + ex.getMessage()), ex);
}
return signedJwt.serialize();
}
private static @Nullable JWKMatcher createJwkMatcher(JwsHeader headers) {
JwsAlgorithm algorithm = headers.getAlgorithm();
Assert.notNull(algorithm, "JWS header algorithm must not be null");
JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(algorithm.getName());
if (JWSAlgorithm.Family.RSA.contains(jwsAlgorithm) || JWSAlgorithm.Family.EC.contains(jwsAlgorithm)) {
// @formatter:off
return new JWKMatcher.Builder()
.keyType(KeyType.forAlgorithm(jwsAlgorithm))
.keyID(headers.getKeyId())
.keyUses(KeyUse.SIGNATURE, null)
.algorithms(jwsAlgorithm, null)
.x509CertSHA256Thumbprint(Base64URL.from(headers.getX509SHA256Thumbprint()))View on GitHub (pinned to 96852e8860)
Solutions
- Verify the JWK in your JWKSource matches the JwsAlgorithm: RSA key for RS256/RS384/RS512, EC P-256/384/521 key for ES256/384/512, symmetric key for HS256/384/512.
- For HS256/384/512, ensure the symmetric secret is at least as long as the hash output (256/384/512 bits): generate with a secure random generator, not a short passphrase.
- Read the underlying JOSEException message (it is appended and available via getCause()) — it names the exact key/algorithm constraint violated.
- Regenerate key material if it was truncated, hand-edited, or exported incorrectly (e.g. Base64-decoding mistakes in an OctetSequenceKey).
Example fix
// before String secret = "short-secret"; SecretKey key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); // after byte[] secretBytes = new byte[32]; new SecureRandom().nextBytes(secretBytes); SecretKey key = new SecretKeySpec(secretBytes, "HmacSHA256");
Defensive patterns
Strategy: try-catch
Validate before calling
// before encode
JWK jwk = ...; // resolved key
if ("oct".equals(jwk.getKeyType().getValue())
&& jwk instanceof OctetSequenceKey osk
&& osk.getSecretBytes().length * 8 < algorithmBitLength(headers.getAlgorithm())) {
throw new IllegalStateException("Symmetric key too short for " + headers.getAlgorithm());
} Try / catch
try {
jwt = jwtEncoder.encode(params);
} catch (JwtEncodingException ex) {
logger.error("JWT signing failed: {}", ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage(), ex);
throw new IllegalStateException("Token signing misconfiguration", ex);
} Prevention
- Generate signing keys with proper length/entropy (RSA >= 2048 bits, symmetric >= hash output length).
- Keep key type and JwsAlgorithm pairs in one config constant so they cannot drift apart.
- Unit-test signing once at startup with a throwaway claim set to fail fast on bad keys.
- Never pass a human passphrase directly as an HS256 secret.
When it happens
Trigger: Calling NimbusJwtEncoder.encode(JwtEncoderParameters) where the resolved JWSSigner fails during sign(): a JWK whose key material is malformed or too short for the algorithm (e.g. RSA key smaller than 2048 bits for RS256), a MAC algorithm whose secret is shorter than the required minimum (e.g. HS256 secret < 256 bits), or a signer built for an algorithm that does not match the key supplied via JWKSource.
Common situations: Dev environments using truncated or hardcoded secrets for HS256; generating RSA keys with 1024 bits for legacy reasons; swapping a signing key in a config server without regenerating key material; using an OctetSequenceKey built from a passphrase string instead of a full-entropy random key; algorithm changed in JwsHeader but the JWK in the JWKSource is for a different key type.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid_dpop_proof
- invalid_key
- Unsupported alg parameter in JWS Header: ${algorithm.getName
- Missing jwk parameter in JWS Header.
- %s
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/0ab0b131b1533093.
Report an issue: GitHub.