apolloconfig/apollo · error · AccessDeniedException

Access is denied

Error message

Access is denied

What it means

Thrown by AppController.requireReadApplicationPermissionForUserToken when the auth type is USER_TOKEN and unifiedPermissionValidator.hasReadApplicationPermission(appId) returns false. This guards read operations (getApp, getEnvClusterInfo, findMissEnvs) so that user-tokens without read access to the specific app are blocked. It is a Spring Security AccessDeniedException, resulting in HTTP 403. For non-USER_TOKEN auth types, this method returns immediately without checking.

Source

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

      return Collections.emptyList();
    }
    return apps.stream()
        .filter(
            app -> app != null && hasReadApplicationPermissionForCurrentIdentity(app.getAppId()))
        .collect(Collectors.toList());
  }

  private boolean hasReadApplicationPermissionForCurrentIdentity(String appId) {
    if (!UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())) {
      return true;
    }
    return unifiedPermissionValidator.hasReadApplicationPermission(appId);
  }

  private void requireReadApplicationPermissionForUserToken(String appId) {
    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        && !unifiedPermissionValidator.hasReadApplicationPermission(appId)) {
      throw new AccessDeniedException("Access is denied");
    }
  }

  private void requireReadApplicationsPermissionForUserToken(List<String> appIds) {
    if (!UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())) {
      return;
    }
    for (String appId : appIds) {
      if (!unifiedPermissionValidator.hasReadApplicationPermission(appId)) {
        throw new AccessDeniedException("Access is denied");
      }
    }
  }

  private List<OpenAppDTO> page(List<OpenAppDTO> apps, Integer page, Integer size) {
    if (apps == null || apps.isEmpty()) {
      return Collections.emptyList();
    }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Grant the user (behind the user-token) read permission for the target app via the Portal.
  2. Switch to a Consumer token that has been assigned the app role.
  3. Verify the appId is correct and belongs to a project the user has access to.
Defensive patterns

Strategy: validation

Validate before calling

// For USER_TOKEN, check read permission before calling read endpoints
if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())) {
    if (!unifiedPermissionValidator.hasReadApplicationPermission(appId)) {
        throw new AccessDeniedException(
            "User token lacks read permission for app: " + appId);
    }
}

Prevention

When it happens

Trigger: Calling getApp(appId), getEnvClusterInfo(appId), or findMissEnvs(appId) with a USER_TOKEN that does not have read-application permission for the specified appId. The user associated with the token is not authorized to view this app.

Common situations: A user-token was created for a user who lacks read access to the target app. The user was removed from the app's authorized list. The appId is from a different team's project. requireReadApplicationsPermissionForUserToken also throws this for batch findApps queries where any appId in the list lacks permission.

Related errors


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