quarkusio/quarkus · error · UnauthorizedException
Only Alice is allowed to access this endpoint
Error message
Only Alice is allowed to access this endpoint
What it means
This UnauthorizedException is thrown by the OrderResource POST endpoint when the authenticated principal is not 'alice'. It exists in the test to guarantee the SecurityIdentity is resolved eagerly and to verify that when the corresponding event is later consumed, the identity from the original request context is no longer available (a brand-new request context).
Source
Thrown at integration-tests/oidc-wiremock/src/main/java/io/quarkus/it/keycloak/OrderResource.java:29
import io.quarkus.security.UnauthorizedException;
import io.quarkus.security.identity.SecurityIdentity;
import io.vertx.core.eventbus.EventBus;
@Path("order/bearer")
public class OrderResource {
@Inject
EventBus eventBus;
@Inject
SecurityIdentity identity;
@POST
public void order(String product, @HeaderParam(AUTHORIZATION) String bearer) {
if (!"alice".equals(identity.getPrincipal().getName())) {
// point here is to make sure that identity is resolved and later, when the event is consumed
// this identity won't be available as it will be brand-new request context
throw new UnauthorizedException("Only Alice is allowed to access this endpoint");
}
String rawToken = bearer.substring("Bearer ".length());
eventBus.publish("product-order", new Product(product, 1, rawToken));
}
@GET
public String acquiredIdentities() {
return String.join(" ", OrderService.IDENTITY_REPOSITORY);
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Authenticate as user 'alice' (obtain a token for alice from Keycloak/WireMock) before calling the endpoint.
- Check the Authorization header is set to 'Bearer <alice-token>' and the token is valid/not expired.
- Verify the token's preferred_username claim actually resolves to 'alice' in your tenant configuration.
- If intentionally testing denial, expect and assert the 401 response in the test instead of treating it as a failure.
Example fix
// before (wrong user)
String token = getToken("bob");
given().auth().oauth2(token).post("/order"); // 401 Only Alice is allowed
// after
String token = getToken("alice");
given().auth().oauth2(token).body("product").post("/order"); // 200 Defensive patterns
Strategy: try-catch
Validate before calling
String user = identity.getPrincipal().getName();
if (!"alice".equals(user)) {
throw new UnauthorizedException("Only Alice is allowed to access this endpoint");
} Type guard
boolean isAlice(SecurityIdentity identity) {
return identity != null && identity.getPrincipal() != null
&& "alice".equals(identity.getPrincipal().getName());
} Try / catch
try {
eventBus.publish("product-order", new Product(product, 1, rawToken));
} catch (UnauthorizedException e) {
log.warnv("denied order for user {0}", identity.getPrincipal().getName());
throw e; // map to 401 via exception mapper
} Prevention
- Obtain tokens for the correct test user before calling identity-gated endpoints.
- Assert the preferred_username claim when debugging principal mismatches.
- Prefer @Authorization/@RolesAllowed or programmatic SecurityIdentity checks over ad-hoc string compares in production code.
- Remember the identity is bound to the request context when consumed asynchronously on the event bus.
When it happens
Trigger: POST /order is called with an authenticated user whose principal name is not 'alice', e.g. 'bob' or any other valid Keycloak/WireMock token subject.
Common situations: Testing RBAC with different test users, forgetting to switch from an admin token to alice's token in the test client, or token mapping/claim changes causing the principal name to differ from 'alice'.
Related errors
- Extra steps left over
- Unsupported value type: %s
- Unable to fully read json value
- Unknown start character for json value: %s
- Json object ended without }
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/56028134623b8b55.
Report an issue: GitHub.