forked from quarkusio/quarkus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for dynamic OIDC JWK set resolution
- Loading branch information
1 parent
830ef6e
commit af65f8a
Showing
16 changed files
with
668 additions
and
233 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 10 additions & 80 deletions
90
...sions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/BackChannelLogoutTokenCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,33 @@ | ||
package io.quarkus.oidc.runtime; | ||
|
||
import java.util.Iterator; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import jakarta.enterprise.event.Observes; | ||
|
||
import io.quarkus.oidc.OidcTenantConfig; | ||
import io.vertx.core.Handler; | ||
import io.quarkus.runtime.ShutdownEvent; | ||
import io.vertx.core.Vertx; | ||
|
||
public class BackChannelLogoutTokenCache { | ||
private OidcTenantConfig oidcConfig; | ||
|
||
private Map<String, CacheEntry> cacheMap = new ConcurrentHashMap<>();; | ||
private AtomicInteger size = new AtomicInteger(); | ||
final MemoryCache<TokenVerificationResult> cache; | ||
|
||
public BackChannelLogoutTokenCache(OidcTenantConfig oidcTenantConfig, Vertx vertx) { | ||
this.oidcConfig = oidcTenantConfig; | ||
init(vertx); | ||
} | ||
|
||
private void init(Vertx vertx) { | ||
cacheMap = new ConcurrentHashMap<>(); | ||
if (oidcConfig.logout.backchannel.cleanUpTimerInterval.isPresent()) { | ||
vertx.setPeriodic(oidcConfig.logout.backchannel.cleanUpTimerInterval.get().toMillis(), new Handler<Long>() { | ||
@Override | ||
public void handle(Long event) { | ||
// Remove all the entries which have expired | ||
removeInvalidEntries(); | ||
} | ||
}); | ||
} | ||
cache = new MemoryCache<TokenVerificationResult>(vertx, oidcTenantConfig.logout.backchannel.cleanUpTimerInterval, | ||
oidcTenantConfig.logout.backchannel.tokenCacheTimeToLive, oidcTenantConfig.logout.backchannel.tokenCacheSize); | ||
} | ||
|
||
public void addTokenVerification(String token, TokenVerificationResult result) { | ||
if (!prepareSpaceForNewCacheEntry()) { | ||
clearCache(); | ||
} | ||
cacheMap.put(token, new CacheEntry(result)); | ||
cache.add(token, result); | ||
} | ||
|
||
public TokenVerificationResult removeTokenVerification(String token) { | ||
CacheEntry entry = removeCacheEntry(token); | ||
return entry == null ? null : entry.result; | ||
return cache.remove(token); | ||
} | ||
|
||
public boolean containsTokenVerification(String token) { | ||
return cacheMap.containsKey(token); | ||
} | ||
|
||
public void clearCache() { | ||
cacheMap.clear(); | ||
size.set(0); | ||
} | ||
|
||
private void removeInvalidEntries() { | ||
long now = now(); | ||
for (Iterator<Map.Entry<String, CacheEntry>> it = cacheMap.entrySet().iterator(); it.hasNext();) { | ||
Map.Entry<String, CacheEntry> next = it.next(); | ||
if (isEntryExpired(next.getValue(), now)) { | ||
it.remove(); | ||
size.decrementAndGet(); | ||
} | ||
} | ||
} | ||
|
||
private boolean prepareSpaceForNewCacheEntry() { | ||
int currentSize; | ||
do { | ||
currentSize = size.get(); | ||
if (currentSize == oidcConfig.logout.backchannel.tokenCacheSize) { | ||
return false; | ||
} | ||
} while (!size.compareAndSet(currentSize, currentSize + 1)); | ||
return true; | ||
return cache.containsKey(token); | ||
} | ||
|
||
private CacheEntry removeCacheEntry(String token) { | ||
CacheEntry entry = cacheMap.remove(token); | ||
if (entry != null) { | ||
size.decrementAndGet(); | ||
} | ||
return entry; | ||
} | ||
|
||
private boolean isEntryExpired(CacheEntry entry, long now) { | ||
return entry.createdTime + oidcConfig.logout.backchannel.tokenCacheTimeToLive.toMillis() < now; | ||
} | ||
|
||
private static long now() { | ||
return System.currentTimeMillis(); | ||
} | ||
|
||
private static class CacheEntry { | ||
volatile TokenVerificationResult result; | ||
long createdTime = System.currentTimeMillis(); | ||
|
||
public CacheEntry(TokenVerificationResult result) { | ||
this.result = result; | ||
} | ||
void shutdown(@Observes ShutdownEvent event, Vertx vertx) { | ||
cache.stopTimer(vertx); | ||
} | ||
} |
Oops, something went wrong.