{"record":{"id":"d0e7d8fbdcf9711a","repo":"apolloconfig/apollo","slug":"portal-user-session-is-required","errorCode":null,"errorMessage":"Portal user session is required","messagePattern":"Portal user session is required","errorType":"exception","errorClass":"AccessDeniedException","httpStatus":403,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/PortalManagementController.java","lineNumber":1077,"sourceCode":"  }\n\n  private Set<String> nonNullSet(Set<String> values) {\n    return values == null ? Collections.emptySet() : values;\n  }\n\n  private OffsetDateTime toOffsetDateTime(Date date) {\n    return date == null ? null : date.toInstant().atOffset(ZoneOffset.UTC);\n  }\n\n  private Date toDate(OffsetDateTime dateTime) {\n    return dateTime == null ? null : Date.from(dateTime.toInstant());\n  }\n\n  private String requirePortalUserId() {\n    requirePortalUserRequest();\n    UserInfo user = userInfoHolder.getUser();\n    if (user == null || !org.springframework.util.StringUtils.hasText(user.getUserId())) {\n      throw new AccessDeniedException(\"Portal user session is required\");\n    }\n    return user.getUserId();\n  }\n\n  private <T> T convertBody(Object body, Class<T> clazz) {\n    if (clazz.isInstance(body)) {\n      return clazz.cast(body);\n    }\n    return objectMapper.convertValue(body, clazz);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  private List<Object> asObjects(List<?> values) {\n    if (values == null) {\n      return Collections.emptyList();\n    }\n    return (List<Object>) (List<?>) values;\n  }","sourceCodeStart":1059,"sourceCodeEnd":1095,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/PortalManagementController.java#L1059-L1095","documentation":"Thrown by requirePortalUserId when the current user context has no UserInfo or the UserInfo's userId is blank. This method is called after requirePortalUserRequest (which confirms the auth type is USER), so it represents a deeper failure: the portal session was recognized but the user identity could not be resolved. This typically indicates an incomplete or malformed authentication setup.","triggerScenarios":"A portal-user-authenticated request reaches an endpoint that needs the current user's ID, but the UserInfoHolder returns null or a UserInfo with a blank userId field.","commonSituations":"The SSO/authentication integration did not populate the user identity correctly; a custom auth filter sets the auth type to USER but fails to set UserInfo; or a mock/test context has an incomplete user object.","solutions":["Verify the authentication filter (e.g. SSO filter) correctly populates UserInfoHolder with a UserInfo that has a non-blank userId.","If using a custom auth integration, ensure it sets both the auth type to USER and the UserInfo with a valid userId.","In test environments, mock UserInfoHolder with a complete UserInfo object."],"exampleFix":"// before: auth filter sets type but not user\nUserIdentityContextHolder.setAuthType(UserIdentityConstants.USER);\n// UserInfoHolder left null\n\n// after: set both auth type and user\nUserInfoHolder.setUser(new UserInfo(\"user123\"));\nUserIdentityContextHolder.setAuthType(UserIdentityConstants.USER);","handlingStrategy":"validation","validationCode":"// Verify user identity is available before calling endpoints that need userId\nUserInfo user = userInfoHolder.getUser();\nif (user == null || !org.springframework.util.StringUtils.hasText(user.getUserId())) {\n  throw new IllegalStateException(\"Portal user session is incomplete — no userId resolved\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  String userId = requirePortalUserId();\n} catch (AccessDeniedException e) {\n  if (e.getMessage().contains(\"Portal user session\")) {\n    // redirect to login or fix the auth filter to populate UserInfo\n  }\n}","preventionTips":["Ensure the SSO/auth filter sets UserInfoHolder with a UserInfo containing a valid userId.","Test auth integration with integration tests that assert a non-blank userId after login.","Log a warning when UserInfo is null after successful auth-type detection."],"tags":["permission","authorization","access-denied","session","authentication","apollo-portal"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}