{"record":{"id":"1c784f7b74f871af","repo":"iflytek/astron-agent","slug":"unauthorized-businessexception-responseenum","errorCode":"UNAUTHORIZED","errorMessage":"BusinessException(ResponseEnum.UNAUTHORIZED)","messagePattern":"BusinessException\\(ResponseEnum\\.UNAUTHORIZED\\)","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java","lineNumber":934,"sourceCode":"\n            String currentUid = userInfo.getUid();\n            Long currentSpaceId = SpaceInfoUtil.getSpaceId(); // Assuming this gets current space\n\n            Model model = findAccessibleModel(modelId, currentUid, currentSpaceId);\n            if (model == null) {\n                // Model doesn't exist or user doesn't have access to it\n                return ApiResult.error(ResponseEnum.MODEL_NOT_EXIST);\n            }\n\n            LLMInfoVo modelVo = buildPublicLLMInfoVoFromModel(model, userInfo);\n            return ApiResult.success(modelVo);\n        }\n    }\n\n    public LLMInfoVo getRuntimeModelDetail(Long modelId, String authenticatedUid, Long authorizedSpaceId) {\n        UserInfo userInfo = UserInfoManagerHandler.get();\n        if (!Objects.equals(userInfo.getUid(), authenticatedUid)) {\n            throw new BusinessException(ResponseEnum.UNAUTHORIZED);\n        }\n\n        Model model = findAccessibleModel(modelId, authenticatedUid, authorizedSpaceId);\n        if (model == null) {\n            throw new BusinessException(ResponseEnum.MODEL_NOT_EXIST);\n        }\n        return buildRuntimeLLMInfoVoFromModel(model, userInfo);\n    }\n\n    private Model findAccessibleModel(Long modelId, String uid, Long spaceId) {\n        if (spaceId != null && enterpriseSpaceService.checkUserBelongSpace(spaceId, uid) == null) {\n            return null;\n        }\n\n        LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<Model>()\n                .eq(Model::getId, modelId)\n                .eq(Model::getIsDeleted, 0);\n        if (spaceId != null) {","sourceCodeStart":916,"sourceCodeEnd":952,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java#L916-L952","documentation":"UNAUTHORIZED is thrown by getRuntimeModelDetail when the currently authenticated user's uid does not match the authenticatedUid argument passed by the caller. This is an explicit identity-consistency check at the start of the method: the runtime model detail endpoint may only be read by the same user whose authentication context was verified upstream.","triggerScenarios":"Calling getRuntimeModelDetail (public entry, e.g. from a chat/runtime controller) where the UserInfoManagerHandler thread-local user differs from the authenticatedUid parameter — e.g. forged/missing auth context, admin-tooling calling with another user's uid, or a token/session mismatch after re-login.","commonSituations":"Expired or replaced JWT while an old cached uid is passed along; service-to-service calls forwarding a different uid header than the one in the security context; developer tools invoking the method with a hardcoded uid.","solutions":["Ensure the caller passes the uid taken from the same authenticated security context (UserInfoManagerHandler.get().getUid()), not a client-supplied value.","Re-authenticate: refresh the token/session so the security context and forwarded uid match.","Fix the upstream call site to derive authenticatedUid from the current request's auth filter rather than trusting request headers/body.","Check auth filter/ordering so UserInfoManagerHandler is populated before this method runs."],"exampleFix":"// before\nllmInfoVo = modelService.getRuntimeModelDetail(modelId, request.getHeader(\"uid\"), spaceId); // spoofable\n// after\nString uid = UserInfoManagerHandler.get().getUid();\nllmInfoVo = modelService.getRuntimeModelDetail(modelId, uid, spaceId);","handlingStrategy":"type-guard","validationCode":"if (!Objects.equals(UserInfoManagerHandler.get().getUid(), authenticatedUid)) { throw new SecurityException(\"uid mismatch before calling getRuntimeModelDetail\"); }","typeGuard":"boolean sameIdentity(String authenticatedUid) { UserInfo u = UserInfoManagerHandler.get(); return u != null && Objects.equals(u.getUid(), authenticatedUid); }","tryCatchPattern":"try { return modelService.getRuntimeModelDetail(modelId, authenticatedUid, spaceId); } catch (BusinessException e) { if (\"UNAUTHORIZED\".equals(e.getCode())) { forceReauth(); } throw e; }","preventionTips":["Always derive authenticatedUid from the server-side security context, never from client headers/body.","Re-read UserInfoManagerHandler after token refresh so contexts stay in sync.","In inter-service calls, propagate the authenticated uid in a trusted header validated by the auth filter.","Add an assertion/log when uid mismatch occurs to detect miswired call sites early."],"tags":["authorization","auth","uid-mismatch","security"],"backgroundTag":"permission-denied","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}