0
# Authentication
1
2
Authentication flow handling with support for bearer tokens, basic authentication, and OAuth flows. This module provides comprehensive authentication mechanisms and security context management with token refresh capabilities.
3
4
## Capabilities
5
6
### RequestAuthenticator
7
8
Base abstract class for request authentication providing common authentication flow logic.
9
10
```java { .api }
11
/**
12
* Base abstract class for request authentication
13
*/
14
public abstract class RequestAuthenticator {
15
/**
16
* Constructor for request authenticator with SSL redirect port
17
* @param facade HTTP facade for request/response handling
18
* @param deployment Keycloak deployment configuration
19
* @param tokenStore Token storage implementation
20
* @param sslRedirectPort Port for SSL redirects
21
*/
22
public RequestAuthenticator(
23
HttpFacade facade,
24
KeycloakDeployment deployment,
25
AdapterTokenStore tokenStore,
26
int sslRedirectPort
27
);
28
29
/**
30
* Constructor for request authenticator without SSL redirect
31
* @param facade HTTP facade for request/response handling
32
* @param deployment Keycloak deployment configuration
33
*/
34
public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment);
35
36
/**
37
* Get authentication challenge for unauthenticated requests
38
* @return AuthChallenge instance or null if no challenge needed
39
*/
40
public AuthChallenge getChallenge();
41
42
/**
43
* Perform authentication for the current request
44
* @return AuthOutcome indicating authentication result
45
*/
46
public AuthOutcome authenticate();
47
48
// Protected methods for subclass implementation
49
protected abstract OAuthRequestAuthenticator createOAuthAuthenticator();
50
protected BearerTokenRequestAuthenticator createBearerTokenAuthenticator();
51
protected BasicAuthRequestAuthenticator createBasicAuthAuthenticator();
52
protected QueryParameterTokenRequestAuthenticator createQueryParameterTokenRequestAuthenticator();
53
protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
54
protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
55
protected abstract String changeHttpSessionId(boolean create);
56
}
57
```
58
59
### BearerTokenRequestAuthenticator
60
61
Authenticator for bearer token validation in API requests.
62
63
```java { .api }
64
/**
65
* Authenticator for bearer token validation in API requests
66
*/
67
public class BearerTokenRequestAuthenticator {
68
/**
69
* Constructor for bearer token authenticator
70
* @param deployment Keycloak deployment configuration
71
*/
72
public BearerTokenRequestAuthenticator(KeycloakDeployment deployment);
73
74
/**
75
* Get authentication challenge for bearer token requests
76
* @return AuthChallenge for WWW-Authenticate header
77
*/
78
public AuthChallenge getChallenge();
79
80
/**
81
* Get the raw token string from the request
82
* @return Bearer token string or null if not present
83
*/
84
public String getTokenString();
85
86
/**
87
* Get the parsed and validated access token
88
* @return AccessToken instance or null if validation failed
89
*/
90
public AccessToken getToken();
91
92
/**
93
* Get the surrogate authentication user
94
* @return Surrogate user identifier or null
95
*/
96
public String getSurrogate();
97
98
/**
99
* Authenticate the bearer token request
100
* @param exchange HTTP exchange containing the request
101
* @return AuthOutcome indicating authentication result
102
*/
103
public AuthOutcome authenticate(HttpFacade exchange);
104
}
105
```
106
107
**Usage Examples:**
108
109
```java
110
// Bearer token authentication
111
BearerTokenRequestAuthenticator bearerAuth = new BearerTokenRequestAuthenticator(deployment);
112
AuthOutcome outcome = bearerAuth.authenticate(httpFacade);
113
114
if (outcome == AuthOutcome.AUTHENTICATED) {
115
AccessToken token = bearerAuth.getToken();
116
String tokenString = bearerAuth.getTokenString();
117
118
// Extract user information
119
String username = token.getPreferredUsername();
120
Set<String> roles = token.getRealmAccess().getRoles();
121
122
// Use token for authorization decisions
123
if (roles.contains("admin")) {
124
// Allow admin operations
125
}
126
} else if (outcome == AuthOutcome.FAILED) {
127
AuthChallenge challenge = bearerAuth.getChallenge();
128
// Send challenge response
129
}
130
```
131
132
### BasicAuthRequestAuthenticator
133
134
Authenticator for HTTP Basic Authentication with Keycloak credentials.
135
136
```java { .api }
137
/**
138
* Authenticator for HTTP Basic Authentication with Keycloak credentials
139
*/
140
public class BasicAuthRequestAuthenticator {
141
/**
142
* Constructor for basic auth authenticator
143
* @param deployment Keycloak deployment configuration
144
*/
145
public BasicAuthRequestAuthenticator(KeycloakDeployment deployment);
146
147
/**
148
* Authenticate using HTTP Basic Authentication
149
* @param exchange HTTP exchange containing credentials
150
* @return AuthOutcome indicating authentication result
151
*/
152
public AuthOutcome authenticate(HttpFacade exchange);
153
}
154
```
155
156
**Usage Examples:**
157
158
```java
159
// Basic authentication
160
BasicAuthRequestAuthenticator basicAuth = new BasicAuthRequestAuthenticator(deployment);
161
AuthOutcome outcome = basicAuth.authenticate(httpFacade);
162
163
if (outcome == AuthOutcome.AUTHENTICATED) {
164
// User authenticated via basic auth
165
// Continue with request processing
166
} else {
167
// Send 401 Unauthorized with WWW-Authenticate header
168
httpFacade.getResponse().setStatus(401);
169
httpFacade.getResponse().setHeader("WWW-Authenticate", "Basic realm=\"keycloak\"");
170
}
171
```
172
173
### RefreshableKeycloakSecurityContext
174
175
Security context providing access to tokens with automatic refresh capabilities.
176
177
```java { .api }
178
/**
179
* Security context providing access to tokens with automatic refresh capabilities
180
*/
181
public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext {
182
/**
183
* Default constructor
184
*/
185
public RefreshableKeycloakSecurityContext();
186
187
/**
188
* Constructor with complete token set
189
* @param deployment Keycloak deployment configuration
190
* @param tokenStore Token storage implementation
191
* @param tokenString Raw access token string
192
* @param token Parsed access token
193
* @param idTokenString Raw ID token string
194
* @param idToken Parsed ID token
195
* @param refreshToken Refresh token string
196
*/
197
public RefreshableKeycloakSecurityContext(
198
KeycloakDeployment deployment,
199
AdapterTokenStore tokenStore,
200
String tokenString,
201
AccessToken token,
202
String idTokenString,
203
IDToken idToken,
204
String refreshToken
205
);
206
207
/**
208
* Get the current access token
209
* @return AccessToken instance
210
*/
211
public AccessToken getToken();
212
213
/**
214
* Get the raw access token string
215
* @return Access token as string
216
*/
217
public String getTokenString();
218
219
/**
220
* Get the current ID token
221
* @return IDToken instance
222
*/
223
public IDToken getIdToken();
224
225
/**
226
* Get the raw ID token string
227
* @return ID token as string
228
*/
229
public String getIdTokenString();
230
231
/**
232
* Get the refresh token
233
* @return Refresh token string
234
*/
235
public String getRefreshToken();
236
237
/**
238
* Logout the current session
239
* @param deployment Keycloak deployment configuration
240
*/
241
public void logout(KeycloakDeployment deployment);
242
243
/**
244
* Check if the security context is active
245
* @return true if tokens are valid and not expired
246
*/
247
public boolean isActive();
248
249
/**
250
* Check if token has sufficient time to live
251
* @param token Token to check
252
* @return true if token has sufficient TTL
253
*/
254
public boolean isTokenTimeToLiveSufficient(AccessToken token);
255
256
/**
257
* Get the deployment configuration
258
* @return KeycloakDeployment instance
259
*/
260
public KeycloakDeployment getDeployment();
261
262
/**
263
* Set current request information for token refresh
264
* @param deployment Keycloak deployment configuration
265
* @param tokenStore Token storage implementation
266
*/
267
public void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore);
268
269
/**
270
* Refresh expired tokens
271
* @param checkActive Whether to check if context is active first
272
* @return true if refresh was successful
273
*/
274
public boolean refreshExpiredToken(boolean checkActive);
275
276
/**
277
* Set authorization context for policy enforcement
278
* @param authorizationContext Authorization context instance
279
*/
280
public void setAuthorizationContext(AuthorizationContext authorizationContext);
281
}
282
```
283
284
**Usage Examples:**
285
286
```java
287
// Create security context from tokens
288
RefreshableKeycloakSecurityContext securityContext = new RefreshableKeycloakSecurityContext(
289
deployment, tokenStore, tokenString, accessToken, idTokenString, idToken, refreshToken
290
);
291
292
// Check if context is active
293
if (securityContext.isActive()) {
294
AccessToken token = securityContext.getToken();
295
296
// Check if token needs refresh
297
if (!securityContext.isTokenTimeToLiveSufficient(token)) {
298
// Attempt to refresh token
299
boolean refreshed = securityContext.refreshExpiredToken(true);
300
if (refreshed) {
301
// Use refreshed token
302
token = securityContext.getToken();
303
}
304
}
305
306
// Access user information
307
String username = token.getPreferredUsername();
308
String email = token.getEmail();
309
Map<String, Object> customClaims = token.getOtherClaims();
310
}
311
312
// Logout when done
313
securityContext.logout(deployment);
314
```
315
316
### QueryParameterTokenRequestAuthenticator
317
318
Authenticator for extracting bearer tokens from URL query parameters instead of Authorization header.
319
320
```java { .api }
321
/**
322
* Authenticator for extracting bearer tokens from URL query parameters
323
*/
324
public class QueryParameterTokenRequestAuthenticator {
325
/**
326
* Constructor for query parameter token authenticator
327
* @param deployment Keycloak deployment configuration
328
*/
329
public QueryParameterTokenRequestAuthenticator(KeycloakDeployment deployment);
330
331
/**
332
* Get authentication challenge for query parameter token requests
333
* @return AuthChallenge for error responses
334
*/
335
public AuthChallenge getChallenge();
336
337
/**
338
* Get the raw token string from query parameters
339
* @return Bearer token string or null if not present
340
*/
341
public String getTokenString();
342
343
/**
344
* Get the parsed and validated access token
345
* @return AccessToken instance or null if validation failed
346
*/
347
public AccessToken getToken();
348
349
/**
350
* Authenticate the request using query parameter token
351
* @param exchange HTTP exchange containing the request
352
* @return AuthOutcome indicating authentication result
353
*/
354
public AuthOutcome authenticate(HttpFacade exchange);
355
}
356
```
357
358
**Usage Examples:**
359
360
```java
361
// Query parameter token authentication (e.g., for WebSocket connections)
362
QueryParameterTokenRequestAuthenticator queryAuth =
363
new QueryParameterTokenRequestAuthenticator(deployment);
364
365
AuthOutcome outcome = queryAuth.authenticate(httpFacade);
366
367
if (outcome == AuthOutcome.AUTHENTICATED) {
368
AccessToken token = queryAuth.getToken();
369
String tokenString = queryAuth.getTokenString();
370
371
// Token was successfully extracted from query parameter
372
// e.g., /api/websocket?access_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
373
String username = token.getPreferredUsername();
374
375
} else if (outcome == AuthOutcome.FAILED) {
376
AuthChallenge challenge = queryAuth.getChallenge();
377
// Handle authentication failure
378
}
379
```
380
381
### AuthenticatedActionsHandler
382
383
Handler for pre-authenticated actions like CORS preflight and bearer token queries.
384
385
```java { .api }
386
/**
387
* Handler for pre-authenticated actions like CORS preflight and bearer token queries
388
*/
389
public class AuthenticatedActionsHandler {
390
/**
391
* Constructor for authenticated actions handler
392
* @param deployment Keycloak deployment configuration
393
* @param facade OIDC HTTP facade
394
*/
395
public AuthenticatedActionsHandler(KeycloakDeployment deployment, OIDCHttpFacade facade);
396
397
/**
398
* Handle the request if it matches a pre-authenticated action
399
* @return true if request was handled, false otherwise
400
*/
401
public boolean handledRequest();
402
}
403
```
404
405
**Usage Examples:**
406
407
```java
408
// Handle pre-authenticated actions
409
AuthenticatedActionsHandler actionsHandler =
410
new AuthenticatedActionsHandler(deployment, oidcFacade);
411
412
if (actionsHandler.handledRequest()) {
413
// Request was handled (e.g., CORS preflight)
414
// No further processing needed
415
return;
416
}
417
418
// Continue with normal authentication flow
419
RequestAuthenticator authenticator = createAuthenticator(facade, deployment);
420
AuthOutcome outcome = authenticator.authenticate();
421
```
422
423
### OidcKeycloakAccount
424
425
Interface representing an authenticated OIDC account.
426
427
```java { .api }
428
/**
429
* Interface representing an authenticated OIDC account
430
*/
431
public interface OidcKeycloakAccount extends KeycloakAccount {
432
/**
433
* Get the security context for this account
434
* @return KeycloakSecurityContext instance
435
*/
436
KeycloakSecurityContext getKeycloakSecurityContext();
437
}
438
```
439
440
### OIDCHttpFacade
441
442
HTTP facade interface for OIDC operations.
443
444
```java { .api }
445
/**
446
* HTTP facade interface for OIDC operations extending base HttpFacade
447
*/
448
public interface OIDCHttpFacade extends HttpFacade {
449
/**
450
* Get the security context for the current request
451
* @return KeycloakSecurityContext or null if not authenticated
452
*/
453
KeycloakSecurityContext getSecurityContext();
454
}
455
```
456
457
### OIDCAuthenticationError
458
459
Error representation for OIDC authentication failures.
460
461
```java { .api }
462
/**
463
* Error representation for OIDC authentication failures
464
*/
465
public class OIDCAuthenticationError {
466
/**
467
* Enumeration of possible authentication error reasons
468
*/
469
public enum Reason {
470
NO_BEARER_TOKEN,
471
NO_REDIRECT_URI,
472
INVALID_STATE_COOKIE,
473
OAUTH_ERROR,
474
SSL_REQUIRED,
475
CODE_TO_TOKEN_FAILURE,
476
INVALID_TOKEN,
477
STALE_TOKEN,
478
NO_AUTHORIZATION_HEADER,
479
NO_QUERY_PARAMETER_ACCESS_TOKEN
480
}
481
482
/**
483
* Constructor for authentication error
484
* @param reason Error reason from enum
485
* @param description Detailed error description
486
*/
487
public OIDCAuthenticationError(Reason reason, String description);
488
489
/**
490
* Get the error reason
491
* @return Reason enum value
492
*/
493
public Reason getReason();
494
495
/**
496
* Get the error description
497
* @return Detailed error message
498
*/
499
public String getDescription();
500
501
/**
502
* String representation of the error
503
* @return Formatted error string
504
*/
505
public String toString();
506
}
507
```
508
509
**Usage Examples:**
510
511
```java
512
// Handle authentication errors
513
try {
514
AuthOutcome outcome = authenticator.authenticate();
515
if (outcome == AuthOutcome.FAILED) {
516
// Create error for client
517
OIDCAuthenticationError error = new OIDCAuthenticationError(
518
OIDCAuthenticationError.Reason.INVALID_TOKEN,
519
"Token signature validation failed"
520
);
521
522
// Log error details
523
logger.warn("Authentication failed: {} - {}",
524
error.getReason(), error.getDescription());
525
526
// Return appropriate HTTP response
527
sendErrorResponse(error);
528
}
529
} catch (Exception e) {
530
OIDCAuthenticationError error = new OIDCAuthenticationError(
531
OIDCAuthenticationError.Reason.CODE_TO_TOKEN_FAILURE,
532
"Failed to exchange authorization code for tokens: " + e.getMessage()
533
);
534
handleAuthenticationError(error);
535
}
536
```