apache/pulsar · error · AuthenticationException

Not supported

Error message

Not supported

What it means

AuthenticationStateOpenID implements only the asynchronous authenticateAsync() path; the deprecated synchronous AuthenticationState.authenticate(AuthData) method is deliberately unsupported and always throws AuthenticationException("Not supported"). Token validation for OIDC involves async I/O (discovery and JWKS fetching), so the provider only supports the async API and the sync method is a placeholder slated for removal.

Source

Thrown at pulsar-broker-auth-oidc/src/main/java/org/apache/pulsar/broker/authentication/oidc/AuthenticationStateOpenID.java:63

            SSLSession sslSession) {
        this.provider = provider;
        this.remoteAddress = remoteAddress;
        this.sslSession = sslSession;
    }

    @Override
    public String getAuthRole() throws AuthenticationException {
        if (role == null) {
            throw new AuthenticationException("Authentication has not completed");
        }
        return role;
    }

    @Deprecated
    @Override
    public AuthData authenticate(AuthData authData) throws AuthenticationException {
        // This method is not expected to be called and is subject to removal.
        throw new AuthenticationException("Not supported");
    }

    @Override
    public CompletableFuture<AuthData> authenticateAsync(AuthData authData) {
        final String token = new String(authData.getBytes(), UTF_8);
        this.authenticationDataSource = new AuthenticationDataCommand(token, remoteAddress, sslSession);
        return provider
                .authenticateTokenAsync(authenticationDataSource)
                .thenApply(jwt -> {
                    this.role = provider.getRole(jwt);
                    // OIDC requires setting the exp claim, so this should never be null.
                    // We verify it is not null during token validation.
                    this.expiration = jwt.getExpiresAt().getTime();
                    // Single stage authentication, so return null here
                    return null;
                });
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Migrate the calling code to use authenticateAsync(AuthData) and handle the returned CompletableFuture instead of the sync authenticate().
  2. If the caller is framework code you cannot change, upgrade Pulsar/the component to a version where the async API is used for OIDC authentication.
  3. In your own code, stop overriding/calling the deprecated method; treat AuthenticationStateOpenID as async-only.

Example fix

// before
AuthData response = authState.authenticate(authData);
// after
authState.authenticateAsync(authData)
    .thenAccept(response -> { /* continue handshake */ })
    .exceptionally(ex -> { /* handle auth failure */ return null; });
Defensive patterns

Strategy: try-catch

Try / catch

try {
    authState.authenticate(authData); // deprecated, throws for OIDC
} catch (AuthenticationException e) {
    // fall back to the async API
    authState.authenticateAsync(authData).whenComplete((resp, ex) -> { /* ... */ });
}

Prevention

When it happens

Trigger: Any code path that calls the deprecated AuthenticationState.authenticate(AuthData) on an AuthenticationStateOpenID instance — typically legacy broker/framework code or custom plugins written against the pre-async API, or test code invoking the sync method directly (as in authenticateShouldThrowNotImplementedException).

Common situations: Running an older Pulsar broker or third-party authentication interceptor that still drives the deprecated synchronous AuthenticationState API; custom ProtocolHandler or PulsarProxy code that was not migrated to authenticateAsync; unit tests asserting the method stays unimplemented.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/41be92fed9b2daea. Report an issue: GitHub.