apolloconfig/apollo · error · AccessDeniedException

Portal user session is required

Error message

Portal user session is required

What it means

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.

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/PortalManagementController.java:1077

  }

  private Set<String> nonNullSet(Set<String> values) {
    return values == null ? Collections.emptySet() : values;
  }

  private OffsetDateTime toOffsetDateTime(Date date) {
    return date == null ? null : date.toInstant().atOffset(ZoneOffset.UTC);
  }

  private Date toDate(OffsetDateTime dateTime) {
    return dateTime == null ? null : Date.from(dateTime.toInstant());
  }

  private String requirePortalUserId() {
    requirePortalUserRequest();
    UserInfo user = userInfoHolder.getUser();
    if (user == null || !org.springframework.util.StringUtils.hasText(user.getUserId())) {
      throw new AccessDeniedException("Portal user session is required");
    }
    return user.getUserId();
  }

  private <T> T convertBody(Object body, Class<T> clazz) {
    if (clazz.isInstance(body)) {
      return clazz.cast(body);
    }
    return objectMapper.convertValue(body, clazz);
  }

  @SuppressWarnings("unchecked")
  private List<Object> asObjects(List<?> values) {
    if (values == null) {
      return Collections.emptyList();
    }
    return (List<Object>) (List<?>) values;
  }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Verify the authentication filter (e.g. SSO filter) correctly populates UserInfoHolder with a UserInfo that has a non-blank userId.
  2. If using a custom auth integration, ensure it sets both the auth type to USER and the UserInfo with a valid userId.
  3. In test environments, mock UserInfoHolder with a complete UserInfo object.

Example fix

// before: auth filter sets type but not user
UserIdentityContextHolder.setAuthType(UserIdentityConstants.USER);
// UserInfoHolder left null

// after: set both auth type and user
UserInfoHolder.setUser(new UserInfo("user123"));
UserIdentityContextHolder.setAuthType(UserIdentityConstants.USER);
Defensive patterns

Strategy: validation

Validate before calling

// Verify user identity is available before calling endpoints that need userId
UserInfo user = userInfoHolder.getUser();
if (user == null || !org.springframework.util.StringUtils.hasText(user.getUserId())) {
  throw new IllegalStateException("Portal user session is incomplete — no userId resolved");
}

Try / catch

try {
  String userId = requirePortalUserId();
} catch (AccessDeniedException e) {
  if (e.getMessage().contains("Portal user session")) {
    // redirect to login or fix the auth filter to populate UserInfo
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/d0e7d8fbdcf9711a. Report an issue: GitHub.