Skip to content

Commit 0e6b512

Browse files
committed
Provided uncached way to use OidcIdTokenDecoderFactory
Signed-off-by: iigolovko <[email protected]>
1 parent eb5252c commit 0e6b512

File tree

4 files changed

+104
-22
lines changed

4 files changed

+104
-22
lines changed

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
* @author Joe Grandja
5959
* @author Rafael Dominguez
6060
* @author Mark Heckler
61+
* @author Ivan Golovko
6162
* @since 5.2
6263
* @see JwtDecoderFactory
6364
* @see ClientRegistration
@@ -78,7 +79,7 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<Client
7879

7980
private static final ClaimTypeConverter DEFAULT_CLAIM_TYPE_CONVERTER = createDefaultClaimTypeConverter();
8081

81-
private final Map<String, JwtDecoder> jwtDecoders = new ConcurrentHashMap<>();
82+
private final Map<String, JwtDecoder> jwtDecoders;
8283

8384
private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> jwtValidatorFactory = new DefaultOidcIdTokenValidatorFactory();
8485

@@ -88,6 +89,19 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<Client
8889
private Function<ClientRegistration, Converter<Map<String, Object>, Map<String, Object>>> claimTypeConverterFactory = (
8990
clientRegistration) -> DEFAULT_CLAIM_TYPE_CONVERTER;
9091

92+
public OidcIdTokenDecoderFactory() {
93+
this(true);
94+
}
95+
96+
public OidcIdTokenDecoderFactory(boolean withCache) {
97+
if (withCache) {
98+
this.jwtDecoders = new ConcurrentHashMap<>();
99+
}
100+
else {
101+
this.jwtDecoders = null;
102+
}
103+
}
104+
91105
/**
92106
* Returns the default {@link Converter}'s used for type conversion of claim values
93107
* for an {@link OidcIdToken}.
@@ -135,16 +149,24 @@ public static ClaimTypeConverter createDefaultClaimTypeConverter() {
135149
@Override
136150
public JwtDecoder createDecoder(ClientRegistration clientRegistration) {
137151
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
138-
return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(), (key) -> {
139-
NimbusJwtDecoder jwtDecoder = buildDecoder(clientRegistration);
140-
jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration));
141-
Converter<Map<String, Object>, Map<String, Object>> claimTypeConverter = this.claimTypeConverterFactory
142-
.apply(clientRegistration);
143-
if (claimTypeConverter != null) {
144-
jwtDecoder.setClaimSetConverter(claimTypeConverter);
145-
}
146-
return jwtDecoder;
147-
});
152+
if (this.jwtDecoders != null) {
153+
return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(),
154+
(key) -> createFreshDecoder(clientRegistration));
155+
}
156+
else {
157+
return createFreshDecoder(clientRegistration);
158+
}
159+
}
160+
161+
private JwtDecoder createFreshDecoder(ClientRegistration clientRegistration) {
162+
NimbusJwtDecoder jwtDecoder = buildDecoder(clientRegistration);
163+
jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration));
164+
Converter<Map<String, Object>, Map<String, Object>> claimTypeConverter = this.claimTypeConverterFactory
165+
.apply(clientRegistration);
166+
if (claimTypeConverter != null) {
167+
jwtDecoder.setClaimSetConverter(claimTypeConverter);
168+
}
169+
return jwtDecoder;
148170
}
149171

150172
private NimbusJwtDecoder buildDecoder(ClientRegistration clientRegistration) {

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
* @author Rafael Dominguez
6060
* @author Mark Heckler
6161
* @author Ubaid ur Rehman
62+
* @author Ivan Golovko
6263
* @since 5.2
6364
* @see ReactiveJwtDecoderFactory
6465
* @see ClientRegistration
@@ -80,7 +81,7 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod
8081
private static final ClaimTypeConverter DEFAULT_CLAIM_TYPE_CONVERTER = new ClaimTypeConverter(
8182
createDefaultClaimTypeConverters());
8283

83-
private final Map<String, ReactiveJwtDecoder> jwtDecoders = new ConcurrentHashMap<>();
84+
private final Map<String, ReactiveJwtDecoder> jwtDecoders;
8485

8586
private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> jwtValidatorFactory = new DefaultOidcIdTokenValidatorFactory();
8687

@@ -90,6 +91,19 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod
9091
private Function<ClientRegistration, Converter<Map<String, Object>, Map<String, Object>>> claimTypeConverterFactory = (
9192
clientRegistration) -> DEFAULT_CLAIM_TYPE_CONVERTER;
9293

94+
public ReactiveOidcIdTokenDecoderFactory() {
95+
this(true);
96+
}
97+
98+
public ReactiveOidcIdTokenDecoderFactory(boolean withCache) {
99+
if (withCache) {
100+
this.jwtDecoders = new ConcurrentHashMap<>();
101+
}
102+
else {
103+
this.jwtDecoders = null;
104+
}
105+
}
106+
93107
/**
94108
* Returns the default {@link Converter}'s used for type conversion of claim values
95109
* for an {@link OidcIdToken}.
@@ -126,16 +140,24 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod
126140
@Override
127141
public ReactiveJwtDecoder createDecoder(ClientRegistration clientRegistration) {
128142
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
129-
return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(), (key) -> {
130-
NimbusReactiveJwtDecoder jwtDecoder = buildDecoder(clientRegistration);
131-
jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration));
132-
Converter<Map<String, Object>, Map<String, Object>> claimTypeConverter = this.claimTypeConverterFactory
133-
.apply(clientRegistration);
134-
if (claimTypeConverter != null) {
135-
jwtDecoder.setClaimSetConverter(claimTypeConverter);
136-
}
137-
return jwtDecoder;
138-
});
143+
if (this.jwtDecoders != null) {
144+
return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(),
145+
(key) -> createFreshDecoder(clientRegistration));
146+
}
147+
else {
148+
return createFreshDecoder(clientRegistration);
149+
}
150+
}
151+
152+
private ReactiveJwtDecoder createFreshDecoder(ClientRegistration clientRegistration) {
153+
NimbusReactiveJwtDecoder jwtDecoder = buildDecoder(clientRegistration);
154+
jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration));
155+
Converter<Map<String, Object>, Map<String, Object>> claimTypeConverter = this.claimTypeConverterFactory
156+
.apply(clientRegistration);
157+
if (claimTypeConverter != null) {
158+
jwtDecoder.setClaimSetConverter(claimTypeConverter);
159+
}
160+
return jwtDecoder;
139161
}
140162

141163
private NimbusReactiveJwtDecoder buildDecoder(ClientRegistration clientRegistration) {

oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
3535
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
3636
import org.springframework.security.oauth2.jwt.Jwt;
37+
import org.springframework.security.oauth2.jwt.JwtDecoder;
3738

3839
import static org.assertj.core.api.Assertions.assertThat;
3940
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -46,6 +47,7 @@
4647
/**
4748
* @author Joe Grandja
4849
* @author Rafael Dominguez
50+
* @author Ivan Golovko
4951
* @since 5.2
5052
*/
5153
public class OidcIdTokenDecoderFactoryTests {
@@ -177,4 +179,21 @@ public void createDecoderWhenCustomClaimTypeConverterFactorySetThenApplied() {
177179
verify(customClaimTypeConverterFactory).apply(same(clientRegistration));
178180
}
179181

182+
@Test
183+
public void createDecoderTwiceWithCaching() {
184+
ClientRegistration clientRegistration = this.registration.build();
185+
JwtDecoder decoder1 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
186+
JwtDecoder decoder2 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
187+
assertThat(decoder1).isSameAs(decoder2);
188+
}
189+
190+
@Test
191+
public void createDecoderTwiceWithoutCaching() {
192+
this.idTokenDecoderFactory = new OidcIdTokenDecoderFactory(false);
193+
ClientRegistration clientRegistration = this.registration.build();
194+
JwtDecoder decoder1 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
195+
JwtDecoder decoder2 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
196+
assertThat(decoder1).isNotSameAs(decoder2);
197+
}
198+
180199
}

oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
3535
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
3636
import org.springframework.security.oauth2.jwt.Jwt;
37+
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
3738

3839
import static org.assertj.core.api.Assertions.assertThat;
3940
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -47,6 +48,7 @@
4748
* @author Joe Grandja
4849
* @author Rafael Dominguez
4950
* @author Ubaid ur Rehman
51+
* @author Ivan Golovko
5052
* @since 5.2
5153
*/
5254
public class ReactiveOidcIdTokenDecoderFactoryTests {
@@ -177,4 +179,21 @@ public void createDecoderWhenCustomClaimTypeConverterFactorySetThenApplied() {
177179
verify(customClaimTypeConverterFactory).apply(same(clientRegistration));
178180
}
179181

182+
@Test
183+
public void createDecoderTwiceWithCaching() {
184+
ClientRegistration clientRegistration = this.registration.build();
185+
ReactiveJwtDecoder decoder1 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
186+
ReactiveJwtDecoder decoder2 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
187+
assertThat(decoder1).isSameAs(decoder2);
188+
}
189+
190+
@Test
191+
public void createDecoderTwiceWithoutCaching() {
192+
this.idTokenDecoderFactory = new ReactiveOidcIdTokenDecoderFactory(false);
193+
ClientRegistration clientRegistration = this.registration.build();
194+
ReactiveJwtDecoder decoder1 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
195+
ReactiveJwtDecoder decoder2 = this.idTokenDecoderFactory.createDecoder(clientRegistration);
196+
assertThat(decoder1).isNotSameAs(decoder2);
197+
}
198+
180199
}

0 commit comments

Comments
 (0)