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
- Grant the user (behind the user-token) read permission for the target app via the Portal.
- Switch to a Consumer token that has been assigned the app role.
- 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
- Pre-check hasReadApplicationPermission for user-tokens before read operations.
- Use Consumer tokens with assigned app roles for automated read-heavy workflows.
- For batch findApps calls, validate all appIds have read permission before the request.
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
- Assign role permission is required
- App not found: {appId}
- Create application permission is required
- Access is denied
- Access is denied
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/48cd769a5400906c.
Report an issue: GitHub.