apache/druid · error · ForbiddenException

<authResult.getErrorMessage()>

Error message

<authResult.getErrorMessage()>

What it means

AuthorizationUtils.verifyUnrestrictedAccessToDatasource throws ForbiddenException when the authenticated user is authorized to access a datasource only with restrictions (policies/row filters), not with unrestricted access. Druid throws it because some HTTP resources require full, unfiltered access to a datasource before serving data. The message carries the authorizer-supplied error text explaining why access was restricted or denied.

Source

Thrown at server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java:132

      AuthorizerMapper authorizerMapper
  )
  {
    ResourceAction resourceAction = createDatasourceResourceAction(datasource, req);
    AuthorizationResult authResult = authorizeResourceAction(req, resourceAction, authorizerMapper);
    if (!authResult.allowAccessWithNoRestriction()) {
      if (authResult.allowBasicAccess()) {
        // Basic access was granted, but access was restricted by a policy.
        // This is checked to avoid double emitting the forbidden metric if the basic access was denied,
        // since the authorizeResourceAction method already emits the metric in that case.
        emitAuthMetric(
            authorizerMapper.getServiceEmitter(),
            authenticationResultFromRequest(req),
            resourceAction,
            METRIC_FORBIDDEN,
            authResult.getErrorMessage()
        );
      }
      throw new ForbiddenException(authResult.getErrorMessage());
    }
  }

  /**
   * Returns the authentication information for a request.
   *
   * @param request http request
   * @return authentication result
   * @throws IllegalStateException if the request was not authenticated
   */
  public static AuthenticationResult authenticationResultFromRequest(final HttpServletRequest request)
  {
    final AuthenticationResult authenticationResult = (AuthenticationResult) request.getAttribute(
        AuthConfig.DRUID_AUTHENTICATION_RESULT
    );

    if (authenticationResult == null) {
      throw new ISE("Null authentication result");

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Grant the user's role unrestricted READ (and required action) permissions on the datasource in the authorizer configuration.
  2. Remove or relax row-level policies that restrict the datasource for this user.
  3. Verify the correct authenticator/authorizer chain is configured so the user maps to the intended roles.
  4. If the operation legitimately should be restricted, use an API that supports filtered access instead.

Example fix

// before: user has row-filtered READ only -> 403 ForbiddenException
// after: in authorizer config, grant full datasource permission
//   authorizer:
//     roles:
//       datasourceReader:
//         permissions:
//           - resource: {name: "wikipedia", type: "DATASOURCE"}
//             action: READ
//           - resource: {name: ".*", type: "DATASOURCE"}
//             action: READ
//         users: ["alice"]
Defensive patterns

Strategy: try-catch

Validate before calling

final Access access = AuthorizationUtils.authorizeResourceAction(req, resourceAction, authorizerMapper);
if (!access.isAllow()) { /* skip call or request higher privilege */ }

Type guard

if (authorizerMapper == null || authorizerMapper.getAuthorizer(authResult.getAuthorizerName()) == null) { /* misconfigured authorizer; fix config before calling */ }

Try / catch

try { AuthorizationUtils.verifyUnrestrictedAccessToDatasource(req, datasource, authorizerMapper); }
catch (ForbiddenException e) { log.warn("Unrestricted access denied for datasource %s: %s", datasource, e.getMessage()); }

Prevention

When it happens

Trigger: Calling an endpoint that routes through verifyUnrestrictedAccessToDatasource (e.g. datasource metadata/lookup HTTP resources) while the user's authorizer grants basic access but applies a policy, or denies access entirely.

Common situations: Users granted READ with row-level filters attempting to use endpoints that require full table access; overly restrictive role definitions in the authorizer config; newly created users lacking an authorization role.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/44ab48da67d86c94. Report an issue: GitHub.