quarkusio/quarkus · error · io.quarkus.security.AuthenticationFailedException
Authentication has happened before the '@AuthenticationConte
Error message
Authentication has happened before the '@AuthenticationContext' annotation was matched with the HTTP request path '%s'. It can happen when the authentication is required by an HTTP Security Policy before the JAX-RS chain is run. In such cases, please set the 'quarkus.http.auth.permission."permissions".applies-to=JAXRS' to all HTTP Security Policies which secure the same REST endpoints as the ones annotated with the '@AuthenticationContext' annotation.
What it means
Quarkus OIDC throws this when the @AuthenticationContext annotation is matched to the request path, but authentication already happened for the request. Authentication required by an HTTP Security Policy runs before the JAX-RS chain, so the annotation never gets a chance to control authentication. The framework detects an existing tenant config or authenticated user at annotation-matching time and fails the request.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java:164
@Override
public Consumer<RoutingContext> apply(String annotationBinding) {
int separatorIndex = annotationBinding.indexOf(ACR_VALUES_TO_MAX_AGE_SEPARATOR);
String acrValues = annotationBinding.substring(0, separatorIndex);
String maxAgeAsStr = annotationBinding.substring(separatorIndex + ACR_VALUES_TO_MAX_AGE_SEPARATOR.length());
final Duration maxAgeDuration;
if (maxAgeAsStr.isEmpty()) {
maxAgeDuration = null;
} else {
maxAgeDuration = parseDuration(maxAgeAsStr);
}
StepUpAuthenticationPolicy policy = new StepUpAuthenticationPolicy(acrValues, maxAgeDuration);
return new Consumer<RoutingContext>() {
@Override
public void accept(RoutingContext routingContext) {
String requestPath = routingContext.request().path();
OidcTenantConfig tenantConfig = routingContext.get(OidcTenantConfig.class.getName());
if (tenantConfig != null || routingContext.user() != null) {
throw new AuthenticationFailedException("""
Authentication has happened before the '@AuthenticationContext' annotation was
matched with the HTTP request path '%s'. It can happen when the authentication
is required by an HTTP Security Policy before the JAX-RS chain is run. In such
cases, please set the 'quarkus.http.auth.permission."permissions".applies-to=JAXRS'
to all HTTP Security Policies which secure the same REST endpoints as the ones
annotated with the '@AuthenticationContext' annotation.
""".formatted(requestPath));
}
LOG.debugf("The '@AuthenticationContext' annotation set required 'acr' values '%s' "
+ "and max age '%s' for the request path '%s'", acrValues, maxAgeAsStr, requestPath);
policy.storeSelfOnContext(routingContext);
}
};
}
};
}
public Handler<RoutingContext> getBackChannelLogoutHandler(BeanContainer beanContainer) {View on GitHub (pinned to e1c734241f)
Solutions
- Set 'quarkus.http.auth.permission."permissions".applies-to=JAXRS' on all HTTP Security Policies that secure the same REST endpoints annotated with @AuthenticationContext
- Remove or narrow HTTP Security Policies covering the annotated endpoints so they do not force early authentication
- Use @AuthenticationContext on endpoints not secured by proactive HTTP-level policies
Example fix
// before quarkus.http.auth.permission.secured.paths=/rest/* quarkus.http.auth.permission.secured.policy=authenticated // after quarkus.http.auth.permission.secured.paths=/rest/* quarkus.http.auth.permission.secured.policy=authenticated quarkus.http.auth.permission.secured.applies-to=JAXRS
Defensive patterns
Strategy: validation
Validate before calling
// Ensure no proactive policy covers @AuthenticationContext paths
boolean proactive = policyPaths.stream().anyMatch(path -> endpointPath.startsWith(path) && !"JAXRS".equals(policyAppliesTo));
if (proactive) throw new IllegalStateException("Policy must use applies-to=JAXRS for " + endpointPath); Try / catch
try { callApi(); } catch (AuthenticationFailedException e) { log.error("Auth ran before @AuthenticationContext matched; add applies-to=JAXRS to policies", e); } Prevention
- Pair every @AuthenticationContext endpoint with JAXRS-scoped policies only
- Avoid wildcard HTTP Security Policy paths that swallow annotated endpoints
- Test annotated endpoints for 401/403 behavior after adding new policies
When it happens
Trigger: A request to a path annotated with @AuthenticationContext matches an HTTP Security Policy requiring authentication; the policy resolves the tenant and authenticates before the JAX-RS chain, so when the annotation's consumer runs (OidcRecorder.accept) it finds tenantConfig != null or routingContext.user() != null and throws AuthenticationFailedException.
Common situations: Endpoints annotated with @AuthenticationContext that are also covered by quarkus.http.auth.permission policies without applies-to=JAXRS; apps migrating to annotation-based authentication while keeping global security policies; wildcard policies accidentally covering annotated endpoints.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The '%1$s' selected with the @Tenant annotation must be used
- Extra steps left over
- Unsupported value type: %s
- Unable to fully read json value
- Unknown start character for json value: %s
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/2b00fc3df38a4ac0.
Report an issue: GitHub.