apolloconfig/apollo · error · AccessDeniedException
Metadata read permission is required
Error message
Metadata read permission is required
What it means
Thrown by EnvController.requireMetadataReadPermissionForUserToken when a USER_TOKEN identity does not have the METADATA_READ operation scope. The getEnvs endpoint returns the list of configured environments, which Apollo treats as metadata. For USER_TOKEN auth, this requires the token to have any operation in the METADATA_READ bundle (all operations except user:manage). Maps to HTTP 403 AccessDeniedException.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/EnvController.java:51
private final EnvOpenApiService envOpenApiService;
private final UnifiedPermissionValidator unifiedPermissionValidator;
public EnvController(EnvOpenApiService envOpenApiService,
UnifiedPermissionValidator unifiedPermissionValidator) {
this.envOpenApiService = envOpenApiService;
this.unifiedPermissionValidator = unifiedPermissionValidator;
}
@Override
public ResponseEntity<List<String>> getEnvs() {
requireMetadataReadPermissionForUserToken();
return ResponseEntity.ok(envOpenApiService.getEnvs());
}
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
- Grant the USER_TOKEN at least one operation from the METADATA_READ bundle (config:read, config:modify, config:release, namespace:create, namespace:delete, cluster:create, app:create, app:manage-role, system:admin) in the Portal.
- Use a CONSUMER token for environment listing, since the METADATA_READ check only applies to USER_TOKEN auth.
- If the token's sole purpose is user management, make a separate API call with a broader token for environment metadata.
Defensive patterns
Strategy: validation
Validate before calling
// Before calling GET /envs with a USER_TOKEN, verify the token has metadata-read scope
if (authType.equals("USER_TOKEN") && !tokenHasAnyMetadataReadOperation()) {
// The token needs at least one of: config:read, config:modify, config:release,
// namespace:create, namespace:delete, cluster:create, app:create, app:manage-role, system:admin
throw new SecurityException("USER_TOKEN lacks metadata-read scope. Add an operation grant.");
} Try / catch
try {
return client.get("/openapi/v1/envs");
} catch (AccessDeniedException e) {
if (e.getMessage().contains("Metadata read")) {
// Use a different token with broader scope, or fall back to config-based env list
return getEnvsFromConfig();
}
throw e;
} Prevention
- When generating a USER_TOKEN for general-purpose use, include at least config:read scope.
- Reserve user:manage-only tokens strictly for user management APIs.
- Document which scopes are needed for each OpenAPI endpoint category.
When it happens
Trigger: GET /openapi/v1/envs called with a USER_TOKEN that has only user:manage scope or no scopes at all. The hasAnyUserTokenOperation(UserTokenOperation.METADATA_READ) check fails because the token lacks any metadata-read-capable operation.
Common situations: A narrowly-scoped user token (e.g. only user:manage for user administration) is reused for a general environment-listing API call. The token is valid but its scope doesn't include metadata-read operations.
Related errors
- Create cluster permission is required
- Access is denied
- Access is denied
- Super admin permission is required
- App admin permission is required
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/7937b3ca6a265c34.
Report an issue: GitHub.