apolloconfig/apollo · error · AccessDeniedException

Access is denied

Error message

Access is denied

What it means

HTTP 403 (AccessDeniedException). Thrown by NamespaceController.requireConfigReadForUserToken: auth type USER_TOKEN and UnifiedPermissionValidator.shouldHideConfigToCurrentUser is true for appId/env/cluster/namespace. The user-token caller is denied read access to a namespace marked hidden from them. Identical policy to error 86 but on the NamespaceController read surface.

Source

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

        && unifiedPermissionValidator.shouldHideConfigToCurrentUser(appId, env, clusterName,
            namespaceName);
  }

  private boolean shouldDenyConfigReadToCurrentIdentity(String appId, String env,
      String clusterName, String namespaceName) {
    String authType = UserIdentityContextHolder.getAuthType();
    return (UserIdentityConstants.USER.equals(authType)
        || UserIdentityConstants.USER_TOKEN.equals(authType))
        && unifiedPermissionValidator.shouldHideConfigToCurrentUser(appId, env, clusterName,
            namespaceName);
  }

  private void requireConfigReadForUserToken(String appId, String env, String clusterName,
      String namespaceName) {
    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        && unifiedPermissionValidator.shouldHideConfigToCurrentUser(appId, env, clusterName,
            namespaceName)) {
      throw new AccessDeniedException("Access is denied");
    }
  }

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

  private void requireCreateNamespacesPermissionForUserToken(
      List<OpenCreateNamespaceDTO> namespaces) {
    if (!UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        || CollectionUtils.isEmpty(namespaces)) {
      return;
    }
    for (OpenCreateNamespaceDTO namespace : namespaces) {
      if (namespace == null || StringUtils.isBlank(namespace.getAppId())) {

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Grant the token owner read/view permission on the namespace or clear the hidden flag.
  2. Switch to a USER session or a CONSUMER token that is authorized for that namespace.
  3. Verify the namespace is meant to be visible to the caller before retrying.
  4. Stop automated reads of namespaces the token owner cannot see.

Example fix

// before: user-token owner excluded from hidden namespace
client.withUserToken(token).getNamespace(appId, env, cluster, ns); // 403

// after: authorize the owner, or use an allowed identity
admin.grantView(appId, ns, token.getOwnerId());
client.withUserToken(token).getNamespace(appId, env, cluster, ns);
Defensive patterns

Strategy: validation

Validate before calling

// For USER_TOKEN namespace reads: confirm namespace visible to the owner.
boolean hidden = shouldHide(tokenOwner, appId, env, cluster, ns);
if (hidden) { /* grant view or skip; do not call getNamespace */ }

Type guard

null

Try / catch

try {
  client.withUserToken(token).getNamespace(appId, env, cluster, ns);
} catch (HttpServerErrorException.Forbidden e) {
  // Access is denied -> hidden namespace; grant view or switch identity
}

Prevention

When it happens

Trigger: GET namespace/items read endpoints on NamespaceController using a user-token for a restricted/hidden namespace whose visibility rule excludes the token owner.

Common situations: User-token owned by an unauthorized user reading a secrets namespace; namespace hidden after token issuance; cross-env token reuse where the owner has no view right.

Related errors


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