{"record":{"id":"44ab48da67d86c94","repo":"apache/druid","slug":"authresult-geterrormessage-44ab48","errorCode":null,"errorMessage":"<authResult.getErrorMessage()>","messagePattern":"<authResult\\.getErrorMessage\\(\\)>","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java","lineNumber":132,"sourceCode":"      AuthorizerMapper authorizerMapper\n  )\n  {\n    ResourceAction resourceAction = createDatasourceResourceAction(datasource, req);\n    AuthorizationResult authResult = authorizeResourceAction(req, resourceAction, authorizerMapper);\n    if (!authResult.allowAccessWithNoRestriction()) {\n      if (authResult.allowBasicAccess()) {\n        // Basic access was granted, but access was restricted by a policy.\n        // This is checked to avoid double emitting the forbidden metric if the basic access was denied,\n        // since the authorizeResourceAction method already emits the metric in that case.\n        emitAuthMetric(\n            authorizerMapper.getServiceEmitter(),\n            authenticationResultFromRequest(req),\n            resourceAction,\n            METRIC_FORBIDDEN,\n            authResult.getErrorMessage()\n        );\n      }\n      throw new ForbiddenException(authResult.getErrorMessage());\n    }\n  }\n\n  /**\n   * Returns the authentication information for a request.\n   *\n   * @param request http request\n   * @return authentication result\n   * @throws IllegalStateException if the request was not authenticated\n   */\n  public static AuthenticationResult authenticationResultFromRequest(final HttpServletRequest request)\n  {\n    final AuthenticationResult authenticationResult = (AuthenticationResult) request.getAttribute(\n        AuthConfig.DRUID_AUTHENTICATION_RESULT\n    );\n\n    if (authenticationResult == null) {\n      throw new ISE(\"Null authentication result\");","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java#L114-L150","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Grant the user's role unrestricted READ (and required action) permissions on the datasource in the authorizer configuration.","Remove or relax row-level policies that restrict the datasource for this user.","Verify the correct authenticator/authorizer chain is configured so the user maps to the intended roles.","If the operation legitimately should be restricted, use an API that supports filtered access instead."],"exampleFix":"// before: user has row-filtered READ only -> 403 ForbiddenException\n// after: in authorizer config, grant full datasource permission\n//   authorizer:\n//     roles:\n//       datasourceReader:\n//         permissions:\n//           - resource: {name: \"wikipedia\", type: \"DATASOURCE\"}\n//             action: READ\n//           - resource: {name: \".*\", type: \"DATASOURCE\"}\n//             action: READ\n//         users: [\"alice\"]","handlingStrategy":"try-catch","validationCode":"final Access access = AuthorizationUtils.authorizeResourceAction(req, resourceAction, authorizerMapper);\nif (!access.isAllow()) { /* skip call or request higher privilege */ }","typeGuard":"if (authorizerMapper == null || authorizerMapper.getAuthorizer(authResult.getAuthorizerName()) == null) { /* misconfigured authorizer; fix config before calling */ }","tryCatchPattern":"try { AuthorizationUtils.verifyUnrestrictedAccessToDatasource(req, datasource, authorizerMapper); }\ncatch (ForbiddenException e) { log.warn(\"Unrestricted access denied for datasource %s: %s\", datasource, e.getMessage()); }\n","preventionTips":["Grant unrestricted READ permissions for datasources used by full-access endpoints.","Keep authorizer role mappings in version control and review them on user onboarding.","Test new roles against the endpoints they will call before rollout."],"tags":["authorization","http","security","forbidden"],"backgroundTag":"permission-denied","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}