Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gjør TokenXExchangeKlient retryable og inkluderer cache #1326

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import java.net.URI;
import java.net.http.HttpRequest;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

import no.nav.vedtak.sikkerhet.kontekst.DefaultRequestKontekstProvider;
import no.nav.vedtak.sikkerhet.kontekst.KontekstProvider;
import no.nav.vedtak.util.LRUCache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -19,15 +24,20 @@
public final class TokenXExchangeKlient {

private static final Logger LOG = LoggerFactory.getLogger(TokenXExchangeKlient.class);
private static final KontekstProvider KONTEKST_PROVIDER = new DefaultRequestKontekstProvider();
private static final int RETRIES = 2; // 1 attempt, the n retries

private static TokenXExchangeKlient INSTANCE;

private LRUCache<String, OpenIDToken> obocache;

private final URI tokenEndpoint;


private TokenXExchangeKlient() {
var provider = ConfigProvider.getOpenIDConfiguration(OpenIDProvider.TOKENX);
this.tokenEndpoint = provider.map(OpenIDConfiguration::tokenEndpoint).orElse(null);
this.obocache = new LRUCache<>(2500, TimeUnit.MILLISECONDS.convert(120, TimeUnit.SECONDS));
espenwaaga marked this conversation as resolved.
Show resolved Hide resolved
}

public static synchronized TokenXExchangeKlient instance() {
Expand All @@ -41,10 +51,19 @@ public static synchronized TokenXExchangeKlient instance() {

public OpenIDToken exchangeToken(OpenIDToken token, String assertion, String scopes) {
var audience = audience(scopes);
var uid = KONTEKST_PROVIDER.getKontekst().getUid();
var tokenFromCache = getCachedToken(uid, audience);
if (tokenFromCache != null && tokenFromCache.isNotExpired()) {
return tokenFromCache.copy();
}

var response = hentToken(token, assertion, audience);
LOG.debug("TokenX byttet og fikk token av type {} utløper {}", response.token_type(), response.expires_in());
return new OpenIDToken(OpenIDProvider.TOKENX, response.token_type(), new TokenString(response.access_token()), audience,

var newToken = new OpenIDToken(OpenIDProvider.TOKENX, response.token_type(), new TokenString(response.access_token()), audience,
response.expires_in());
putTokenToCache(uid, scopes, newToken);
return newToken.copy();
}

private OidcTokenResponse hentToken(OpenIDToken token, String assertion, String audience) {
Expand All @@ -55,15 +74,22 @@ private OidcTokenResponse hentToken(OpenIDToken token, String assertion, String
.uri(tokenEndpoint)
.POST(ofFormData(token, assertion, audience))
.build();
try {
return GeneriskTokenKlient.hentToken(request, null);
} catch (TekniskException e) {
//Vist seg å være litt ustabil
LOG.info("Feiler ved henting av token. Prøver på nytt", e);
return GeneriskTokenKlient.hentToken(request, null);
return hentTokenRetryable(request);
}

public static OidcTokenResponse hentTokenRetryable(HttpRequest request) {
int i = RETRIES;
while (i-- > 0) {
try {
return GeneriskTokenKlient.hentToken(request, null);
} catch (TekniskException e) {
LOG.info("Feilet {}. gang ved henting av token. Prøver på nytt", RETRIES - i, e);
}
}
return GeneriskTokenKlient.hentToken(request, null);
}


private static HttpRequest.BodyPublisher ofFormData(OpenIDToken token, String assertion, String audience) {
var formdata = "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&"
+ "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&"
Expand All @@ -80,4 +106,16 @@ private static String audience(String scope) {
.replace("/.default", "")
.replace(".", ":");
}

private OpenIDToken getCachedToken(String uid, String audience) {
return obocache.get(cacheKey(uid, audience));
}

private void putTokenToCache(String uid, String audience, OpenIDToken exchangedToken) {
obocache.put(cacheKey(uid, audience), exchangedToken);
}

private String cacheKey(String uid, String audience) {
return uid + ":::" + audience;
}
}