Polish JwtEncoder APIs

Closes gh-391
This commit is contained in:
Joe Grandja
2021-08-09 15:21:46 -04:00
parent ea7c68997f
commit 6b5d9f0fe5
7 changed files with 266 additions and 217 deletions

View File

@@ -17,6 +17,7 @@ package org.springframework.security.oauth2.jwt;
import org.junit.Test;
import org.springframework.security.oauth2.jose.JwaAlgorithm;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,18 +34,18 @@ public class JoseHeaderTests {
public void withAlgorithmWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> JoseHeader.withAlgorithm(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("jwsAlgorithm cannot be null");
.hasMessage("jwaAlgorithm cannot be null");
}
@Test
public void buildWhenAllHeadersProvidedThenAllHeadersAreSet() {
JoseHeader expectedJoseHeader = TestJoseHeaders.joseHeader().build();
JoseHeader joseHeader = JoseHeader.withAlgorithm(expectedJoseHeader.getJwsAlgorithm())
.jwkSetUri(expectedJoseHeader.getJwkSetUri().toExternalForm())
JoseHeader joseHeader = JoseHeader.withAlgorithm(expectedJoseHeader.getAlgorithm())
.jwkSetUrl(expectedJoseHeader.getJwkSetUrl().toExternalForm())
.jwk(expectedJoseHeader.getJwk())
.keyId(expectedJoseHeader.getKeyId())
.x509Uri(expectedJoseHeader.getX509Uri().toExternalForm())
.x509Url(expectedJoseHeader.getX509Url().toExternalForm())
.x509CertificateChain(expectedJoseHeader.getX509CertificateChain())
.x509SHA1Thumbprint(expectedJoseHeader.getX509SHA1Thumbprint())
.x509SHA256Thumbprint(expectedJoseHeader.getX509SHA256Thumbprint())
@@ -53,11 +54,11 @@ public class JoseHeaderTests {
.headers(headers -> headers.put("custom-header-name", "custom-header-value"))
.build();
assertThat(joseHeader.getJwsAlgorithm()).isEqualTo(expectedJoseHeader.getJwsAlgorithm());
assertThat(joseHeader.getJwkSetUri()).isEqualTo(expectedJoseHeader.getJwkSetUri());
assertThat(joseHeader.<JwaAlgorithm>getAlgorithm()).isEqualTo(expectedJoseHeader.getAlgorithm());
assertThat(joseHeader.getJwkSetUrl()).isEqualTo(expectedJoseHeader.getJwkSetUrl());
assertThat(joseHeader.getJwk()).isEqualTo(expectedJoseHeader.getJwk());
assertThat(joseHeader.getKeyId()).isEqualTo(expectedJoseHeader.getKeyId());
assertThat(joseHeader.getX509Uri()).isEqualTo(expectedJoseHeader.getX509Uri());
assertThat(joseHeader.getX509Url()).isEqualTo(expectedJoseHeader.getX509Url());
assertThat(joseHeader.getX509CertificateChain()).isEqualTo(expectedJoseHeader.getX509CertificateChain());
assertThat(joseHeader.getX509SHA1Thumbprint()).isEqualTo(expectedJoseHeader.getX509SHA1Thumbprint());
assertThat(joseHeader.getX509SHA256Thumbprint()).isEqualTo(expectedJoseHeader.getX509SHA256Thumbprint());

View File

@@ -39,6 +39,7 @@ import org.mockito.stubbing.Answer;
import org.springframework.security.oauth2.jose.TestJwks;
import org.springframework.security.oauth2.jose.TestKeys;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -111,7 +112,7 @@ public class NimbusJwsEncoderTests {
this.jwkList.add(rsaJwk);
this.jwkList.add(rsaJwk);
JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
assertThatExceptionOfType(JwtEncodingException.class)
@@ -129,24 +130,6 @@ public class NimbusJwsEncoderTests {
.withMessageContaining("Failed to select a JWK signing key");
}
@Test
public void encodeWhenJwkKidNullThenThrowJwtEncodingException() throws Exception {
// @formatter:off
RSAKey rsaJwk = TestJwks.jwk(TestKeys.DEFAULT_PUBLIC_KEY, TestKeys.DEFAULT_PRIVATE_KEY)
.keyID(null)
.build();
// @formatter:on
this.jwkList.add(rsaJwk);
JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
assertThatExceptionOfType(JwtEncodingException.class)
.isThrownBy(() -> this.jwsEncoder.encode(joseHeader, jwtClaimsSet))
.withMessageContaining("The \"kid\" (key ID) from the selected JWK cannot be empty");
}
@Test
public void encodeWhenJwkUseEncryptionThenThrowJwtEncodingException() throws Exception {
// @formatter:off
@@ -172,15 +155,31 @@ public class NimbusJwsEncoderTests {
RSAKey rsaJwk = TestJwks.DEFAULT_RSA_JWK;
this.jwkList.add(rsaJwk);
JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
Jwt encodedJws = this.jwsEncoder.encode(joseHeader, jwtClaimsSet);
// Assert headers/claims were added
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.TYP)).isEqualTo("JWT");
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.ALG)).isEqualTo(joseHeader.getAlgorithm());
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.JKU)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.JWK)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.KID)).isEqualTo(rsaJwk.getKeyID());
assertThat(encodedJws.getId()).isNotNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5U)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5C)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5T)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5T_S256)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.TYP)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.CTY)).isNull();
assertThat(encodedJws.getHeaders().get(JoseHeaderNames.CRIT)).isNull();
assertThat(encodedJws.getIssuer()).isEqualTo(jwtClaimsSet.getIssuer());
assertThat(encodedJws.getSubject()).isEqualTo(jwtClaimsSet.getSubject());
assertThat(encodedJws.getAudience()).isEqualTo(jwtClaimsSet.getAudience());
assertThat(encodedJws.getExpiresAt()).isEqualTo(jwtClaimsSet.getExpiresAt());
assertThat(encodedJws.getNotBefore()).isEqualTo(jwtClaimsSet.getNotBefore());
assertThat(encodedJws.getIssuedAt()).isEqualTo(jwtClaimsSet.getIssuedAt());
assertThat(encodedJws.getId()).isEqualTo(jwtClaimsSet.getId());
assertThat(encodedJws.<String>getClaim("custom-claim-name")).isEqualTo("custom-claim-value");
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(rsaJwk.toRSAPublicKey()).build();
jwtDecoder.decode(encodedJws.getTokenValue());
@@ -200,7 +199,7 @@ public class NimbusJwsEncoderTests {
JwkListResultCaptor jwkListResultCaptor = new JwkListResultCaptor();
willAnswer(jwkListResultCaptor).given(jwkSourceDelegate).get(any(), any());
JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
Jwt encodedJws = jwsEncoder.encode(joseHeader, jwtClaimsSet);

View File

@@ -36,10 +36,10 @@ public final class TestJoseHeaders {
public static JoseHeader.Builder joseHeader(SignatureAlgorithm signatureAlgorithm) {
// @formatter:off
return JoseHeader.withAlgorithm(signatureAlgorithm)
.jwkSetUri("https://provider.com/oauth2/jwks")
.jwkSetUrl("https://provider.com/oauth2/jwks")
.jwk(rsaJwk())
.keyId("keyId")
.x509Uri("https://provider.com/oauth2/x509")
.x509Url("https://provider.com/oauth2/x509")
.x509CertificateChain(Arrays.asList("x509Cert1", "x509Cert2"))
.x509SHA1Thumbprint("x509SHA1Thumbprint")
.x509SHA256Thumbprint("x509SHA256Thumbprint")