spring-projects / spring-projects/spring-security

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

Open
#17,098 11 comments 20 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: oauth2 type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in NimbusJwtEncoder at selectJwk and createJwkMatcher, then inspect SignatureAlgorithm and JwtEncoderParameters to understand how the requested algorithm reaches key selection. Reproduce the supplied Ed25519 example and verify that an OctetKeyPair with Curve.Ed25519 can be selected and used to produce a signed JWT.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.