18
18
19
19
import java .io .IOException ;
20
20
import java .net .URI ;
21
+ import java .util .concurrent .ExecutionException ;
22
+ import java .util .concurrent .TimeUnit ;
21
23
22
24
import org .apache .http .client .HttpClient ;
23
25
import org .apache .http .client .utils .URIBuilder ;
37
39
import org .springframework .web .client .RestTemplate ;
38
40
39
41
import com .google .common .base .Strings ;
42
+ import com .google .common .cache .CacheBuilder ;
43
+ import com .google .common .cache .CacheLoader ;
44
+ import com .google .common .cache .LoadingCache ;
45
+ import com .google .common .util .concurrent .UncheckedExecutionException ;
40
46
import com .google .gson .JsonObject ;
41
47
import com .google .gson .JsonParser ;
42
48
43
49
/**
44
- * Utility class to fetch userinfo from the userinfo endpoint, if available.
50
+ * Utility class to fetch userinfo from the userinfo endpoint, if available. Caches the results.
45
51
* @author jricher
46
52
*
47
53
*/
@@ -52,75 +58,95 @@ public class UserInfoFetcher {
52
58
*/
53
59
private static final Logger logger = LoggerFactory .getLogger (UserInfoFetcher .class );
54
60
61
+ private LoadingCache <PendingOIDCAuthenticationToken , UserInfo > cache ;
62
+
63
+ public UserInfoFetcher () {
64
+ cache = CacheBuilder .newBuilder ()
65
+ .expireAfterWrite (1 , TimeUnit .HOURS ) // expires 1 hour after fetch
66
+ .maximumSize (100 )
67
+ .build (new UserInfoLoader ());
68
+ }
69
+
55
70
public UserInfo loadUserInfo (final PendingOIDCAuthenticationToken token ) {
56
-
57
- ServerConfiguration serverConfiguration = token .getServerConfiguration ();
58
-
59
- if (serverConfiguration == null ) {
60
- logger .warn ("No server configuration found." );
61
- return null ;
62
- }
63
-
64
- if (Strings .isNullOrEmpty (serverConfiguration .getUserInfoUri ())) {
65
- logger .warn ("No userinfo endpoint, not fetching." );
71
+ try {
72
+ return cache .get (token );
73
+ } catch (UncheckedExecutionException | ExecutionException e ) {
74
+ logger .warn ("Couldn't load User Info from token: " + e .getMessage ());
66
75
return null ;
67
76
}
68
77
69
- try {
70
-
71
- // if we got this far, try to actually get the userinfo
72
- HttpClient httpClient = HttpClientBuilder .create ()
73
- .useSystemProperties ()
74
- .build ();
75
-
76
- HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory (httpClient );
77
-
78
- String userInfoString = null ;
79
-
80
- if (serverConfiguration .getUserInfoTokenMethod () == null || serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .HEADER )) {
81
- RestTemplate restTemplate = new RestTemplate (factory ) {
82
-
83
- @ Override
84
- protected ClientHttpRequest createRequest (URI url , HttpMethod method ) throws IOException {
85
- ClientHttpRequest httpRequest = super .createRequest (url , method );
86
- httpRequest .getHeaders ().add ("Authorization" , String .format ("Bearer %s" , token .getAccessTokenValue ()));
87
- return httpRequest ;
88
- }
89
- };
90
-
91
- userInfoString = restTemplate .getForObject (serverConfiguration .getUserInfoUri (), String .class );
92
-
93
- } else if (serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .FORM )) {
94
- MultiValueMap <String , String > form = new LinkedMultiValueMap <>();
95
- form .add ("access_token" , token .getAccessTokenValue ());
96
-
97
- RestTemplate restTemplate = new RestTemplate (factory );
98
- userInfoString = restTemplate .postForObject (serverConfiguration .getUserInfoUri (), form , String .class );
99
- } else if (serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .QUERY )) {
100
- URIBuilder builder = new URIBuilder (serverConfiguration .getUserInfoUri ());
101
- builder .setParameter ("access_token" , token .getAccessTokenValue ());
102
-
103
- RestTemplate restTemplate = new RestTemplate (factory );
104
- userInfoString = restTemplate .getForObject (builder .toString (), String .class );
78
+ }
79
+
80
+
81
+ private class UserInfoLoader extends CacheLoader <PendingOIDCAuthenticationToken , UserInfo > {
82
+ private HttpClient httpClient = HttpClientBuilder .create ()
83
+ .useSystemProperties ()
84
+ .build ();
85
+ private HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory (httpClient );
86
+
87
+ public UserInfo load (final PendingOIDCAuthenticationToken token ) {
88
+
89
+ ServerConfiguration serverConfiguration = token .getServerConfiguration ();
90
+
91
+ if (serverConfiguration == null ) {
92
+ logger .warn ("No server configuration found." );
93
+ return null ;
105
94
}
106
-
107
-
108
- if (!Strings .isNullOrEmpty (userInfoString )) {
109
-
110
- JsonObject userInfoJson = new JsonParser ().parse (userInfoString ).getAsJsonObject ();
111
-
112
- UserInfo userInfo = fromJson (userInfoJson );
113
-
114
- return userInfo ;
115
- } else {
116
- // didn't get anything, return null
95
+
96
+ if (Strings .isNullOrEmpty (serverConfiguration .getUserInfoUri ())) {
97
+ logger .warn ("No userinfo endpoint, not fetching." );
117
98
return null ;
118
99
}
119
- } catch (Exception e ) {
120
- logger .warn ("Error fetching userinfo" , e );
121
- return null ;
100
+
101
+ try {
102
+
103
+ String userInfoString = null ;
104
+
105
+ if (serverConfiguration .getUserInfoTokenMethod () == null || serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .HEADER )) {
106
+ RestTemplate restTemplate = new RestTemplate (factory ) {
107
+
108
+ @ Override
109
+ protected ClientHttpRequest createRequest (URI url , HttpMethod method ) throws IOException {
110
+ ClientHttpRequest httpRequest = super .createRequest (url , method );
111
+ httpRequest .getHeaders ().add ("Authorization" , String .format ("Bearer %s" , token .getAccessTokenValue ()));
112
+ return httpRequest ;
113
+ }
114
+ };
115
+
116
+ userInfoString = restTemplate .getForObject (serverConfiguration .getUserInfoUri (), String .class );
117
+
118
+ } else if (serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .FORM )) {
119
+ MultiValueMap <String , String > form = new LinkedMultiValueMap <>();
120
+ form .add ("access_token" , token .getAccessTokenValue ());
121
+
122
+ RestTemplate restTemplate = new RestTemplate (factory );
123
+ userInfoString = restTemplate .postForObject (serverConfiguration .getUserInfoUri (), form , String .class );
124
+ } else if (serverConfiguration .getUserInfoTokenMethod ().equals (UserInfoTokenMethod .QUERY )) {
125
+ URIBuilder builder = new URIBuilder (serverConfiguration .getUserInfoUri ());
126
+ builder .setParameter ("access_token" , token .getAccessTokenValue ());
127
+
128
+ RestTemplate restTemplate = new RestTemplate (factory );
129
+ userInfoString = restTemplate .getForObject (builder .toString (), String .class );
130
+ }
131
+
132
+
133
+ if (!Strings .isNullOrEmpty (userInfoString )) {
134
+
135
+ JsonObject userInfoJson = new JsonParser ().parse (userInfoString ).getAsJsonObject ();
136
+
137
+ UserInfo userInfo = fromJson (userInfoJson );
138
+
139
+ return userInfo ;
140
+ } else {
141
+ // didn't get anything, return null
142
+ return null ;
143
+ }
144
+ } catch (Exception e ) {
145
+ logger .warn ("Error fetching userinfo" , e );
146
+ return null ;
147
+ }
148
+
122
149
}
123
-
124
150
}
125
151
126
152
protected UserInfo fromJson (JsonObject userInfoJson ) {
0 commit comments