Replace ManagedKey with CryptoKey

Closes gh-105
This commit is contained in:
Joe Grandja
2020-10-25 19:58:29 -04:00
parent 8100568613
commit a9423c6b13
23 changed files with 757 additions and 731 deletions

View File

@@ -27,8 +27,8 @@ import org.springframework.http.HttpHeaders;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
@@ -85,7 +85,7 @@ public class OAuth2AuthorizationCodeGrantTests {
private static RegisteredClientRepository registeredClientRepository;
private static OAuth2AuthorizationService authorizationService;
private static KeyManager keyManager;
private static CryptoKeySource keySource;
@Rule
public final SpringTestRule spring = new SpringTestRule();
@@ -97,7 +97,7 @@ public class OAuth2AuthorizationCodeGrantTests {
public static void init() {
registeredClientRepository = mock(RegisteredClientRepository.class);
authorizationService = mock(OAuth2AuthorizationService.class);
keyManager = new StaticKeyGeneratingKeyManager();
keySource = new StaticKeyGeneratingCryptoKeySource();
}
@Before
@@ -266,8 +266,8 @@ public class OAuth2AuthorizationCodeGrantTests {
}
@Bean
KeyManager keyManager() {
return keyManager;
CryptoKeySource keySource() {
return keySource;
}
}
}

View File

@@ -26,8 +26,8 @@ import org.springframework.http.HttpHeaders;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -61,7 +61,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class OAuth2ClientCredentialsGrantTests {
private static RegisteredClientRepository registeredClientRepository;
private static OAuth2AuthorizationService authorizationService;
private static KeyManager keyManager;
private static CryptoKeySource keySource;
@Rule
public final SpringTestRule spring = new SpringTestRule();
@@ -73,7 +73,7 @@ public class OAuth2ClientCredentialsGrantTests {
public static void init() {
registeredClientRepository = mock(RegisteredClientRepository.class);
authorizationService = mock(OAuth2AuthorizationService.class);
keyManager = new StaticKeyGeneratingKeyManager();
keySource = new StaticKeyGeneratingCryptoKeySource();
}
@Before
@@ -159,8 +159,8 @@ public class OAuth2ClientCredentialsGrantTests {
}
@Bean
KeyManager keyManager() {
return keyManager;
CryptoKeySource keySource() {
return keySource;
}
}
}

View File

@@ -26,8 +26,8 @@ import org.springframework.http.HttpHeaders;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
@@ -67,6 +67,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class OAuth2RefreshTokenGrantTests {
private static RegisteredClientRepository registeredClientRepository;
private static OAuth2AuthorizationService authorizationService;
private static CryptoKeySource keySource;
@Rule
public final SpringTestRule spring = new SpringTestRule();
@@ -78,6 +79,7 @@ public class OAuth2RefreshTokenGrantTests {
public static void init() {
registeredClientRepository = mock(RegisteredClientRepository.class);
authorizationService = mock(OAuth2AuthorizationService.class);
keySource = new StaticKeyGeneratingCryptoKeySource();
}
@Before
@@ -151,6 +153,8 @@ public class OAuth2RefreshTokenGrantTests {
}
@Bean
KeyManager keyManager() { return new StaticKeyGeneratingKeyManager(); }
CryptoKeySource keySource() {
return keySource;
}
}
}

View File

@@ -27,8 +27,8 @@ import org.springframework.http.HttpHeaders;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
@@ -66,7 +66,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class OAuth2TokenRevocationTests {
private static RegisteredClientRepository registeredClientRepository;
private static OAuth2AuthorizationService authorizationService;
private static KeyManager keyManager;
private static CryptoKeySource keySource;
@Rule
public final SpringTestRule spring = new SpringTestRule();
@@ -78,7 +78,7 @@ public class OAuth2TokenRevocationTests {
public static void init() {
registeredClientRepository = mock(RegisteredClientRepository.class);
authorizationService = mock(OAuth2AuthorizationService.class);
keyManager = new StaticKeyGeneratingKeyManager();
keySource = new StaticKeyGeneratingCryptoKeySource();
}
@Before
@@ -181,8 +181,8 @@ public class OAuth2TokenRevocationTests {
}
@Bean
KeyManager keyManager() {
return keyManager;
CryptoKeySource keySource() {
return keySource;
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.crypto.key;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.crypto.SecretKey;
import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.security.crypto.key.KeyGeneratorUtils.generateRsaKey;
import static org.springframework.security.crypto.key.KeyGeneratorUtils.generateSecretKey;
/**
* Tests for {@link CryptoKey}.
*
* @author Joe Grandja
*/
public class CryptoKeyTests {
private static SecretKey secretKey;
private static KeyPair rsaKeyPair;
@BeforeClass
public static void init() {
secretKey = generateSecretKey();
rsaKeyPair = generateRsaKey();
}
@Test
public void symmetricWhenSecretKeyNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> CryptoKey.symmetric(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("key cannot be null");
}
@Test
public void metadataWhenNameNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> CryptoKey.symmetric(secretKey).metadata(null, "value"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("name cannot be empty");
}
@Test
public void metadataWhenValueNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> CryptoKey.symmetric(secretKey).metadata("name", null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("value cannot be null");
}
@Test
public void symmetricWhenAllAttributesProvidedThenAllAttributesAreSet() {
Map<String, Object> keyMetadata = new HashMap<>();
keyMetadata.put("name1", "value1");
keyMetadata.put("name2", "value2");
SymmetricKey symmetricKey = CryptoKey.symmetric(secretKey)
.id("id")
.metadata(metadata -> metadata.putAll(keyMetadata))
.build();
assertThat(symmetricKey.getKey()).isEqualTo(secretKey);
assertThat(symmetricKey.getId()).isEqualTo("id");
assertThat(symmetricKey.getMetadata()).isEqualTo(keyMetadata);
}
@Test
public void asymmetricWhenPrivateKeyNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> CryptoKey.asymmetric(null, rsaKeyPair.getPublic()))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("key cannot be null");
}
@Test
public void asymmetricWhenPublicKeyNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> CryptoKey.asymmetric(rsaKeyPair.getPrivate(), null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("publicKey cannot be null");
}
@Test
public void asymmetricWhenAllAttributesProvidedThenAllAttributesAreSet() {
Map<String, Object> keyMetadata = new HashMap<>();
keyMetadata.put("name1", "value1");
keyMetadata.put("name2", "value2");
AsymmetricKey asymmetricKey = CryptoKey.asymmetric(rsaKeyPair.getPrivate(), rsaKeyPair.getPublic())
.id("id")
.metadata(metadata -> metadata.putAll(keyMetadata))
.build();
assertThat(asymmetricKey.getKey()).isEqualTo(rsaKeyPair.getPrivate());
assertThat(asymmetricKey.getPublicKey()).isEqualTo(rsaKeyPair.getPublic());
assertThat(asymmetricKey.getId()).isEqualTo("id");
assertThat(asymmetricKey.getMetadata()).isEqualTo(keyMetadata);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.crypto.key;
import java.security.KeyPair;
import static org.springframework.security.crypto.key.KeyGeneratorUtils.generateEcKey;
import static org.springframework.security.crypto.key.KeyGeneratorUtils.generateRsaKey;
import static org.springframework.security.crypto.key.KeyGeneratorUtils.generateSecretKey;
/**
* @author Joe Grandja
*/
public class TestCryptoKeys {
public static SymmetricKey.Builder secretKey() {
return CryptoKey.symmetric(generateSecretKey());
}
public static AsymmetricKey.Builder rsaKey() {
KeyPair rsaKeyPair = generateRsaKey();
return CryptoKey.asymmetric(rsaKeyPair.getPrivate(), rsaKeyPair.getPublic());
}
public static AsymmetricKey.Builder ecKey() {
KeyPair ecKeyPair = generateEcKey();
return CryptoKey.asymmetric(ecKeyPair.getPrivate(), ecKeyPair.getPublic());
}
}

View File

@@ -1,120 +0,0 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.crypto.keys;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.crypto.SecretKey;
import java.security.Key;
import java.security.KeyPair;
import java.security.PrivateKey;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.security.crypto.keys.KeyGeneratorUtils.generateRsaKey;
import static org.springframework.security.crypto.keys.KeyGeneratorUtils.generateSecretKey;
/**
* Tests for {@link ManagedKey}.
*
* @author Joe Grandja
*/
public class ManagedKeyTests {
private static SecretKey secretKey;
private static KeyPair rsaKeyPair;
@BeforeClass
public static void init() {
secretKey = generateSecretKey();
rsaKeyPair = generateRsaKey();
}
@Test
public void withSymmetricKeyWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> ManagedKey.withSymmetricKey(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("secretKey cannot be null");
}
@Test
public void buildWhenKeyIdNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> ManagedKey.withSymmetricKey(secretKey).build())
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("keyId cannot be empty");
}
@Test
public void buildWhenActivatedOnNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> ManagedKey.withSymmetricKey(secretKey).keyId("keyId").build())
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("activatedOn cannot be null");
}
@Test
public void buildWhenSymmetricKeyAllAttributesProvidedThenAllAttributesAreSet() {
ManagedKey expectedManagedKey = TestManagedKeys.secretManagedKey().build();
ManagedKey managedKey = ManagedKey.withSymmetricKey(expectedManagedKey.getKey())
.keyId(expectedManagedKey.getKeyId())
.activatedOn(expectedManagedKey.getActivatedOn())
.build();
assertThat(managedKey.isSymmetric()).isTrue();
assertThat(managedKey.<Key>getKey()).isInstanceOf(SecretKey.class);
assertThat(managedKey.<SecretKey>getKey()).isEqualTo(expectedManagedKey.getKey());
assertThat(managedKey.getPublicKey()).isNull();
assertThat(managedKey.getKeyId()).isEqualTo(expectedManagedKey.getKeyId());
assertThat(managedKey.getActivatedOn()).isEqualTo(expectedManagedKey.getActivatedOn());
assertThat(managedKey.getDeactivatedOn()).isEqualTo(expectedManagedKey.getDeactivatedOn());
assertThat(managedKey.isActive()).isTrue();
assertThat(managedKey.getAlgorithm()).isEqualTo(expectedManagedKey.getAlgorithm());
}
@Test
public void withAsymmetricKeyWhenPublicKeyNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> ManagedKey.withAsymmetricKey(null, rsaKeyPair.getPrivate()))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("publicKey cannot be null");
}
@Test
public void withAsymmetricKeyWhenPrivateKeyNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> ManagedKey.withAsymmetricKey(rsaKeyPair.getPublic(), null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("privateKey cannot be null");
}
@Test
public void buildWhenAsymmetricKeyAllAttributesProvidedThenAllAttributesAreSet() {
ManagedKey expectedManagedKey = TestManagedKeys.rsaManagedKey().build();
ManagedKey managedKey = ManagedKey.withAsymmetricKey(expectedManagedKey.getPublicKey(), expectedManagedKey.getKey())
.keyId(expectedManagedKey.getKeyId())
.activatedOn(expectedManagedKey.getActivatedOn())
.build();
assertThat(managedKey.isAsymmetric()).isTrue();
assertThat(managedKey.<Key>getKey()).isInstanceOf(PrivateKey.class);
assertThat(managedKey.<PrivateKey>getKey()).isEqualTo(expectedManagedKey.getKey());
assertThat(managedKey.getPublicKey()).isNotNull();
assertThat(managedKey.getKeyId()).isEqualTo(expectedManagedKey.getKeyId());
assertThat(managedKey.getActivatedOn()).isEqualTo(expectedManagedKey.getActivatedOn());
assertThat(managedKey.getDeactivatedOn()).isEqualTo(expectedManagedKey.getDeactivatedOn());
assertThat(managedKey.isActive()).isTrue();
assertThat(managedKey.getAlgorithm()).isEqualTo(expectedManagedKey.getAlgorithm());
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.crypto.keys;
import java.security.KeyPair;
import java.time.Instant;
import java.util.UUID;
import static org.springframework.security.crypto.keys.KeyGeneratorUtils.generateEcKey;
import static org.springframework.security.crypto.keys.KeyGeneratorUtils.generateRsaKey;
import static org.springframework.security.crypto.keys.KeyGeneratorUtils.generateSecretKey;
/**
* @author Joe Grandja
*/
public class TestManagedKeys {
public static ManagedKey.Builder secretManagedKey() {
return ManagedKey.withSymmetricKey(generateSecretKey())
.keyId(UUID.randomUUID().toString())
.activatedOn(Instant.now());
}
public static ManagedKey.Builder rsaManagedKey() {
KeyPair rsaKeyPair = generateRsaKey();
return ManagedKey.withAsymmetricKey(rsaKeyPair.getPublic(), rsaKeyPair.getPrivate())
.keyId(UUID.randomUUID().toString())
.activatedOn(Instant.now());
}
public static ManagedKey.Builder ecManagedKey() {
KeyPair ecKeyPair = generateEcKey();
return ManagedKey.withAsymmetricKey(ecKeyPair.getPublic(), ecKeyPair.getPrivate())
.keyId(UUID.randomUUID().toString())
.activatedOn(Instant.now());
}
}

View File

@@ -17,9 +17,9 @@ package org.springframework.security.oauth2.jose.jws;
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.ManagedKey;
import org.springframework.security.crypto.keys.TestManagedKeys;
import org.springframework.security.crypto.key.AsymmetricKey;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.TestCryptoKeys;
import org.springframework.security.oauth2.jose.JoseHeader;
import org.springframework.security.oauth2.jose.JoseHeaderNames;
import org.springframework.security.oauth2.jose.TestJoseHeaders;
@@ -30,14 +30,12 @@ import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -47,20 +45,20 @@ import static org.mockito.Mockito.when;
* @author Joe Grandja
*/
public class NimbusJwsEncoderTests {
private KeyManager keyManager;
private CryptoKeySource keySource;
private NimbusJwsEncoder jwtEncoder;
@Before
public void setUp() {
this.keyManager = mock(KeyManager.class);
this.jwtEncoder = new NimbusJwsEncoder(this.keyManager);
this.keySource = mock(CryptoKeySource.class);
this.jwtEncoder = new NimbusJwsEncoder(this.keySource);
}
@Test
public void constructorWhenKeyManagerNullThenThrowIllegalArgumentException() {
public void constructorWhenKeySourceNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new NimbusJwsEncoder(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("keyManager cannot be null");
.hasMessage("keySource cannot be null");
}
@Test
@@ -103,8 +101,8 @@ public class NimbusJwsEncoderTests {
@Test
public void encodeWhenUnsupportedKeyTypeThenThrowJwtEncodingException() {
ManagedKey managedKey = TestManagedKeys.ecManagedKey().build();
when(this.keyManager.findByAlgorithm(any())).thenReturn(Collections.singleton(managedKey));
AsymmetricKey ecKey = TestCryptoKeys.ecKey().build();
when(this.keySource.getKeys()).thenReturn(Collections.singleton(ecKey));
JoseHeader joseHeader = TestJoseHeaders.joseHeader(SignatureAlgorithm.ES256).build();
JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
@@ -116,8 +114,8 @@ public class NimbusJwsEncoderTests {
@Test
public void encodeWhenSuccessThenDecodes() {
ManagedKey managedKey = TestManagedKeys.rsaManagedKey().build();
when(this.keyManager.findByAlgorithm(any())).thenReturn(Collections.singleton(managedKey));
AsymmetricKey rsaKey = TestCryptoKeys.rsaKey().build();
when(this.keySource.getKeys()).thenReturn(Collections.singleton(rsaKey));
JoseHeader joseHeader = TestJoseHeaders.joseHeader()
.headers(headers -> headers.remove(JoseHeaderNames.CRIT))
@@ -126,25 +124,17 @@ public class NimbusJwsEncoderTests {
Jwt jws = this.jwtEncoder.encode(joseHeader, jwtClaimsSet);
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey((RSAPublicKey) managedKey.getPublicKey()).build();
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey((RSAPublicKey) rsaKey.getPublicKey()).build();
jwtDecoder.decode(jws.getTokenValue());
}
@Test
public void encodeWhenMultipleActiveKeysThenUseMostRecent() {
ManagedKey managedKeyActivated2DaysAgo = TestManagedKeys.rsaManagedKey()
.activatedOn(Instant.now().minus(2, ChronoUnit.DAYS))
.build();
ManagedKey managedKeyActivated1DayAgo = TestManagedKeys.rsaManagedKey()
.activatedOn(Instant.now().minus(1, ChronoUnit.DAYS))
.build();
ManagedKey managedKeyActivatedToday = TestManagedKeys.rsaManagedKey()
.activatedOn(Instant.now())
.build();
when(this.keyManager.findByAlgorithm(any())).thenReturn(
Stream.of(managedKeyActivated2DaysAgo, managedKeyActivated1DayAgo, managedKeyActivatedToday)
.collect(Collectors.toSet()));
public void encodeWhenMultipleActiveKeysThenUseFirst() {
AsymmetricKey rsaKey1 = TestCryptoKeys.rsaKey().build();
AsymmetricKey rsaKey2 = TestCryptoKeys.rsaKey().build();
when(this.keySource.getKeys()).thenReturn(
Stream.of(rsaKey1, rsaKey2)
.collect(Collectors.toCollection(LinkedHashSet::new)));
JoseHeader joseHeader = TestJoseHeaders.joseHeader()
.headers(headers -> headers.remove(JoseHeaderNames.CRIT))
@@ -153,7 +143,7 @@ public class NimbusJwsEncoderTests {
Jwt jws = this.jwtEncoder.encode(joseHeader, jwtClaimsSet);
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey((RSAPublicKey) managedKeyActivatedToday.getPublicKey()).build();
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey((RSAPublicKey) rsaKey1.getPublicKey()).build();
jwtDecoder.decode(jws.getTokenValue());
}
}

View File

@@ -25,14 +25,14 @@ import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.crypto.keys.KeyManager;
import org.springframework.security.crypto.keys.ManagedKey;
import org.springframework.security.crypto.keys.TestManagedKeys;
import org.springframework.security.crypto.key.AsymmetricKey;
import org.springframework.security.crypto.key.CryptoKeySource;
import org.springframework.security.crypto.key.SymmetricKey;
import org.springframework.security.crypto.key.TestCryptoKeys;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.util.Collections;
import java.util.HashSet;
import java.util.stream.Collectors;
@@ -52,25 +52,25 @@ import static org.mockito.Mockito.when;
* @author Joe Grandja
*/
public class JwkSetEndpointFilterTests {
private KeyManager keyManager;
private CryptoKeySource keySource;
private JwkSetEndpointFilter filter;
@Before
public void setUp() {
this.keyManager = mock(KeyManager.class);
this.filter = new JwkSetEndpointFilter(this.keyManager);
this.keySource = mock(CryptoKeySource.class);
this.filter = new JwkSetEndpointFilter(this.keySource);
}
@Test
public void constructorWhenKeyManagerNullThenThrowIllegalArgumentException() {
public void constructorWhenKeySourceNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new JwkSetEndpointFilter(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("keyManager cannot be null");
.hasMessage("keySource cannot be null");
}
@Test
public void constructorWhenJwkSetEndpointUriNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new JwkSetEndpointFilter(this.keyManager, null))
assertThatThrownBy(() -> new JwkSetEndpointFilter(this.keySource, null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("jwkSetEndpointUri cannot be empty");
}
@@ -103,10 +103,10 @@ public class JwkSetEndpointFilterTests {
@Test
public void doFilterWhenAsymmetricKeysThenJwkSetResponse() throws Exception {
ManagedKey rsaManagedKey = TestManagedKeys.rsaManagedKey().build();
ManagedKey ecManagedKey = TestManagedKeys.ecManagedKey().build();
when(this.keyManager.getKeys()).thenReturn(
Stream.of(rsaManagedKey, ecManagedKey).collect(Collectors.toSet()));
AsymmetricKey rsaKey = TestCryptoKeys.rsaKey().build();
AsymmetricKey ecKey = TestCryptoKeys.ecKey().build();
when(this.keySource.getKeys()).thenReturn(
Stream.of(rsaKey, ecKey).collect(Collectors.toSet()));
String requestUri = JwkSetEndpointFilter.DEFAULT_JWK_SET_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -123,17 +123,17 @@ public class JwkSetEndpointFilterTests {
JWKSet jwkSet = JWKSet.parse(response.getContentAsString());
assertThat(jwkSet.getKeys()).hasSize(2);
RSAKey rsaJwk = (RSAKey) jwkSet.getKeyByKeyId(rsaManagedKey.getKeyId());
RSAKey rsaJwk = (RSAKey) jwkSet.getKeyByKeyId(rsaKey.getId());
assertThat(rsaJwk).isNotNull();
assertThat(rsaJwk.toRSAPublicKey()).isEqualTo(rsaManagedKey.getPublicKey());
assertThat(rsaJwk.toRSAPublicKey()).isEqualTo(rsaKey.getPublicKey());
assertThat(rsaJwk.toRSAPrivateKey()).isNull();
assertThat(rsaJwk.getKeyUse()).isEqualTo(KeyUse.SIGNATURE);
assertThat(rsaJwk.getAlgorithm()).isEqualTo(JWSAlgorithm.RS256);
ECKey ecJwk = (ECKey) jwkSet.getKeyByKeyId(ecManagedKey.getKeyId());
ECKey ecJwk = (ECKey) jwkSet.getKeyByKeyId(ecKey.getId());
assertThat(ecJwk).isNotNull();
assertThat(ecJwk.toECPublicKey()).isEqualTo(ecManagedKey.getPublicKey());
assertThat(ecJwk.toECPublicKey()).isEqualTo(ecManagedKey.getPublicKey());
assertThat(ecJwk.toECPublicKey()).isEqualTo(ecKey.getPublicKey());
assertThat(ecJwk.toECPublicKey()).isEqualTo(ecKey.getPublicKey());
assertThat(ecJwk.toECPrivateKey()).isNull();
assertThat(ecJwk.getKeyUse()).isEqualTo(KeyUse.SIGNATURE);
assertThat(ecJwk.getAlgorithm()).isEqualTo(JWSAlgorithm.ES256);
@@ -141,32 +141,9 @@ public class JwkSetEndpointFilterTests {
@Test
public void doFilterWhenSymmetricKeysThenJwkSetResponseEmpty() throws Exception {
ManagedKey secretManagedKey = TestManagedKeys.secretManagedKey().build();
when(this.keyManager.getKeys()).thenReturn(
new HashSet<>(Collections.singleton(secretManagedKey)));
String requestUri = JwkSetEndpointFilter.DEFAULT_JWK_SET_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
request.setServletPath(requestUri);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
this.filter.doFilter(request, response, filterChain);
verifyNoInteractions(filterChain);
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
JWKSet jwkSet = JWKSet.parse(response.getContentAsString());
assertThat(jwkSet.getKeys()).isEmpty();
}
@Test
public void doFilterWhenNoActiveKeysThenJwkSetResponseEmpty() throws Exception {
ManagedKey rsaManagedKey = TestManagedKeys.rsaManagedKey().deactivatedOn(Instant.now()).build();
ManagedKey ecManagedKey = TestManagedKeys.ecManagedKey().deactivatedOn(Instant.now()).build();
when(this.keyManager.getKeys()).thenReturn(
Stream.of(rsaManagedKey, ecManagedKey).collect(Collectors.toSet()));
SymmetricKey secretKey = TestCryptoKeys.secretKey().build();
when(this.keySource.getKeys()).thenReturn(
new HashSet<>(Collections.singleton(secretKey)));
String requestUri = JwkSetEndpointFilter.DEFAULT_JWK_SET_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);