{"record":{"id":"c259f977c7740687","repo":"SonarSource/sonarqube","slug":"usersession-not-found-in-authentication-principal","errorCode":null,"errorMessage":"UserSession not found in authentication principal","messagePattern":"UserSession not found in authentication principal","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/security/SecurityContextBackedUserSession.java","lineNumber":69,"sourceCode":"\n  /**\n   * Get the UserSession from SecurityContext.\n   * This extracts the actual UserSession stored in the SonarUserDetails principal.\n   */\n  private static UserSession delegate() {\n    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\n\n    if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {\n      throw new UnauthorizedException(\"Authentication is required\");\n    }\n\n    // Extract UserSession from SonarUserDetails principal\n    Object principal = authentication.getPrincipal();\n    if (principal instanceof SonarUserDetails sonarUserDetails) {\n      return sonarUserDetails.getUserSession();\n    }\n\n    throw new UnauthorizedException(\"UserSession not found in authentication principal\");\n  }\n\n  @Override\n  @CheckForNull\n  public String getLogin() {\n    return delegate().getLogin();\n  }\n\n  @Override\n  @CheckForNull\n  public String getUuid() {\n    return delegate().getUuid();\n  }\n\n  @Override\n  @CheckForNull\n  public String getName() {\n    return delegate().getName();","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/security/SecurityContextBackedUserSession.java#L51-L87","documentation":"UnauthorizedException thrown by SecurityContextBackedUserSession.delegate() when an Authentication exists but its principal is not a SonarUserDetails instance, so no UserSession can be extracted. This indicates an unexpected principal type in the security context — an internal wiring/auth-filter problem rather than user error.","triggerScenarios":"An authenticated Authentication whose getPrincipal() is not SonarUserDetails reaches a call that resolves the UserSession — e.g. custom authentication filters, alternate token auth paths, or version mismatch between security modules.","commonSituations":"Custom Spring Security integrations setting their own principal, partially upgraded installations with mismatched security components, plugins injecting custom Authentication objects.","solutions":["Ensure the authentication filter populates SonarUserDetails as the principal","Remove or fix custom security filters/plugins replacing the principal","Align all SonarQube modules to the same version (redeploy webapp)","Log the principal's concrete class to diagnose which component set it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    session = securityContextBackedUserSession.getLogin();\n} catch (UnauthorizedException e) {\n    // principal wiring problem: inspect SecurityContext authentication principal type\n}","preventionTips":["Don't install custom Spring Security filters that replace the SonarUserDetails principal","Keep all SonarQube modules/plugins on matching versions","Test custom auth integrations against UserSession-dependent endpoints"],"tags":["java","spring-security","principal"],"backgroundTag":"authentication-required","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}