SonarSource/sonarqube · warning · UnauthorizedException
Authentication is required
Error message
Authentication is required
What it means
UnauthorizedException thrown by SecurityContextBackedUserSession.delegate() when the Spring Security context holds no Authentication or an AnonymousAuthenticationToken, meaning no user is authenticated. All UserSession operations delegated through this wrapper require a real authenticated principal.
Solutions
- Authenticate first: supply a valid token (Authorization header) or log in to obtain a session
- Refresh/renew expired credentials and retry
- Verify the endpoint is not expected to be anonymous; use an anonymous-safe API if so
- Check reverse-proxy/security config isn't stripping authentication
Example fix
// before curl http://sonarqube:9000/api/v2/users/current // after curl -H "Authorization: Bearer $SONAR_TOKEN" http://sonarqube:9000/api/v2/users/current
Defensive patterns
Strategy: try-catch
Validate before calling
// verify credentials are present before the call
if (token == null || token.isBlank()) throw new IllegalStateException("SONAR_TOKEN not set"); Try / catch
try {
user = api.usersCurrent();
} catch (UnauthorizedException | ForbiddenException e) {
// 401: (re)authenticate, refresh token, then retry once
} Prevention
- Keep tokens valid and rotate before expiry
- Always send Authorization header for protected v2 endpoints
- Handle 401 by re-authenticating rather than retrying blindly
When it happens
Trigger: Any API call routed through SecurityContextBackedUserSession (getLogin, getPermissions, etc.) while unauthenticated or anonymous — e.g. missing/invalid token, expired session, or endpoint invoked without security filter populating the context.
Common situations: Expired or missing bearer token, calling a protected endpoint from a script without credentials, session invalidated server-side, misconfigured security filter chain letting anonymous principals through.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authentication is required
- Identity provider does not exist or is not enabled
- Invalid personal access token
- Invalid personal access token
- UserSession not found in authentication principal
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/e7b7f19dc5a1ec09.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/security/SecurityContextBackedUserSession.java:60
* <p>For backwards compatibility with code that expects ThreadLocalUserSession,
* this wrapper allows legacy code to continue working while the actual user data
* lives in SecurityContext.</p>
*
* <p><strong>Architecture:</strong> All methods delegate to the original UserSession
* stored in UserSessionAuthentication within SecurityContext. This eliminates
* dual ThreadLocal storage.</p>
*/
public class SecurityContextBackedUserSession implements UserSession {
/**
* Get the UserSession from SecurityContext.
* This extracts the actual UserSession stored in the SonarUserDetails principal.
*/
private static UserSession delegate() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
throw new UnauthorizedException("Authentication is required");
}
// Extract UserSession from SonarUserDetails principal
Object principal = authentication.getPrincipal();
if (principal instanceof SonarUserDetails sonarUserDetails) {
return sonarUserDetails.getUserSession();
}
throw new UnauthorizedException("UserSession not found in authentication principal");
}
@Override
@CheckForNull
public String getLogin() {
return delegate().getLogin();
}
@OverrideView on GitHub (pinned to 184c821202)