apolloconfig/apollo · error · AccessDeniedException

Assign role permission is required

Error message

Assign role permission is required

What it means

HTTP 403 (AccessDeniedException). Thrown by PermissionController.requirePortalUserOrAssignRolePermission when none of the allow-paths match: caller is not a plain USER, OR is a CONSUMER without app-scoped hasAssignRolePermission(appId), OR is a USER_TOKEN without namespace-scoped hasAssignRolePermission(appId,env,cluster,namespace). Used to gate role-assignment writes — assigning roles requires either being a portal user or holding the ASSIGN_ROLE permission at the right scope.

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/PermissionController.java:314

  private void requirePortalUserOrAssignRolePermission(String appId) {
    requirePortalUserOrAssignRolePermission(appId, null, null, null);
  }

  private void requirePortalUserOrAssignRolePermission(String appId, String env, String clusterName,
      String namespaceName) {
    String authType = UserIdentityContextHolder.getAuthType();
    if (UserIdentityConstants.USER.equals(authType)) {
      return;
    }
    if (UserIdentityConstants.CONSUMER.equals(authType)
        && unifiedPermissionValidator.hasAssignRolePermission(appId)) {
      return;
    }
    if (UserIdentityConstants.USER_TOKEN.equals(authType) && unifiedPermissionValidator
        .hasAssignRolePermission(appId, env, clusterName, namespaceName)) {
      return;
    }
    throw new AccessDeniedException("Assign role permission is required");
  }

  private void requireAppRoleReadPermission(String appId) {
    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        && !unifiedPermissionValidator.hasAssignRolePermission(appId)) {
      throw new AccessDeniedException("Assign role permission is required");
    }
  }

  private void requireAppRoleReadPermission(String appId, String env, String clusterName,
      String namespaceName) {
    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        && !unifiedPermissionValidator.hasAssignRolePermission(appId, env, clusterName,
            namespaceName)) {
      throw new AccessDeniedException("Assign role permission is required");
    }
  }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Grant the caller ASSIGN_ROLE permission at the required scope: app-level for CONSUMER, namespace-level (appId/env/cluster/namespace) for USER_TOKEN.
  2. Perform role assignment interactively as a portal USER (USER auth always passes this gate).
  3. Verify the appId/env/cluster/namespace in the request match the scope of the granted ASSIGN_ROLE permission.
  4. Pre-check hasAssignRolePermission before submitting the assignment.

Example fix

// before: CONSUMER token without ASSIGN_ROLE on appX
client.withConsumerToken(token).assignRole("appX", role); // 403

// after: grant ASSIGN_ROLE (app scope) to the token, or use portal USER
admin.grantAssignRole("appX", token);
client.withConsumerToken(token).assignRole("appX", role);
Defensive patterns

Strategy: validation

Validate before calling

// Before role assignment: confirm ASSIGN_ROLE at the right scope.
String authType = currentAuthType();
boolean ok;
if ("CONSUMER".equals(authType))      ok = hasAssignRole(token, appId);
else if ("USER_TOKEN".equals(authType)) ok = hasAssignRole(token, appId, env, cluster, ns);
else                                    ok = "USER".equals(authType);
if (!ok) { /* grant ASSIGN_ROLE or use portal USER; do not call assignRole */ }

Type guard

null

Try / catch

try {
  client.assignRole(appId, env, cluster, ns, role);
} catch (HttpServerErrorException.Forbidden e) {
  // Assign role permission is required -> grant ASSIGN_ROLE at the right scope and retry
}

Prevention

When it happens

Trigger: POST role-assignment endpoints (grant/remove roles) using a CONSUMER token without ASSIGN_ROLE permission on the app, or a USER_TOKEN without namespace-scoped ASSIGN_ROLE permission.

Common situations: OpenAPI consumer token reused for role management it was never granted; user-token scoped to config ops attempting role assignment; permission revoked after automation was set up; attempting to assign roles on an app the token is not scoped to.

Related errors


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/99aea5df7544f66d. Report an issue: GitHub.