-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ACL-263] Caching improvements (#337)
- Loading branch information
Showing
23 changed files
with
604 additions
and
212 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
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
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
50 changes: 50 additions & 0 deletions
50
src/main/java/com/truelayer/java/http/auth/cache/CredentialsCacheHelper.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 |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package com.truelayer.java.http.auth.cache; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
import static org.apache.commons.lang3.ObjectUtils.isEmpty; | ||
|
||
import com.truelayer.java.TrueLayerException; | ||
import com.truelayer.java.entities.RequestScopes; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.text.MessageFormat; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
public class CredentialsCacheHelper { | ||
private static final String CACHE_KEY_PREFIX = "tl-auth-token"; | ||
private static final String SCOPES_DELIMITER = ","; | ||
|
||
public static String buildKey(String clientId, RequestScopes requestScopes) { | ||
if (isEmpty(clientId) || isEmpty(requestScopes) || isEmpty(requestScopes.getScopes())) { | ||
throw new TrueLayerException("Invalid client id or request scopes provided"); | ||
} | ||
|
||
List<String> scopes = new ArrayList<>(requestScopes.getScopes()); | ||
|
||
// Use natural ordering to make ordering not significant | ||
Collections.sort(scopes); | ||
|
||
byte[] md5InBytes = digest(String.join(SCOPES_DELIMITER, scopes).getBytes(UTF_8)); | ||
return MessageFormat.format("{0}:{1}:{2}", CACHE_KEY_PREFIX, clientId, bytesToHex(md5InBytes)); | ||
} | ||
|
||
private static byte[] digest(byte[] input) { | ||
MessageDigest md; | ||
try { | ||
md = MessageDigest.getInstance("MD5"); | ||
} catch (NoSuchAlgorithmException e) { | ||
throw new TrueLayerException("Hashing algorithm is not available", e); | ||
} | ||
return md.digest(input); | ||
} | ||
|
||
private static String bytesToHex(byte[] bytes) { | ||
StringBuilder sb = new StringBuilder(); | ||
for (byte b : bytes) { | ||
sb.append(String.format("%02x", b)); | ||
} | ||
return sb.toString(); | ||
} | ||
} |
21 changes: 3 additions & 18 deletions
21
src/main/java/com/truelayer/java/http/auth/cache/ICredentialsCache.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,28 +1,13 @@ | ||
package com.truelayer.java.http.auth.cache; | ||
|
||
import com.truelayer.java.auth.entities.AccessToken; | ||
import com.truelayer.java.entities.RequestScopes; | ||
import java.util.Optional; | ||
|
||
public interface ICredentialsCache { | ||
|
||
/** | ||
* Gets the cached access token for the given request scopes. | ||
* @param scopes the requested scopes | ||
* @return an optional access token. If the token is expired an empty optional is returned | ||
*/ | ||
Optional<AccessToken> getToken(RequestScopes scopes); | ||
Optional<AccessToken> getToken(String key); | ||
|
||
/** | ||
* Stores an access token in cache for the given request scopes. | ||
* @param token the new token to store | ||
* @param scopes the requested scopes | ||
*/ | ||
void storeToken(RequestScopes scopes, AccessToken token); | ||
void storeToken(String key, AccessToken token); | ||
|
||
/** | ||
* Remove the entry in the cache for the given request scopes. | ||
* @param scopes the requested scopes | ||
*/ | ||
void clearToken(RequestScopes scopes); | ||
void clearToken(String key); | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/com/truelayer/java/http/auth/cache/InMemoryCredentialsCache.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 |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.truelayer.java.http.auth.cache; | ||
|
||
import com.truelayer.java.auth.entities.AccessToken; | ||
import java.time.Clock; | ||
import java.time.LocalDateTime; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
public class InMemoryCredentialsCache implements ICredentialsCache { | ||
|
||
private final Clock clock; | ||
|
||
/** | ||
* internal state | ||
*/ | ||
private final Map<String, AccessTokenRecord> tokenRecords = new ConcurrentHashMap<>(); | ||
|
||
@Override | ||
public Optional<AccessToken> getToken(String key) { | ||
AccessTokenRecord tokenRecord = tokenRecords.get(key); | ||
if (tokenRecord == null || !LocalDateTime.now(clock).isBefore(tokenRecord.expiresAt)) { | ||
return Optional.empty(); | ||
} | ||
|
||
return Optional.of(tokenRecord.token); | ||
} | ||
|
||
@Override | ||
public void storeToken(String key, AccessToken token) { | ||
AccessTokenRecord tokenRecord = | ||
new AccessTokenRecord(token, LocalDateTime.now(clock).plusSeconds(token.getExpiresIn())); | ||
|
||
tokenRecords.put(key, tokenRecord); | ||
} | ||
|
||
@Override | ||
public void clearToken(String key) { | ||
tokenRecords.remove(key); | ||
} | ||
|
||
@RequiredArgsConstructor | ||
public static class AccessTokenRecord { | ||
private final AccessToken token; | ||
private final LocalDateTime expiresAt; | ||
} | ||
} |
Oops, something went wrong.