quarkusio/quarkus · error · IllegalArgumentException

Authentication has already been set

Error message

Authentication has already been set

What it means

Thrown by HttpPermission's validateAuthenticationNotSetYet when the authentication mechanism is configured twice. A permission can define at most one authentication setup; once authMechanism is non-null, a second authentication assignment is rejected so the resulting policy is never ambiguous.

Source

Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java:398

            this.authMechanism = null;
            this.authorizationPolicy = null;
            this.shared = false;
            this.methods = null;
            this.applyToJaxRs = false;
        }

        private void requireAuthenticationByDefault() {
            // if someone selects authentication mechanism and doesn't configure
            // authorization policy, it is reasonable to expect they require authentication
            // similarly to what we do with @BasicAuthentication etc.
            if (authorizationPolicy == null) {
                authenticated();
            }
        }

        private void validateAuthenticationNotSetYet() {
            if (authMechanism != null) {
                throw new IllegalArgumentException("Authentication has already been set");
            }
        }

        private void validateAuthorizationNotSetYet() {
            if (authMechanism == null && authorizationPolicy != null) {
                throw new IllegalArgumentException("Authorization has already been set");
            }
        }

        @Override
        public HttpPermission basic() {
            return authenticatedWith(BasicAuthentication.AUTH_MECHANISM_SCHEME);
        }

        @Override
        public HttpPermission form() {
            return authenticatedWith(FormAuthentication.AUTH_MECHANISM_SCHEME);
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call only one authentication method per HttpPermission; remove the redundant authenticated()/authenticatedWith(...) call.
  2. If multiple mechanisms should be allowed, use authenticatedWith(Set<String> schemes) once with all schemes instead of repeated calls.
  3. Split into separate permissions (separate paths() calls) if different paths need different mechanisms.

Example fix

// before
httpSecurity.paths("/api/*").basic().bearer(); // throws
// after
httpSecurity.paths("/api/*").authenticatedWith(Set.of("basic", "Bearer"));
Defensive patterns

Strategy: validation

Validate before calling

// ensure only one auth call: track in a local builder wrapper
boolean authSet = false;
if (authSet) throw new IllegalStateException("auth already configured");

Try / catch

try { perm.authenticatedWith(mech); } catch (IllegalArgumentException e) { if (!e.getMessage().contains("Authentication has already been set")) throw e; }

Prevention

When it happens

Trigger: Calling authenticatedWith(...) twice, or authenticated() followed by authenticatedWith(...)/basic()/form()/bearer()/mTLS()/webAuthn()/authorizationCodeFlow() on the same HttpPermission instance.

Common situations: Chaining .basic().bearer() hoping to allow multiple mechanisms; conditional code that calls different auth methods on the same permission object; copy-paste refactors of fluent chains.

Understand the failure class

Related errors


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