{"record":{"id":"55ea8538ca00d7e1","repo":"apolloconfig/apollo","slug":"user-token-operation-is-not-allowed-s","errorCode":null,"errorMessage":"User token operation is not allowed:%s","messagePattern":"User token operation is not allowed:(.+?)","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/UserTokenService.java","lineNumber":330,"sourceCode":"    scope.setEnvs(emptyToNull(request.getEnvs()));\n    scope.setNamespaces(request.getNamespaces());\n    return scope;\n  }\n\n  private Set<String> normalizeOperations(Set<String> operations) {\n    if (operations == null || operations.isEmpty()) {\n      return null;\n    }\n    Set<String> normalized = new HashSet<>();\n    for (String operation : operations) {\n      if (StringUtils.isBlank(operation)) {\n        continue;\n      }\n      if (!UserTokenOperation.ALL.contains(operation)) {\n        throw new BadRequestException(\"Invalid user token operation:%s\", operation);\n      }\n      if (!isOperationAvailable(operation)) {\n        throw new BadRequestException(\"User token operation is not allowed:%s\", operation);\n      }\n      normalized.add(operation);\n    }\n    return normalized.isEmpty() ? null : normalized;\n  }\n\n  private boolean isOperationAvailable(String operation) {\n    if (UserTokenOperation.RESOURCE_SCOPED.contains(operation)) {\n      return true;\n    }\n    if (UserTokenOperation.APP_CREATE.equals(operation)) {\n      return userPermissionValidator.hasCreateApplicationPermission();\n    }\n    if (UserTokenOperation.USER_MANAGE.equals(operation)) {\n      return userPermissionValidator.hasManageUsersPermission();\n    }\n    if (UserTokenOperation.SYSTEM_ADMIN.equals(operation)) {\n      return userPermissionValidator.isSuperAdmin();","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/UserTokenService.java#L312-L348","documentation":"Thrown by UserTokenService.normalizeOperations() → isOperationAvailable() during token creation when the operation string is recognized (it's in UserTokenOperation.ALL) but the creating user lacks the permission to grant it. Resource-scoped operations (config:read, config:modify, config:release, namespace:create, namespace:delete, cluster:create, app:manage-role) are always available. The privileged operations app:create, user:manage, and system:admin require hasCreateApplicationPermission(), hasManageUsersPermission(), and isSuperAdmin() respectively. BadRequestException → HTTP 400.","triggerScenarios":"A non-privileged user calls createToken() requesting operations=['system:admin'] or ['user:manage'] or ['app:create'] without the corresponding portal permission. For example, a regular developer trying to create a token with system:admin scope.","commonSituations":"A user who recently lost an admin role still tries to create a token with elevated operations. A frontend form shows all operations regardless of the user's current permissions. Misconfigured role assignments in the portal.","solutions":["Only request operations you have permission for — use findAvailableOperations() to check beforehand.","If the user should have access, grant the corresponding portal role/permission (create application, manage users, or super admin).","Remove the privileged operation from the request and retry with only resource-scoped operations."],"exampleFix":"// before\nList<String> available = userTokenService.findAvailableOperations();\nrequest.setOperations(Set.of(\"system:admin\")); // not in available list\n// after\nrequest.setOperations(new HashSet<>(available));","handlingStrategy":"validation","validationCode":"Set<String> available = new HashSet<>(userTokenService.findAvailableOperations());\nSet<String> requested = request.getOperations();\nif (requested != null && !available.containsAll(requested)) {\n    Set<String> disallowed = new HashSet<>(requested);\n    disallowed.removeAll(available);\n    throw new IllegalStateException(\"Operations not permitted for this user: \" + disallowed);\n}\nuserTokenService.createToken(request, operator);","typeGuard":"static boolean isOperationPermitted(UserTokenService svc, String operation) {\n    return svc.findAvailableOperations().contains(operation);\n}","tryCatchPattern":"try {\n    userTokenService.createToken(request, operator);\n} catch (BadRequestException e) {\n    if (e.getMessage().contains(\"not allowed\")) {\n        List<String> available = userTokenService.findAvailableOperations();\n        return Response.status(400).entity(\"Available operations: \" + available).build();\n    }\n    throw e;\n}","preventionTips":["Populate the operation picker from findAvailableOperations() so the UI only shows what the user can use.","Grant the appropriate portal role/permission if the user needs privileged operations."],"tags":["apollo-portal","user-token","authorization","permissions","bad-request"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}