5
5
import java .net .URI ;
6
6
import java .net .http .HttpRequest ;
7
7
import java .time .Duration ;
8
+ import java .util .concurrent .TimeUnit ;
9
+
10
+ import no .nav .vedtak .sikkerhet .kontekst .DefaultRequestKontekstProvider ;
11
+ import no .nav .vedtak .sikkerhet .kontekst .KontekstProvider ;
12
+ import no .nav .vedtak .util .LRUCache ;
8
13
9
14
import org .slf4j .Logger ;
10
15
import org .slf4j .LoggerFactory ;
19
24
public final class TokenXExchangeKlient {
20
25
21
26
private static final Logger LOG = LoggerFactory .getLogger (TokenXExchangeKlient .class );
27
+ private static final KontekstProvider KONTEKST_PROVIDER = new DefaultRequestKontekstProvider ();
28
+ private static final int RETRIES = 2 ; // 1 attempt, the n retries
22
29
23
30
private static TokenXExchangeKlient INSTANCE ;
24
31
32
+ private LRUCache <String , OpenIDToken > obocache ;
33
+
25
34
private final URI tokenEndpoint ;
26
35
27
36
28
37
private TokenXExchangeKlient () {
29
38
var provider = ConfigProvider .getOpenIDConfiguration (OpenIDProvider .TOKENX );
30
39
this .tokenEndpoint = provider .map (OpenIDConfiguration ::tokenEndpoint ).orElse (null );
40
+ this .obocache = new LRUCache <>(2500 , TimeUnit .MILLISECONDS .convert (90 , TimeUnit .SECONDS ));
31
41
}
32
42
33
43
public static synchronized TokenXExchangeKlient instance () {
@@ -41,10 +51,19 @@ public static synchronized TokenXExchangeKlient instance() {
41
51
42
52
public OpenIDToken exchangeToken (OpenIDToken token , String assertion , String scopes ) {
43
53
var audience = audience (scopes );
54
+ var uid = KONTEKST_PROVIDER .getKontekst ().getUid ();
55
+ var tokenFromCache = getCachedToken (uid , audience );
56
+ if (tokenFromCache != null && tokenFromCache .isNotExpired ()) {
57
+ return tokenFromCache .copy ();
58
+ }
59
+
44
60
var response = hentToken (token , assertion , audience );
45
61
LOG .debug ("TokenX byttet og fikk token av type {} utløper {}" , response .token_type (), response .expires_in ());
46
- return new OpenIDToken (OpenIDProvider .TOKENX , response .token_type (), new TokenString (response .access_token ()), audience ,
62
+
63
+ var newToken = new OpenIDToken (OpenIDProvider .TOKENX , response .token_type (), new TokenString (response .access_token ()), audience ,
47
64
response .expires_in ());
65
+ putTokenToCache (uid , scopes , newToken );
66
+ return newToken .copy ();
48
67
}
49
68
50
69
private OidcTokenResponse hentToken (OpenIDToken token , String assertion , String audience ) {
@@ -55,15 +74,22 @@ private OidcTokenResponse hentToken(OpenIDToken token, String assertion, String
55
74
.uri (tokenEndpoint )
56
75
.POST (ofFormData (token , assertion , audience ))
57
76
.build ();
58
- try {
59
- return GeneriskTokenKlient .hentToken (request , null );
60
- } catch (TekniskException e ) {
61
- //Vist seg å være litt ustabil
62
- LOG .info ("Feiler ved henting av token. Prøver på nytt" , e );
63
- return GeneriskTokenKlient .hentToken (request , null );
77
+ return hentTokenRetryable (request );
78
+ }
79
+
80
+ public static OidcTokenResponse hentTokenRetryable (HttpRequest request ) {
81
+ int i = RETRIES ;
82
+ while (i -- > 0 ) {
83
+ try {
84
+ return GeneriskTokenKlient .hentToken (request , null );
85
+ } catch (TekniskException e ) {
86
+ LOG .info ("Feilet {}. gang ved henting av token. Prøver på nytt" , RETRIES - i , e );
87
+ }
64
88
}
89
+ return GeneriskTokenKlient .hentToken (request , null );
65
90
}
66
91
92
+
67
93
private static HttpRequest .BodyPublisher ofFormData (OpenIDToken token , String assertion , String audience ) {
68
94
var formdata = "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&"
69
95
+ "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&"
@@ -80,4 +106,16 @@ private static String audience(String scope) {
80
106
.replace ("/.default" , "" )
81
107
.replace ("." , ":" );
82
108
}
109
+
110
+ private OpenIDToken getCachedToken (String uid , String audience ) {
111
+ return obocache .get (cacheKey (uid , audience ));
112
+ }
113
+
114
+ private void putTokenToCache (String uid , String audience , OpenIDToken exchangedToken ) {
115
+ obocache .put (cacheKey (uid , audience ), exchangedToken );
116
+ }
117
+
118
+ private String cacheKey (String uid , String audience ) {
119
+ return uid + ":::" + audience ;
120
+ }
83
121
}
0 commit comments