apache/pulsar · error · RestException

Unauthorized to validateBrokerOperation for originalPrincipa

Error message

Unauthorized to validateBrokerOperation for originalPrincipal [${principal}] and clientAppId [${clientAppId}] about operation [${operation}] on broker [${brokerId}]

What it means

validateBrokerOperationAsync consults the AuthorizationService (allowBrokerOperationAsync) when authentication is enabled and authorization is enabled; if the provider denies the requested broker operation for the original principal and clientAppId, it throws HTTP 401 UNAUTHORIZED with this message. Unlike error 67, this path only checks broker-operation authorization (no superuser bypass).

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java:589

                    throw new RestException(Status.UNAUTHORIZED,
                            String.format("Unauthorized to validateBothSuperuserAndBrokerOperation for"
                                          + " originalPrincipal [%s] and clientAppId [%s] "
                                          + "about operation [%s] on broker [%s]",
                                    originalPrincipal(), clientAppId(), operation.toString(), brokerId));
                });
    }

    private CompletableFuture<Void> validateBrokerOperationAsync(String cluster, String brokerId,
                                                                 BrokerOperation operation) {
        final var pulsar = pulsar();
        if (pulsar.getBrokerService().isAuthenticationEnabled()
            && pulsar.getBrokerService().isAuthorizationEnabled()) {
            return pulsar.getBrokerService().getAuthorizationService()
                    .allowBrokerOperationAsync(cluster, brokerId, operation, originalPrincipal(),
                            clientAppId(), clientAuthData())
                    .thenAccept(isAuthorized -> {
                        if (!isAuthorized) {
                            throw new RestException(Status.UNAUTHORIZED,
                                    String.format("Unauthorized to validateBrokerOperation for"
                                                  + " originalPrincipal [%s] and clientAppId [%s] "
                                                  + "about operation [%s] on broker [%s]",
                                            originalPrincipal(), clientAppId(), operation.toString(), brokerId));
                        }
                    });
        }
        return CompletableFuture.completedFuture(null);
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Grant the principal's role the required broker-operation permission in your AuthorizationProvider / external store, matching the exact role name shown as originalPrincipal in the message.
  2. Add the role to superUserRoles if it should bypass authorization entirely (superusers skip this check at the validateBothSuperuserAndBrokerOperation layer).
  3. Review and fix custom AuthorizationProvider logic (or switch to the default PulsarAuthorizationProvider) so allowBrokerOperationAsync returns true for legitimate admin roles.
  4. Verify the client is sending valid credentials conveying the intended role (expired/rotated token is a frequent cause).
Defensive patterns

Strategy: validation

Validate before calling

// ensure the role is authorized for broker operations before calling admin APIs
boolean allowed = authorizationProvider
        .allowBrokerOperationAsync(cluster, brokerId, operation, role, appId, authData).join();
if (!allowed) { throw new SecurityException("role not authorized: " + role); }

Try / catch

try {
    brokerOperationValidation(...).get();
} catch (ExecutionException e) {
    if (e.getCause() instanceof PulsarAdminException.NotAuthorizedException) {
        handleDenied(operation, brokerId);
    }
}

Prevention

When it happens

Trigger: Called via brokerOperationValidation from broker admin endpoints when: authentication enabled, authorization enabled, and the authorization provider returns false for allowBrokerOperationAsync(cluster, brokerId, operation, originalPrincipal, clientAppId, clientAuthData).

Common situations: Custom AuthorizationProvider rules not covering the BrokerOperation being requested; role absent from the external authorization store; wildcard/regex role matching disabled so 'admin-*' patterns don't apply; client auth data (peer cert / token) missing role claims after a TLS or token migration.

Understand the failure class

Related errors


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