0
# HTTP Operations
1
2
HTTP client builder with SSL configuration and server request utilities for token operations, logout, and node registration. This module provides secure HTTP communication capabilities with Keycloak servers and comprehensive request handling utilities.
3
4
## Capabilities
5
6
### HttpClientBuilder
7
8
Builder for creating configured HttpClient instances with SSL support and connection management.
9
10
```java { .api }
11
/**
12
* Builder for creating configured HttpClient instances with SSL support and connection management
13
*/
14
public class HttpClientBuilder {
15
/**
16
* Set socket timeout for HTTP operations
17
* @param timeout Timeout value
18
* @param unit Time unit for timeout
19
* @return Builder instance for chaining
20
*/
21
public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit);
22
23
/**
24
* Set connection establishment timeout
25
* @param timeout Timeout value for connection establishment
26
* @param unit Time unit for timeout
27
* @return Builder instance for chaining
28
*/
29
public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit);
30
31
/**
32
* Set connection time-to-live
33
* @param ttl Time-to-live value
34
* @param unit Time unit for TTL
35
* @return Builder instance for chaining
36
*/
37
public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit);
38
39
/**
40
* Set maximum connections per route
41
* @param maxPooledPerRoute Maximum connections per route
42
* @return Builder instance for chaining
43
*/
44
public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute);
45
46
/**
47
* Set total connection pool size
48
* @param connectionPoolSize Total pool size
49
* @return Builder instance for chaining
50
*/
51
public HttpClientBuilder connectionPoolSize(int connectionPoolSize);
52
53
/**
54
* Disable trust manager (accept all certificates)
55
* WARNING: Only use for development/testing
56
* @return Builder instance for chaining
57
*/
58
public HttpClientBuilder disableTrustManager();
59
60
/**
61
* Configure cookie cache behavior
62
* @param disable Whether to disable cookie caching
63
* @return Builder instance for chaining
64
*/
65
public HttpClientBuilder disableCookieCache(boolean disable);
66
67
/**
68
* Set hostname verification policy
69
* @param policy Hostname verification policy
70
* @return Builder instance for chaining
71
*/
72
public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy);
73
74
/**
75
* Set custom SSL context
76
* @param sslContext Configured SSL context
77
* @return Builder instance for chaining
78
*/
79
public HttpClientBuilder sslContext(SSLContext sslContext);
80
81
/**
82
* Set trust store for server certificate validation
83
* @param truststore Trust store containing trusted certificates
84
* @return Builder instance for chaining
85
*/
86
public HttpClientBuilder trustStore(KeyStore truststore);
87
88
/**
89
* Set client key store for mutual TLS
90
* @param keyStore Key store containing client certificate and private key
91
* @param password Key store password
92
* @return Builder instance for chaining
93
*/
94
public HttpClientBuilder keyStore(KeyStore keyStore, String password);
95
96
/**
97
* Set client key store for mutual TLS with char array password
98
* @param keyStore Key store containing client certificate and private key
99
* @param password Key store password as char array
100
* @return Builder instance for chaining
101
*/
102
public HttpClientBuilder keyStore(KeyStore keyStore, char[] password);
103
104
/**
105
* Build HTTP client with default configuration
106
* @return Configured HttpClient instance
107
*/
108
public HttpClient build();
109
110
/**
111
* Build HTTP client with adapter-specific configuration
112
* @param adapterConfig Adapter HTTP client configuration
113
* @return Configured HttpClient instance
114
*/
115
public HttpClient build(AdapterHttpClientConfig adapterConfig);
116
117
/**
118
* Hostname verification policy enumeration
119
*/
120
public enum HostnameVerificationPolicy {
121
/** Accept any hostname (insecure) */
122
ANY,
123
/** Standard wildcard verification */
124
WILDCARD,
125
/** Strict hostname verification */
126
STRICT
127
}
128
}
129
```
130
131
**Usage Examples:**
132
133
```java
134
// Basic HTTP client for Keycloak communication
135
HttpClient client = new HttpClientBuilder()
136
.socketTimeout(30, TimeUnit.SECONDS)
137
.establishConnectionTimeout(10, TimeUnit.SECONDS)
138
.connectionPoolSize(20)
139
.maxPooledPerRoute(5)
140
.build();
141
142
// HTTP client with custom SSL configuration
143
KeyStore trustStore = loadTrustStore();
144
HttpClient secureClient = new HttpClientBuilder()
145
.trustStore(trustStore)
146
.hostnameVerification(HostnameVerificationPolicy.STRICT)
147
.socketTimeout(60, TimeUnit.SECONDS)
148
.build();
149
150
// HTTP client with mutual TLS
151
KeyStore clientKeyStore = loadClientKeyStore();
152
HttpClient mutualTlsClient = new HttpClientBuilder()
153
.keyStore(clientKeyStore, "keystore-password")
154
.trustStore(trustStore)
155
.sslContext(createCustomSslContext())
156
.build();
157
158
// Development/testing client (insecure)
159
HttpClient devClient = new HttpClientBuilder()
160
.disableTrustManager()
161
.hostnameVerification(HostnameVerificationPolicy.ANY)
162
.build();
163
164
// Configure in deployment
165
KeycloakDeployment deployment = new KeycloakDeployment();
166
deployment.setClient(secureClient);
167
```
168
169
### ServerRequest
170
171
Utility class for server-side operations including token management, logout, and node registration.
172
173
```java { .api }
174
/**
175
* Utility class for server-side operations including token management, logout, and node registration
176
*/
177
public class ServerRequest {
178
/**
179
* Exception thrown for HTTP operation failures
180
*/
181
public static class HttpFailure extends Exception {
182
public HttpFailure(String message);
183
public HttpFailure(String message, Throwable cause);
184
}
185
186
/**
187
* Invoke logout on Keycloak server
188
* @param deployment Keycloak deployment configuration
189
* @param refreshToken Refresh token to invalidate
190
* @throws IOException If network operation fails
191
* @throws HttpFailure If server returns error response
192
*/
193
public static void invokeLogout(KeycloakDeployment deployment, String refreshToken)
194
throws IOException, HttpFailure;
195
196
/**
197
* Exchange authorization code for tokens
198
* @param deployment Keycloak deployment configuration
199
* @param code Authorization code from OAuth flow
200
* @param redirectUri Redirect URI used in authorization request
201
* @param sessionId Session identifier
202
* @return Access token response containing tokens
203
* @throws IOException If network operation fails
204
* @throws HttpFailure If server returns error response
205
*/
206
public static AccessTokenResponse invokeAccessCodeToToken(
207
KeycloakDeployment deployment,
208
String code,
209
String redirectUri,
210
String sessionId
211
) throws IOException, HttpFailure;
212
213
/**
214
* Exchange authorization code for tokens with PKCE
215
* @param deployment Keycloak deployment configuration
216
* @param code Authorization code from OAuth flow
217
* @param redirectUri Redirect URI used in authorization request
218
* @param sessionId Session identifier
219
* @param codeVerifier PKCE code verifier
220
* @return Access token response containing tokens
221
* @throws IOException If network operation fails
222
* @throws HttpFailure If server returns error response
223
*/
224
public static AccessTokenResponse invokeAccessCodeToToken(
225
KeycloakDeployment deployment,
226
String code,
227
String redirectUri,
228
String sessionId,
229
String codeVerifier
230
) throws IOException, HttpFailure;
231
232
/**
233
* Refresh access token using refresh token
234
* @param deployment Keycloak deployment configuration
235
* @param refreshToken Current refresh token
236
* @return Access token response with new tokens
237
* @throws IOException If network operation fails
238
* @throws HttpFailure If server returns error response
239
*/
240
public static AccessTokenResponse invokeRefresh(
241
KeycloakDeployment deployment,
242
String refreshToken
243
) throws IOException, HttpFailure;
244
245
/**
246
* Register application node with Keycloak server
247
* @param deployment Keycloak deployment configuration
248
* @param host Host identifier for the node
249
* @throws HttpFailure If registration fails
250
* @throws IOException If network operation fails
251
*/
252
public static void invokeRegisterNode(KeycloakDeployment deployment, String host)
253
throws HttpFailure, IOException;
254
255
/**
256
* Unregister application node from Keycloak server
257
* @param deployment Keycloak deployment configuration
258
* @param host Host identifier for the node
259
* @throws HttpFailure If unregistration fails
260
* @throws IOException If network operation fails
261
*/
262
public static void invokeUnregisterNode(KeycloakDeployment deployment, String host)
263
throws HttpFailure, IOException;
264
265
/**
266
* Invoke generic client management request
267
* @param deployment Keycloak deployment configuration
268
* @param host Host identifier
269
* @param endpointUrl Management endpoint URL
270
* @throws HttpFailure If request fails
271
* @throws IOException If network operation fails
272
*/
273
public static void invokeClientManagementRequest(
274
KeycloakDeployment deployment,
275
String host,
276
String endpointUrl
277
) throws HttpFailure, IOException;
278
279
/**
280
* Handle error response and throw appropriate exception
281
* @param status HTTP status code
282
* @param entity Response entity
283
* @throws HttpFailure Always thrown with error details
284
* @throws IOException If entity processing fails
285
*/
286
public static void error(int status, HttpEntity entity) throws HttpFailure, IOException;
287
}
288
```
289
290
**Usage Examples:**
291
292
```java
293
// Token refresh operation
294
try {
295
AccessTokenResponse tokenResponse = ServerRequest.invokeRefresh(deployment, refreshToken);
296
297
String newAccessToken = tokenResponse.getToken();
298
String newRefreshToken = tokenResponse.getRefreshToken();
299
String newIdToken = tokenResponse.getIdToken();
300
int expiresIn = tokenResponse.getExpiresIn();
301
302
// Update security context with new tokens
303
securityContext.updateTokens(newAccessToken, newRefreshToken, newIdToken);
304
305
} catch (ServerRequest.HttpFailure e) {
306
// Handle server error (e.g., invalid refresh token)
307
logger.warn("Token refresh failed: {}", e.getMessage());
308
// Redirect to re-authentication
309
310
} catch (IOException e) {
311
// Handle network error
312
logger.error("Network error during token refresh", e);
313
// Retry or fallback logic
314
}
315
316
// Authorization code exchange
317
try {
318
AccessTokenResponse tokenResponse = ServerRequest.invokeAccessCodeToToken(
319
deployment,
320
authorizationCode,
321
redirectUri,
322
sessionId
323
);
324
325
// Create security context from tokens
326
RefreshableKeycloakSecurityContext securityContext =
327
createSecurityContext(tokenResponse);
328
329
} catch (ServerRequest.HttpFailure e) {
330
// Handle authorization code exchange failure
331
logger.warn("Code to token exchange failed: {}", e.getMessage());
332
sendOAuthError(response, "invalid_grant", e.getMessage());
333
}
334
335
// PKCE-enabled authorization code exchange
336
String codeVerifier = generateCodeVerifier();
337
try {
338
AccessTokenResponse tokenResponse = ServerRequest.invokeAccessCodeToToken(
339
deployment,
340
authorizationCode,
341
redirectUri,
342
sessionId,
343
codeVerifier
344
);
345
346
} catch (ServerRequest.HttpFailure e) {
347
logger.warn("PKCE code exchange failed: {}", e.getMessage());
348
}
349
350
// User logout
351
try {
352
ServerRequest.invokeLogout(deployment, refreshToken);
353
logger.debug("User logged out successfully");
354
355
} catch (ServerRequest.HttpFailure e) {
356
logger.warn("Logout request failed: {}", e.getMessage());
357
// Continue with local logout even if server logout fails
358
359
} catch (IOException e) {
360
logger.error("Network error during logout", e);
361
}
362
363
// Node registration for clustered applications
364
try {
365
String hostIdentifier = InetAddress.getLocalHost().getHostName();
366
ServerRequest.invokeRegisterNode(deployment, hostIdentifier);
367
logger.info("Node registered with Keycloak: {}", hostIdentifier);
368
369
} catch (ServerRequest.HttpFailure e) {
370
logger.error("Failed to register node: {}", e.getMessage());
371
372
} catch (IOException e) {
373
logger.error("Network error during node registration", e);
374
}
375
376
// Node unregistration during shutdown
377
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
378
try {
379
String hostIdentifier = getCurrentHostIdentifier();
380
ServerRequest.invokeUnregisterNode(deployment, hostIdentifier);
381
logger.info("Node unregistered from Keycloak: {}", hostIdentifier);
382
} catch (Exception e) {
383
logger.warn("Failed to unregister node during shutdown", e);
384
}
385
}));
386
```
387
388
### HttpClientAdapterException
389
390
Exception thrown for HTTP client adapter operations.
391
392
```java { .api }
393
/**
394
* Exception thrown for HTTP client adapter operations
395
*/
396
public class HttpClientAdapterException extends Exception {
397
/**
398
* Constructor with error message
399
* @param message Error description
400
*/
401
public HttpClientAdapterException(String message);
402
403
/**
404
* Constructor with error message and cause
405
* @param message Error description
406
* @param t Underlying cause
407
*/
408
public HttpClientAdapterException(String message, Throwable t);
409
}
410
```
411
412
**Usage Examples:**
413
414
```java
415
// Exception handling in HTTP operations
416
public void performKeycloakRequest(KeycloakDeployment deployment) {
417
try {
418
HttpClient client = deployment.getClient();
419
HttpGet request = new HttpGet(deployment.getRealmInfoUrl());
420
421
HttpResponse response = client.execute(request);
422
if (response.getStatusLine().getStatusCode() != 200) {
423
throw new HttpClientAdapterException(
424
"Failed to fetch realm info: " + response.getStatusLine().getReasonPhrase()
425
);
426
}
427
428
// Process successful response
429
430
} catch (IOException e) {
431
throw new HttpClientAdapterException("Network error accessing Keycloak", e);
432
} catch (Exception e) {
433
throw new HttpClientAdapterException("Unexpected error in Keycloak request", e);
434
}
435
}
436
```
437
438
## HTTP Configuration Patterns
439
440
### SSL Configuration
441
442
```java
443
// Custom SSL context with specific trust store
444
public SSLContext createCustomSslContext() throws Exception {
445
// Load custom trust store
446
KeyStore trustStore = KeyStore.getInstance("JKS");
447
try (InputStream trustStoreStream = getClass().getResourceAsStream("/keycloak-truststore.jks")) {
448
trustStore.load(trustStoreStream, "truststore-password".toCharArray());
449
}
450
451
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
452
tmf.init(trustStore);
453
454
SSLContext sslContext = SSLContext.getInstance("TLS");
455
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
456
457
return sslContext;
458
}
459
460
// Configure deployment with custom SSL
461
KeycloakDeployment deployment = new KeycloakDeployment();
462
HttpClient client = new HttpClientBuilder()
463
.sslContext(createCustomSslContext())
464
.hostnameVerification(HostnameVerificationPolicy.STRICT)
465
.build();
466
deployment.setClient(client);
467
```
468
469
### Connection Pool Configuration
470
471
```java
472
// Production HTTP client configuration
473
public HttpClient createProductionHttpClient() {
474
return new HttpClientBuilder()
475
.connectionPoolSize(50) // Total connections
476
.maxPooledPerRoute(10) // Per-route connections
477
.connectionTTL(60, TimeUnit.SECONDS) // Connection reuse time
478
.socketTimeout(30, TimeUnit.SECONDS) // Response timeout
479
.establishConnectionTimeout(10, TimeUnit.SECONDS) // Connection timeout
480
.build();
481
}
482
483
// Development HTTP client configuration
484
public HttpClient createDevelopmentHttpClient() {
485
return new HttpClientBuilder()
486
.disableTrustManager() // Accept self-signed certificates
487
.hostnameVerification(HostnameVerificationPolicy.ANY)
488
.socketTimeout(60, TimeUnit.SECONDS) // Longer timeout for debugging
489
.build();
490
}
491
```