{"record":{"id":"3abd61eb7ba9b303","repo":"apache/dolphinscheduler","slug":"user-no-operation-perm","errorCode":"USER_NO_OPERATION_PERM","errorMessage":"USER_NO_OPERATION_PERM","messagePattern":"USER_NO_OPERATION_PERM","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java","lineNumber":89,"sourceCode":"        }\n        IPage<AccessToken> accessTokenList = accessTokenDao.queryAccessTokenPage(page, searchVal, userId);\n        pageInfo.setTotal((int) accessTokenList.getTotal());\n        pageInfo.setTotalList(accessTokenList.getRecords());\n        return pageInfo;\n    }\n\n    /**\n     * query access token for specified user\n     *\n     * @param loginUser login user\n     * @param userId    user id\n     * @return token list for specified user\n     */\n    @Override\n    public List<AccessToken> queryAccessTokenByUser(User loginUser, Integer userId) {\n        // no permission\n        if (loginUser.getUserType().equals(UserType.GENERAL_USER) && loginUser.getId() != userId) {\n            throw new ServiceException(Status.USER_NO_OPERATION_PERM);\n        }\n        userId = loginUser.getUserType().equals(UserType.ADMIN_USER) ? 0 : userId;\n        // query access token for specified user\n        List<AccessToken> accessTokenList = this.accessTokenDao.queryAccessTokenByUser(userId);\n        return accessTokenList;\n    }\n\n    /**\n     * create token\n     *\n     * @param loginUser loginUser\n     * @param userId token for user\n     * @param expireTime token expire time\n     * @param token token string (if it is absent, it will be automatically generated)\n     * @return create result code\n     */\n    @SuppressWarnings(\"checkstyle:WhitespaceAround\")\n    @Override","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java#L71-L107","documentation":"queryAccessTokenByUser enforces that a GENERAL_USER may only query their own access tokens; if loginUser.getUserType() is GENERAL_USER and loginUser.getId() != userId, it throws ServiceException(Status.USER_NO_OPERATION_PERM). Admin users bypass this check, and for admins the userId is normalized to 0 to return all tokens.","triggerScenarios":"Calling the access-token query API (GET /users/{userId}/access-tokens) as a non-admin user while passing a different user's userId, e.g. tampering with the userId path/query parameter or a UI sending the wrong id.","commonSituations":"Frontend caching another user's id after account switching; API consumers iterating userIds to enumerate tokens; automated scripts reusing a general-user PAT to fetch other users' tokens.","solutions":["Query access tokens with your own userId, or authenticate as an ADMIN_USER when querying tokens on behalf of other users.","Fix the calling client to pass the id of the currently logged-in user rather than a hard-coded or stale id.","If cross-user visibility is required, have an administrator perform the query.","Check UI/session handling so the correct current user id is sent after login switches."],"exampleFix":"// before: general user querying another user's tokens\naccessTokenService.queryAccessTokenByUser(loginUser, otherUserId);\n\n// after: query own tokens, or use an admin account\naccessTokenService.queryAccessTokenByUser(loginUser, loginUser.getId());","handlingStrategy":"validation","validationCode":"// client-side check before calling the API\nif (loginUser.userType == GENERAL_USER && loginUser.id != targetUserId) {\n    throw new SecurityException(\"General users may only query their own access tokens\");\n}","typeGuard":"boolean canQuery(User loginUser, Integer targetUserId) {\n    return loginUser != null && targetUserId != null\n        && (loginUser.getUserType() == UserType.ADMIN_USER || loginUser.getId() == targetUserId.intValue());\n}","tryCatchPattern":"try {\n    return accessTokenService.queryAccessTokenByUser(loginUser, userId);\n} catch (ServiceException e) {\n    if (e.getCode() == Status.USER_NO_OPERATION_PERM) {\n        return Collections.emptyList(); // or surface 403 to caller\n    }\n    throw e;\n}","preventionTips":["Always pass the logged-in user's own id for non-admin callers.","Fix UI state so stale user ids from previous sessions are not reused.","Use admin credentials for cross-user token administration.","Never enumerate other users' ids with a general-user token."],"tags":["authorization","access-token","permission","api"],"backgroundTag":"permission-denied","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}