Class VertxSecurityHelper
When using @Observes Router to register Vert.x routes (instead of Quarkus Reactive Routes),
the standard Quarkus HTTP authentication flow is bypassed. This helper provides utilities to manually
trigger authentication and activate the CDI request context so that @Authenticated interceptors
work correctly.
Background
Quarkus Reactive Routes (using @Route) automatically:
- Trigger HTTP authentication mechanisms (Basic, OAuth, etc.)
- Activate the CDI request context
- Populate
CurrentIdentityAssociationwith the authenticated identity
However, when using @Observes Router to register raw Vert.x Web routes, none of this happens
automatically. This helper bridges the gap by:
- Triggering authentication via
HttpAuthenticator - Activating the CDI request context
- Populating
CurrentIdentityAssociationwith the authenticated identity - Executing
@Authenticatedmethods within the active context
Usage Pattern
@Inject VertxSecurityHelper securityHelper;
void setupRoutes(@Observes Router router) {
router.post("/api/endpoint")
.blockingHandler(ctx -> {
try {
// Authenticate and execute within request context
securityHelper.runInRequestContext(ctx, () -> {
myAuthenticatedMethod(); // Has @Authenticated annotation
});
} catch (UnauthorizedException | ForbiddenException e) {
securityHelper.handleAuthError(ctx, e);
} catch (Exception e) {
VertxSecurityHelper.handleGenericError(ctx);
}
});
}
- See Also:
-
HttpAuthenticatorCurrentIdentityAssociation
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidhandleAuthError(io.vertx.ext.web.RoutingContext ctx, Exception e) Handles authentication or authorization errors by sending the appropriate HTTP error response.static voidhandleGenericError(io.vertx.ext.web.RoutingContext ctx) Handles generic errors by sending a 500 Internal Server Error response.voidrunInRequestContext(io.vertx.ext.web.RoutingContext ctx, Runnable task) Authenticates the request and executes a task within an active CDI request context.voidrunInRequestContextDeferred(io.vertx.ext.web.RoutingContext ctx, Runnable task) Authenticates the request and executes a task, deferring CDI context destruction to the HTTP response lifecycle.
-
Constructor Details
-
VertxSecurityHelper
public VertxSecurityHelper()
-
-
Method Details
-
runInRequestContext
Authenticates the request and executes a task within an active CDI request context.This method performs the full authentication and context setup flow required for Vert.x Web routes registered via
@Observes Router:- Triggers HTTP authentication via
HttpAuthenticator.attemptAuthentication(io.vertx.ext.web.RoutingContext) - Activates the CDI request context if needed
- Sets the authenticated identity in
CurrentIdentityAssociation - Executes the task (which may call
@Authenticatedmethods) - Terminates the request context if it was activated by this method
Thread Safety: This must be called on a Vert.x worker thread (e.g., from a
blockingHandler), not the event loop thread. The authentication call blocks the worker thread usingawait().indefinitely(), which is safe on worker threads but would block the event loop on event loop threads.Context cleanup: Unlike
runInRequestContextDeferred(io.vertx.ext.web.RoutingContext, java.lang.Runnable), this method callsterminate()immediately in thefinallyblock, so there is no need to registerendHandler/closeHandlercallbacks — the context and its beans are destroyed before this method returns. Use this for non-streaming requests where the task runs synchronously on the calling thread.- Parameters:
ctx- the Vert.x routing context containing the HTTP requesttask- the code to execute within the authenticated request context- Throws:
io.quarkus.security.UnauthorizedException- if authentication failsio.quarkus.security.ForbiddenException- if authorization failsRuntimeException- if the task throws an exception- See Also:
- Triggers HTTP authentication via
-
runInRequestContextDeferred
Authenticates the request and executes a task, deferring CDI context destruction to the HTTP response lifecycle.Unlike
runInRequestContext(io.vertx.ext.web.RoutingContext, java.lang.Runnable), this method does not terminate the CDI request context when the task completes. Instead, it:- Activates the CDI request context (or captures the existing active state)
- Triggers HTTP authentication
- Executes the task
- Deactivates the context on the calling thread (without destroying beans) — this
prevents any external lifecycle manager (e.g. Quarkus's request filter) from calling
terminate()and destroying beans while the agent thread is still running - Destroys the context state when the HTTP response ends or the connection closes
This is required for streaming (SSE) requests where the task dispatches work to a background thread (via
CompletableFuture.runAsyncwith aManagedExecutor) and returns immediately. TheManagedExecutorcaptures the CDI context at submit time and propagates it to the agent thread viaAsyncManagedExecutorProducer— but only if the context hasn't been destroyed yet. By deactivating (not destroying) in the finally block and deferring destruction to the response lifecycle, the agent thread can access all@RequestScopedbeans (including OIDC token credentials for token propagation).When the CDI context is already active (e.g. activated by a Quarkus request filter), this method takes ownership of its destruction lifecycle to ensure it is not prematurely terminated when the blocking handler thread returns. The context is destroyed by the SSE response
endHandler/closeHandlerinstead.This method is also safe for non-streaming requests:
response.end()is called synchronously inside the task, and theendHandlerfires the cleanup shortly after.- Parameters:
ctx- the Vert.x routing context containing the HTTP requesttask- the code to execute within the authenticated request context- Throws:
io.quarkus.security.UnauthorizedException- if authentication failsio.quarkus.security.ForbiddenException- if authorization failsRuntimeException- if the task throws an exception- See Also:
-
handleAuthError
Handles authentication or authorization errors by sending the appropriate HTTP error response.This should be called when catching
UnauthorizedExceptionorForbiddenExceptionthrown by@Authenticatedinterceptors or authentication mechanisms.ForbiddenException→ HTTP 403 Forbidden- All other auth errors → delegates to
HttpAuthenticator.getChallenge(io.vertx.ext.web.RoutingContext)to obtain the correctWWW-Authenticateheader for the configured auth mechanism (Basic, Bearer, etc.) and sends HTTP 401 with the challenge header
- Parameters:
ctx- the routing contexte- the authentication or authorization exception
-
handleGenericError
public static void handleGenericError(io.vertx.ext.web.RoutingContext ctx) Handles generic errors by sending a 500 Internal Server Error response.- Parameters:
ctx- the routing context
-