001 002package io.vrap.rmf.base.client.oauth2; 003 004import java.util.concurrent.CompletableFuture; 005 006import io.vrap.rmf.base.client.AuthenticationToken; 007import io.vrap.rmf.base.client.http.InternalLogger; 008 009public class TokenStorageSupplier implements RefreshableTokenSupplier { 010 private final InternalLogger logger = InternalLogger.getLogger(LOGGER_AUTH); 011 012 private final TokenStorage storage; 013 private final AnonymousFlowTokenSupplier anonymousFlowTokenSupplier; 014 private final Object lock = new Object(); 015 016 private volatile CompletableFuture<AuthenticationToken> tokenFuture; 017 018 public TokenStorageSupplier(TokenStorage storage, AnonymousFlowTokenSupplier supplier) { 019 this.storage = storage; 020 this.anonymousFlowTokenSupplier = supplier; 021 } 022 023 @Override 024 public CompletableFuture<AuthenticationToken> getToken() { 025 AuthenticationToken token = storage.getToken(); 026 if (token != null && !token.isExpired()) { 027 return CompletableFuture.completedFuture(token); 028 } 029 if (token != null) { 030 if (token.getRefreshToken() != null) { 031 synchronized (lock) { 032 if (tokenFuture == null) { 033 logger.debug(() -> "using refresh token flow"); 034 tokenFuture = anonymousFlowTokenSupplier.refreshToken().thenApply(this::storeToken); 035 } 036 } 037 } 038 } 039 synchronized (lock) { 040 if (tokenFuture == null) { 041 logger.debug(() -> "using anonymous token flow"); 042 tokenFuture = anonymousFlowTokenSupplier.getToken().thenApply(this::storeToken); 043 } 044 } 045 return tokenFuture; 046 } 047 048 private void resetTokenFuture() { 049 synchronized (lock) { 050 tokenFuture = null; 051 } 052 } 053 054 private AuthenticationToken storeToken(AuthenticationToken token) { 055 storage.setToken(token); 056 resetTokenFuture(); 057 return token; 058 } 059 060 @Override 061 public CompletableFuture<AuthenticationToken> refreshToken() { 062 resetTokenFuture(); 063 AuthenticationToken token = storage.getToken(); 064 065 if (token != null) { 066 synchronized (lock) { 067 if (tokenFuture == null && token.isExpired()) { 068 logger.debug(() -> "refresh token"); 069 tokenFuture = anonymousFlowTokenSupplier.refreshToken().thenApply(this::storeToken); 070 } 071 } 072 return tokenFuture; 073 } 074 075 return getToken(); 076 } 077}