apolloconfig/apollo · error · AccessDeniedException

Metadata read permission is required

Error message

Metadata read permission is required

What it means

HTTP 403 (AccessDeniedException). Thrown by OrganizationController.requireMetadataReadPermissionForUserToken: auth type USER_TOKEN and UnifiedPermissionValidator.hasAnyUserTokenOperation(UserTokenOperation.METADATA_READ) is false. The user-token lacks the dedicated METADATA_READ user-token operation grant, so it may not list organizations through the OpenAPI.

Source

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

  private final OrganizationOpenApiService organizationOpenApiService;
  private final UnifiedPermissionValidator unifiedPermissionValidator;

  public OrganizationController(OrganizationOpenApiService organizationOpenApiService,
      UnifiedPermissionValidator unifiedPermissionValidator) {
    this.organizationOpenApiService = organizationOpenApiService;
    this.unifiedPermissionValidator = unifiedPermissionValidator;
  }

  @Override
  public ResponseEntity<List<OpenOrganizationDto>> getOrganization() {
    requireMetadataReadPermissionForUserToken();
    return ResponseEntity.ok(organizationOpenApiService.getOrganizations());
  }

  private void requireMetadataReadPermissionForUserToken() {
    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())
        && !unifiedPermissionValidator.hasAnyUserTokenOperation(UserTokenOperation.METADATA_READ)) {
      throw new AccessDeniedException("Metadata read permission is required");
    }
  }
}

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Grant the user-token the METADATA_READ user-token operation and retry.
  2. Use a portal USER session to fetch organizations (USER auth bypasses this gate).
  3. Confirm the token's allowed operations include METADATA_READ before calling.
  4. Avoid calling the org metadata endpoint with a narrowly scoped token.

Example fix

// before: user-token without METADATA_READ
client.withUserToken(token).getOrganizations(); // 403

// after: add METADATA_READ op to the token, or use portal USER
admin.grantUserTokenOperation(tokenId, UserTokenOperation.METADATA_READ);
client.withUserToken(token).getOrganizations();
Defensive patterns

Strategy: validation

Validate before calling

// For USER_TOKEN: confirm METADATA_READ operation is granted before fetching orgs.
boolean ok = tokenHasOperation(token, "METADATA_READ");
if (!ok) { /* grant op or use portal USER; do not call getOrganization */ }

Type guard

null

Try / catch

try {
  client.withUserToken(token).getOrganizations();
} catch (HttpServerErrorException.Forbidden e) {
  // Metadata read permission is required -> add METADATA_READ op or use USER
}

Prevention

When it happens

Trigger: GET /openapi/v1/organizations (getOrganization) using a user-token that was not granted the METADATA_READ operation. Portal SSO users (USER) bypass this gate; CONSUMER tokens are handled separately.

Common situations: A user-token created for config read/write being reused to fetch org metadata without the METADATA_READ operation; token operations scoped down after auditing; new integration assuming all user-tokens can read metadata.

Related errors


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