{"record":{"id":"427b024a1b815223","repo":"alibaba/nacos","slug":"session-expired","errorCode":null,"errorMessage":"session expired!","messagePattern":"session expired!","errorType":"exception","errorClass":"HttpSessionRequiredException","httpStatus":null,"severity":"error","filePath":"plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/v3/UserControllerV3.java","lineNumber":228,"sourceCode":"        \n        userDetailsService.updateUserPassword(username, newPassword);\n        return Result.success(\"update user ok!\");\n        \n    }\n    \n    private boolean hasPermission(String username, HttpServletRequest request)\n        throws HttpSessionRequiredException, AccessException {\n        if (!NacosAuthConfigHolder.getInstance().isAnyAuthEnabled()) {\n            return true;\n        }\n        // Fixes #13959. If the user is server identity, should not check permission.\n        if (isFromServerIdentity(request)) {\n            return true;\n        }\n        IdentityContext identityContext =\n            RequestContextHolder.getContext().getAuthContext().getIdentityContext();\n        if (identityContext == null) {\n            throw new HttpSessionRequiredException(\"session expired!\");\n        }\n        NacosUser user = (NacosUser) identityContext.getParameter(AuthConstants.NACOS_USER_KEY);\n        if (user == null) {\n            user = iAuthenticationManager.authenticate(request);\n            if (user == null) {\n                throw new HttpSessionRequiredException(\"session expired!\");\n            }\n        }\n        //get user form jwt need check permission\n        iAuthenticationManager.hasGlobalAdminRole(user);\n        // admin\n        if (user.isGlobalAdmin()) {\n            return true;\n        }\n        // same user\n        return user.getUserName().equals(username);\n    }\n    ","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/v3/UserControllerV3.java#L210-L246","documentation":"Thrown by UserControllerV3.hasPermission() as an org.springframework.web.HttpSessionRequiredException when the request's auth context carries no IdentityContext at all — meaning the caller reached a protected user-management endpoint (e.g., password update) without an established authenticated identity. The controller catches it and responds HTTP 401 'session expired!'.","triggerScenarios":"Calling /v3/auth/user/update (or another hasPermission-guarded endpoint) when RequestContextHolder.getContext().getAuthContext().getIdentityContext() is null — e.g., no Authorization header / session cookie, or the auth filter did not populate the context (filter ordering / disabled interceptor).","commonSituations":"Browser session timed out and the UI did not refresh the token; a direct API call without credentials; an auth filter misconfiguration after an upgrade that stops populating IdentityContext; server-identity header also absent.","solutions":["Authenticate first (POST /v3/auth/login) to obtain a valid token/session and pass it on subsequent calls.","Ensure the Authorization header (or session cookie) is sent on the request.","If integrating server-to-server, send the server-identity header which short-circuits the check via isFromServerIdentity()."],"exampleFix":"// before\ncurl -X PUT 'http://host/v3/auth/user/update?username=alice&newPassword=...'\n// -> 401 session expired!\n\n// after\ntoken=$(curl -s -X POST 'http://host/v3/auth/login' -d 'username=admin&password=...' | jq -r .data.accessToken)\ncurl -X PUT 'http://host/v3/auth/user/update?username=alice&newPassword=...' -H \"Authorization: Bearer $token\"","handlingStrategy":"validation","validationCode":"// Client-side: ensure a token is present before calling a protected endpoint.\nString token = currentAccessToken();\nif (StringUtils.isBlank(token)) {\n    throw new IllegalStateException(\"No auth token; login first\");\n}\nHttpRequest req = HttpRequest.newBuilder()\n    .uri(URI.create(url))\n    .header(\"Authorization\", \"Bearer \" + token)\n    .PUT(BodyPublishers.ofString(body)).build();","typeGuard":null,"tryCatchPattern":"try {\n    controller.updateUser(username, newPassword, response, request);\n} catch (HttpSessionRequiredException e) {\n    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, \"session expired!\");\n}","preventionTips":["Always send a valid Authorization header (or session cookie) on protected endpoints.","Refresh tokens before they expire to keep IdentityContext populated.","For server-to-server calls, use the server-identity header to bypass the user check."],"tags":["auth","session","http","unauthorized"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}