Skip to content

Commit dcea787

Browse files
committed
Enable refresh of JwkSet in X509SelfSignedCertificateVerifier
Closes gh-1599
1 parent 88f95d4 commit dcea787

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509SelfSignedCertificateVerifier.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@
2020
import java.security.PublicKey;
2121
import java.security.cert.X509Certificate;
2222
import java.text.ParseException;
23+
import java.time.Clock;
24+
import java.time.Instant;
25+
import java.time.temporal.ChronoUnit;
2326
import java.util.Arrays;
2427
import java.util.Map;
2528
import java.util.concurrent.ConcurrentHashMap;
29+
import java.util.concurrent.locks.ReentrantReadWriteLock;
2630
import java.util.function.Consumer;
2731
import java.util.function.Function;
2832
import java.util.function.Supplier;
@@ -158,19 +162,44 @@ private JWKSet retrieve(String jwkSetUrl) {
158162
}
159163

160164
private class JwkSetHolder implements Supplier<JWKSet> {
165+
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
166+
private final Clock clock = Clock.systemUTC();
161167
private final String jwkSetUrl;
162168
private JWKSet jwkSet;
169+
private Instant lastUpdatedAt;
163170

164171
private JwkSetHolder(String jwkSetUrl) {
165172
this.jwkSetUrl = jwkSetUrl;
166173
}
167174

168175
@Override
169176
public JWKSet get() {
170-
if (this.jwkSet == null) {
171-
this.jwkSet = retrieve(this.jwkSetUrl);
177+
this.rwLock.readLock().lock();
178+
if (shouldRefresh()) {
179+
this.rwLock.readLock().unlock();
180+
this.rwLock.writeLock().lock();
181+
try {
182+
if (shouldRefresh()) {
183+
this.jwkSet = retrieve(this.jwkSetUrl);
184+
this.lastUpdatedAt = Instant.now();
185+
}
186+
this.rwLock.readLock().lock();
187+
} finally {
188+
this.rwLock.writeLock().unlock();
189+
}
190+
}
191+
192+
try {
193+
return this.jwkSet;
194+
} finally {
195+
this.rwLock.readLock().unlock();
172196
}
173-
return this.jwkSet;
197+
}
198+
199+
private boolean shouldRefresh() {
200+
// Refresh every 5 minutes
201+
return (this.jwkSet == null ||
202+
this.clock.instant().isAfter(this.lastUpdatedAt.plus(5, ChronoUnit.MINUTES)));
174203
}
175204

176205
}

0 commit comments

Comments
 (0)