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

  1. Authenticate as user 'alice' (obtain a token for alice from Keycloak/WireMock) before calling the endpoint.
  2. Check the Authorization header is set to 'Bearer <alice-token>' and the token is valid/not expired.
  3. Verify the token's preferred_username claim actually resolves to 'alice' in your tenant configuration.
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/56028134623b8b55. Report an issue: GitHub.