Skip to content

Commit 94ad641

Browse files
Max BatischevMax Batischev
authored andcommitted
Simplification of creation of OAuth2TokenValidator with JwtValidators defaults.
Closes gh-14831
1 parent e771267 commit 94ad641

File tree

5 files changed

+129
-18
lines changed

5 files changed

+129
-18
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/DefaultOidcLogoutTokenValidatorFactory.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,17 +19,15 @@
1919
import java.util.function.Function;
2020

2121
import org.springframework.security.oauth2.client.registration.ClientRegistration;
22-
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
2322
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
2423
import org.springframework.security.oauth2.jwt.Jwt;
25-
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
24+
import org.springframework.security.oauth2.jwt.JwtValidators;
2625

2726
final class DefaultOidcLogoutTokenValidatorFactory implements Function<ClientRegistration, OAuth2TokenValidator<Jwt>> {
2827

2928
@Override
3029
public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
31-
return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(),
32-
new OidcBackChannelLogoutTokenValidator(clientRegistration));
30+
return JwtValidators.createDefaultWithValidators(new OidcBackChannelLogoutTokenValidator(clientRegistration));
3331
}
3432

3533
}

config/src/main/java/org/springframework/security/config/web/server/DefaultOidcLogoutTokenValidatorFactory.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,17 +19,15 @@
1919
import java.util.function.Function;
2020

2121
import org.springframework.security.oauth2.client.registration.ClientRegistration;
22-
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
2322
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
2423
import org.springframework.security.oauth2.jwt.Jwt;
25-
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
24+
import org.springframework.security.oauth2.jwt.JwtValidators;
2625

2726
final class DefaultOidcLogoutTokenValidatorFactory implements Function<ClientRegistration, OAuth2TokenValidator<Jwt>> {
2827

2928
@Override
3029
public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
31-
return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(),
32-
new OidcBackChannelLogoutTokenValidator(clientRegistration));
30+
return JwtValidators.createDefaultWithValidators(new OidcBackChannelLogoutTokenValidator(clientRegistration));
3331
}
3432

3533
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/DefaultOidcIdTokenValidatorFactory.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,21 +19,19 @@
1919
import java.util.function.Function;
2020

2121
import org.springframework.security.oauth2.client.registration.ClientRegistration;
22-
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
2322
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
2423
import org.springframework.security.oauth2.jwt.Jwt;
25-
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
24+
import org.springframework.security.oauth2.jwt.JwtValidators;
2625

2726
/**
2827
* @author Joe Grandja
29-
* @since 5.2
28+
* @since 6.3
3029
*/
3130
class DefaultOidcIdTokenValidatorFactory implements Function<ClientRegistration, OAuth2TokenValidator<Jwt>> {
3231

3332
@Override
3433
public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
35-
return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(),
36-
new OidcIdTokenValidator(clientRegistration));
34+
return JwtValidators.createDefaultWithValidators(new OidcIdTokenValidator(clientRegistration));
3735
}
3836

3937
}

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidators.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,13 +22,15 @@
2222

2323
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
2424
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
25+
import org.springframework.util.Assert;
26+
import org.springframework.util.CollectionUtils;
2527

2628
/**
2729
* Provides factory methods for creating {@code OAuth2TokenValidator<Jwt>}
2830
*
2931
* @author Josh Cummings
3032
* @author Rob Winch
31-
* @since 5.1
33+
* @since 6.3
3234
*/
3335
public final class JwtValidators {
3436

@@ -72,4 +74,39 @@ public static OAuth2TokenValidator<Jwt> createDefault() {
7274
return new DelegatingOAuth2TokenValidator<>(Arrays.asList(new JwtTimestampValidator()));
7375
}
7476

77+
/**
78+
* <p>
79+
* Create a {@link Jwt} default validator with standard validators and additional
80+
* validators.
81+
* </p>
82+
* @param validators additional validators
83+
* @return - a delegating validator containing all standard validators with additional
84+
* validators
85+
*/
86+
public static OAuth2TokenValidator<Jwt> createDefaultWithValidators(List<OAuth2TokenValidator<Jwt>> validators) {
87+
Assert.notEmpty(validators, "validators cannot be null or empty");
88+
List<OAuth2TokenValidator<Jwt>> tokenValidators = new ArrayList<>(validators);
89+
JwtTimestampValidator jwtTimestampValidator = CollectionUtils.findValueOfType(tokenValidators,
90+
JwtTimestampValidator.class);
91+
if (jwtTimestampValidator == null) {
92+
tokenValidators.add(new JwtTimestampValidator());
93+
}
94+
return new DelegatingOAuth2TokenValidator<>(tokenValidators);
95+
}
96+
97+
/**
98+
* <p>
99+
* Create a {@link Jwt} default validator with standard validators and additional
100+
* validators.
101+
* </p>
102+
* @param validators additional validators
103+
* @return - a delegating validator containing all standard validators with additional
104+
* validators
105+
*/
106+
public static OAuth2TokenValidator<Jwt> createDefaultWithValidators(OAuth2TokenValidator<Jwt>... validators) {
107+
Assert.notEmpty(validators, "validators cannot be null or empty");
108+
List<OAuth2TokenValidator<Jwt>> tokenValidators = new ArrayList<>(Arrays.asList(validators));
109+
return createDefaultWithValidators(tokenValidators);
110+
}
111+
75112
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.oauth2.jwt;
18+
19+
import java.util.Collection;
20+
import java.util.Collections;
21+
import java.util.Objects;
22+
23+
import org.junit.jupiter.api.Test;
24+
25+
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
26+
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
27+
import org.springframework.test.util.ReflectionTestUtils;
28+
import org.springframework.util.CollectionUtils;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.assertj.core.api.Assertions.assertThatException;
32+
33+
/**
34+
* Tests for {@link JwtValidators}.
35+
*
36+
* @author Max Batischev
37+
*/
38+
public class JwtValidatorsTests {
39+
40+
private static final String ISS_CLAIM = "iss";
41+
42+
@Test
43+
public void createWhenJwtIssuerValidatorIsPresentThenCreateDefaultValidatorWithJwtIssuerValidator() {
44+
OAuth2TokenValidator<Jwt> validator = JwtValidators
45+
.createDefaultWithValidators(new JwtIssuerValidator(ISS_CLAIM));
46+
47+
assertThat(containsByType(validator, JwtIssuerValidator.class)).isTrue();
48+
assertThat(containsByType(validator, JwtTimestampValidator.class)).isTrue();
49+
}
50+
51+
@Test
52+
@SuppressWarnings("unchecked")
53+
public void createWhenJwtTimestampValidatorIsPresentThenCreateDefaultValidatorWithOnlyOneJwtTimestampValidator() {
54+
OAuth2TokenValidator<Jwt> validator = JwtValidators.createDefaultWithValidators(new JwtTimestampValidator());
55+
56+
DelegatingOAuth2TokenValidator<Jwt> delegatingOAuth2TokenValidator = (DelegatingOAuth2TokenValidator<Jwt>) validator;
57+
Collection<OAuth2TokenValidator<Jwt>> tokenValidators = (Collection<OAuth2TokenValidator<Jwt>>) ReflectionTestUtils
58+
.getField(delegatingOAuth2TokenValidator, "tokenValidators");
59+
60+
assertThat(containsByType(validator, JwtTimestampValidator.class)).isTrue();
61+
assertThat(Objects.requireNonNull(tokenValidators).size()).isEqualTo(1);
62+
}
63+
64+
@Test
65+
public void createWhenEmptyValidatorsThenThrowsException() {
66+
assertThatException().isThrownBy(() -> JwtValidators.createDefaultWithValidators(Collections.emptyList()));
67+
}
68+
69+
@SuppressWarnings("unchecked")
70+
private boolean containsByType(OAuth2TokenValidator<Jwt> validator, Class<? extends OAuth2TokenValidator<?>> type) {
71+
DelegatingOAuth2TokenValidator<Jwt> delegatingOAuth2TokenValidator = (DelegatingOAuth2TokenValidator<Jwt>) validator;
72+
Collection<OAuth2TokenValidator<Jwt>> tokenValidators = (Collection<OAuth2TokenValidator<Jwt>>) ReflectionTestUtils
73+
.getField(delegatingOAuth2TokenValidator, "tokenValidators");
74+
75+
OAuth2TokenValidator<?> tokenValidator = CollectionUtils
76+
.findValueOfType(Objects.requireNonNull(tokenValidators), type);
77+
return tokenValidator != null;
78+
}
79+
80+
}

0 commit comments

Comments
 (0)