8
8
import stroom .security .openid .api .OpenIdConfigurationResponse .Builder ;
9
9
import stroom .util .HasHealthCheck ;
10
10
import stroom .util .NullSafe ;
11
- import stroom .util .http .HttpClientConfiguration ;
12
- import stroom .util .http .HttpClientFactory ;
13
- import stroom .util .io .StreamUtil ;
11
+ import stroom .util .jersey .JerseyClientFactory ;
12
+ import stroom .util .jersey .JerseyClientName ;
14
13
import stroom .util .logging .LambdaLogger ;
15
14
import stroom .util .logging .LambdaLoggerFactory ;
16
15
import stroom .util .logging .LogUtil ;
23
22
import jakarta .inject .Provider ;
24
23
import jakarta .inject .Singleton ;
25
24
import jakarta .servlet .http .HttpServletResponse ;
26
- import org .apache .hc .client5 .http .classic .HttpClient ;
27
- import org .apache .hc .client5 .http .classic .methods .HttpGet ;
28
- import org .apache .hc .client5 .http .impl .classic .CloseableHttpClient ;
29
- import org .apache .hc .core5 .http .HttpEntity ;
30
- import org .apache .hc .core5 .io .CloseMode ;
25
+ import jakarta .ws .rs .client .WebTarget ;
26
+ import jakarta .ws .rs .core .MediaType ;
27
+ import jakarta .ws .rs .core .Response ;
31
28
32
29
import java .io .IOException ;
33
- import java .io .InputStream ;
34
30
import java .time .Duration ;
35
31
import java .util .HashSet ;
36
32
import java .util .List ;
37
33
import java .util .Objects ;
38
34
import java .util .Set ;
39
- import java .util .UUID ;
40
35
import java .util .function .BiConsumer ;
41
36
import java .util .function .Consumer ;
42
37
import java .util .function .Supplier ;
@@ -52,22 +47,20 @@ public class ExternalIdpConfigurationProvider
52
47
private static final LambdaLogger LOGGER = LambdaLoggerFactory .getLogger (ExternalIdpConfigurationProvider .class );
53
48
private static final long MAX_SLEEP_TIME_MS = 30_000 ;
54
49
55
- private final HttpClientFactory httpClientFactory ;
50
+ private final JerseyClientFactory jerseyClientFactory ;
56
51
// Important to use AbstractOpenIdConfig here and not OpenIdConfiguration as the former
57
52
// is bound to the yaml config, the latter is what we are presenting this as.
58
53
private final Provider <AbstractOpenIdConfig > localOpenIdConfigProvider ;
59
54
60
55
private volatile String lastConfigurationEndpoint ;
61
56
private volatile OpenIdConfigurationResponse openIdConfigurationResp ;
62
- private volatile CloseableHttpClient currentHttpClient ;
63
- private volatile HttpClientConfiguration currentHttpClientConfiguration ;
64
57
65
58
@ Inject
66
59
public ExternalIdpConfigurationProvider (
67
- final HttpClientFactory httpClientFactory ,
68
- final Provider <AbstractOpenIdConfig > localOpenIdConfigProvider ) {
69
- this .httpClientFactory = httpClientFactory ;
60
+ final Provider <AbstractOpenIdConfig > localOpenIdConfigProvider ,
61
+ final JerseyClientFactory jerseyClientFactory ) {
70
62
this .localOpenIdConfigProvider = localOpenIdConfigProvider ;
63
+ this .jerseyClientFactory = jerseyClientFactory ;
71
64
}
72
65
73
66
@ Override
@@ -76,27 +69,12 @@ public OpenIdConfigurationResponse getConfigurationResponse() {
76
69
final String configurationEndpoint = abstractOpenIdConfig .getOpenIdConfigurationEndpoint ();
77
70
78
71
if (isFetchRequired (configurationEndpoint )) {
79
- updateOpenIdConfigurationResponse (abstractOpenIdConfig , getHttpClient ( abstractOpenIdConfig ) );
72
+ updateOpenIdConfigurationResponse (abstractOpenIdConfig );
80
73
}
81
74
82
75
return openIdConfigurationResp ;
83
76
}
84
77
85
- private synchronized HttpClient getHttpClient (final AbstractOpenIdConfig abstractOpenIdConfig ) {
86
- if (currentHttpClient == null ||
87
- !Objects .equals (abstractOpenIdConfig .getHttpClient (), currentHttpClientConfiguration )) {
88
- if (currentHttpClient != null ) {
89
- currentHttpClient .close (CloseMode .IMMEDIATE );
90
- }
91
-
92
- currentHttpClientConfiguration = abstractOpenIdConfig .getHttpClient ();
93
- currentHttpClient = httpClientFactory .get (
94
- "ExternalIdpConfigurationProvider-" + UUID .randomUUID (),
95
- currentHttpClientConfiguration );
96
- }
97
- return currentHttpClient ;
98
- }
99
-
100
78
@ Override
101
79
public HealthCheck .Result getHealth () {
102
80
final HealthCheck .ResultBuilder resultBuilder = HealthCheck .Result .builder ();
@@ -124,7 +102,7 @@ public HealthCheck.Result getHealth() {
124
102
try {
125
103
resultBuilder .withDetail ("configUri" , configurationEndpoint );
126
104
OpenIdConfigurationResponse response = fetchOpenIdConfigurationResponse (
127
- configurationEndpoint , abstractOpenIdConfig , getHttpClient ( abstractOpenIdConfig ) );
105
+ configurationEndpoint , abstractOpenIdConfig );
128
106
if (response != null ) {
129
107
resultBuilder .healthy ();
130
108
} else {
@@ -147,8 +125,7 @@ private boolean isFetchRequired(final String configurationEndpoint) {
147
125
}
148
126
149
127
private OpenIdConfigurationResponse updateOpenIdConfigurationResponse (
150
- final AbstractOpenIdConfig abstractOpenIdConfig ,
151
- final HttpClient httpClient ) {
128
+ final AbstractOpenIdConfig abstractOpenIdConfig ) {
152
129
final String configurationEndpoint = abstractOpenIdConfig .getOpenIdConfigurationEndpoint ();
153
130
154
131
LOGGER .debug ("About to get lock to update open id configuration" );
@@ -158,7 +135,7 @@ private OpenIdConfigurationResponse updateOpenIdConfigurationResponse(
158
135
if (isFetchRequired (configurationEndpoint )) {
159
136
try {
160
137
final OpenIdConfigurationResponse response = fetchOpenIdConfigurationResponse (
161
- configurationEndpoint , abstractOpenIdConfig , httpClient );
138
+ configurationEndpoint , abstractOpenIdConfig );
162
139
openIdConfigurationResp = mergeResponse (response , abstractOpenIdConfig );
163
140
} catch (final RuntimeException | IOException e ) {
164
141
LOGGER .error (e .getMessage (), e );
@@ -181,39 +158,43 @@ private OpenIdConfigurationResponse updateOpenIdConfigurationResponse(
181
158
182
159
private OpenIdConfigurationResponse fetchOpenIdConfigurationResponse (
183
160
final String configurationEndpoint ,
184
- final AbstractOpenIdConfig abstractOpenIdConfig ,
185
- final HttpClient httpClient ) throws IOException {
161
+ final AbstractOpenIdConfig abstractOpenIdConfig ) throws IOException {
186
162
187
163
Objects .requireNonNull (configurationEndpoint ,
188
164
"Property "
189
165
+ abstractOpenIdConfig .getFullPathStr (AbstractOpenIdConfig .PROP_NAME_CONFIGURATION_ENDPOINT )
190
166
+ " has not been set" );
191
167
LOGGER .info ("Fetching open id configuration from: " + configurationEndpoint );
192
168
193
- final HttpGet httpGet = new HttpGet (configurationEndpoint );
169
+ // final HttpGet httpGet = new HttpGet(configurationEndpoint);
194
170
long sleepMs = 500 ;
195
171
Throwable lastThrowable = null ;
196
172
197
173
while (true ) {
198
174
try {
199
- return httpClient .execute (httpGet , response -> {
200
- if (HttpServletResponse .SC_OK == response .getCode ()) {
201
- final HttpEntity entity = response .getEntity ();
202
- String msg ;
203
- try (final InputStream is = entity .getContent ()) {
204
- msg = StreamUtil .streamToString (is );
205
- }
206
-
175
+ final WebTarget webTarget = jerseyClientFactory .getNamedClient (JerseyClientName .OPEN_ID )
176
+ .target (configurationEndpoint );
177
+
178
+ try (Response response = webTarget .request (MediaType .APPLICATION_JSON ).get ()) {
179
+ if (response .getStatus () == HttpServletResponse .SC_OK ) {
180
+ // According to the spec, the response may contain unexpected props so as we don't easily
181
+ // have access to configure the client to relax jackson, do it manually.
182
+ // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
183
+ final String responseJson = response .readEntity (String .class );
184
+ LOGGER .debug ("configurationEndpoint: '{}'\n {}" ,
185
+ configurationEndpoint ,
186
+ responseJson );
207
187
final OpenIdConfigurationResponse openIdConfigurationResponse = parseConfigurationResponse (
208
188
configurationEndpoint ,
209
- msg );
189
+ responseJson );
190
+
210
191
LOGGER .info ("Successfully fetched open id configuration from: " + configurationEndpoint );
211
192
return openIdConfigurationResponse ;
212
193
} else {
213
- throw new AuthenticationException ("Received status " + response .getCode () +
194
+ throw new AuthenticationException ("Received status " + response .getStatus () +
214
195
" from " + configurationEndpoint );
215
196
}
216
- });
197
+ }
217
198
} catch (AuthenticationException e ) {
218
199
// This is not a connection issue so just bubble it up and likely crash the app
219
200
// if this is happening as part of the guice injector init.
0 commit comments