Skip to content

NimbusJwtEncoder does not support Edwards Curve signature (EdDSA) family algorithms. #17098

Open
@TRUSTMEIMJEDI

Description

@TRUSTMEIMJEDI

Description
It is currently possible to create a NimbusJwtEncoder using an ImmutableJWKSet that contains an Ed25519 key (via OctetKeyPair), but it is not possible to use that encoder to generate a JWT signed with Ed25519 (EdDSA).

Problem Details

  • JwtEncoderParameters.from(header, claims) does not allow custom algorithms in the header.
    • Only enums implementing JwsAlgorithm or JwaAlgorithm are allowed.
    • The default SignatureAlgorithm enum implements JwsAlgorithm, but does not include any EdDSA algorithms like EdDSA (com.nimbusds.jose.JWSAlgorithm.EdDSA).
  • Even if a custom implementation of JwsAlgorithm is provided to represent EdDSA, it does not resolve the problem because of how NimbusJwtEncoder internally selects a signing key.
  • During encoding, the selectJwk method is called. This uses a JWKSelector created with a matcher generated by the private createJwkMatcher method.
    • Unfortunately, createJwkMatcher does not support the EdDSA algorithm family, which results in the JWKSelector being constructed with a null matcher.
    • This causes IllegalArgumentException to be thrown at runtime due to the missing matcher.

When running following code:

val header = JwsHeader.with(FixedSignatureAlgorithm.Ed25519).build()
val claims = JwtClaimsSet.builder()
    .issuer(issuer)
    .issuedAt(Instant.now())
    .expiresAt(expiresAt)
    .claim(SESSION_ID_CLAIM_NAME, sessionId)
    .build()

jwtEncoder.encode(JwtEncoderParameters.from(header, claims)).tokenValue
public enum FixedSignatureAlgorithm implements JwsAlgorithm {
	RS256(JwsAlgorithms.RS256),
	RS384(JwsAlgorithms.RS384),
	RS512(JwsAlgorithms.RS512),
	ES256(JwsAlgorithms.ES256),
	ES384(JwsAlgorithms.ES384),
	ES512(JwsAlgorithms.ES512),
	PS256(JwsAlgorithms.PS256),
	PS384(JwsAlgorithms.PS384),
	PS512(JwsAlgorithms.PS512),
    EdDSA(JWSAlgorithm.EdDSA.getName()),
    Ed25519(JWSAlgorithm.Ed25519.getName());

	private final String name;

	FixedSignatureAlgorithm(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return this.name;
	}

	public static FixedSignatureAlgorithm from(String name) {
		for (FixedSignatureAlgorithm value : values()) {
			if (value.getName().equals(name)) {
				return value;
			}
		}
		return null;
	}
}

then such error is thrown:

org.springframework.security.oauth2.jwt.JwtEncodingException: An error occurred while attempting to encode the Jwt: Failed to select a JWK signing key -> The JWK matcher must not be null
	at org.springframework.security.oauth2.jwt.NimbusJwtEncoder.selectJwk(NimbusJwtEncoder.java:123)
	at org.springframework.security.oauth2.jwt.NimbusJwtEncoder.encode(NimbusJwtEncoder.java:108)
Caused by: java.lang.IllegalArgumentException: The JWK matcher must not be null
	at com.nimbusds.jose.jwk.JWKSelector.<init>(JWKSelector.java:51)
	at org.springframework.security.oauth2.jwt.NimbusJwtEncoder.selectJwk(NimbusJwtEncoder.java:119)
	... 158 common frames omitted

Suggested fix
To support Ed25519/EdDSA, the following would need to be addressed:

  1. Add EdDSA (JWSAlgorithm.EdDSA) support to the SignatureAlgorithm enum or allow flexible/custom algorithm headers in JwtEncoderParameters.
  2. Update createJwkMatcher in NimbusJwtEncoder to recognize and match EdDSA algorithm family keys like OctetKeyPair with Curve.Ed25519.

Used versions
com.springframework.security:spring-security-oauth2-jose:6.3.3
com.nimbusds:nimbus-jose-jwt:9.40

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)type: enhancementA general enhancement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions