1818
1919import java .io .IOException ;
2020import java .net .URI ;
21+ import java .util .concurrent .ExecutionException ;
22+ import java .util .concurrent .TimeUnit ;
2123
2224import org .apache .http .client .HttpClient ;
2325import org .apache .http .client .utils .URIBuilder ;
3739import org .springframework .web .client .RestTemplate ;
3840
3941import 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 ;
4046import com .google .gson .JsonObject ;
4147import com .google .gson .JsonParser ;
4248
4349/**
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.
4551 * @author jricher
4652 *
4753 */
@@ -52,75 +58,95 @@ public class UserInfoFetcher {
5258 */
5359 private static final Logger logger = LoggerFactory .getLogger (UserInfoFetcher .class );
5460
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+
5570 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 ());
6675 return null ;
6776 }
6877
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 ;
10594 }
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." );
11798 return null ;
11899 }
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+
122149 }
123-
124150 }
125151
126152 protected UserInfo fromJson (JsonObject userInfoJson ) {
0 commit comments