Skip to content

Commit 5f7155b

Browse files
committed
Implement internal cache in JtiClaimValidator
Closes gh-17107
1 parent a265ac6 commit 5f7155b

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818

1919
import java.nio.charset.StandardCharsets;
2020
import java.security.MessageDigest;
21-
import java.time.Clock;
2221
import java.time.Instant;
22+
import java.time.temporal.ChronoUnit;
2323
import java.util.Base64;
2424
import java.util.Collections;
25+
import java.util.LinkedHashMap;
2526
import java.util.Map;
26-
import java.util.concurrent.ConcurrentHashMap;
2727
import java.util.function.Function;
2828

2929
import com.nimbusds.jose.JOSEException;
@@ -146,7 +146,7 @@ private static Function<DPoPProofContext, OAuth2TokenValidator<Jwt>> defaultJwtV
146146

147147
private static final class JtiClaimValidator implements OAuth2TokenValidator<Jwt> {
148148

149-
private static final Map<String, Long> jtiCache = new ConcurrentHashMap<>();
149+
private static final Map<String, Long> JTI_CACHE = Collections.synchronizedMap(new JtiCache());
150150

151151
@Override
152152
public OAuth2TokenValidatorResult validate(Jwt jwt) {
@@ -166,8 +166,8 @@ public OAuth2TokenValidatorResult validate(Jwt jwt) {
166166
OAuth2Error error = createOAuth2Error("jti claim is invalid.");
167167
return OAuth2TokenValidatorResult.failure(error);
168168
}
169-
Instant now = Instant.now(Clock.systemUTC());
170-
if ((jtiCache.putIfAbsent(jtiHash, now.toEpochMilli())) != null) {
169+
Instant expiry = Instant.now().plus(1, ChronoUnit.HOURS);
170+
if ((JTI_CACHE.putIfAbsent(jtiHash, expiry.toEpochMilli())) != null) {
171171
// Already used
172172
OAuth2Error error = createOAuth2Error("jti claim is invalid.");
173173
return OAuth2TokenValidatorResult.failure(error);
@@ -185,6 +185,21 @@ private static String computeSHA256(String value) throws Exception {
185185
return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
186186
}
187187

188+
private static final class JtiCache extends LinkedHashMap<String, Long> {
189+
190+
private static final int MAX_SIZE = 1000;
191+
192+
@Override
193+
protected boolean removeEldestEntry(Map.Entry<String, Long> eldest) {
194+
if (size() > MAX_SIZE) {
195+
return true;
196+
}
197+
Instant expiry = Instant.ofEpochMilli(eldest.getValue());
198+
return Instant.now().isAfter(expiry);
199+
}
200+
201+
}
202+
188203
}
189204

190205
}

0 commit comments

Comments
 (0)