{"record":{"id":"3751c0b93ef87e51","repo":"SonarSource/sonarqube","slug":"authentication-failed","errorCode":null,"errorMessage":"Authentication failed","messagePattern":"Authentication failed","errorType":"http","errorClass":"AuthenticationException","httpStatus":401,"severity":"warning","filePath":"server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/common/ServerRestResponseEntityExceptionHandler.java","lineNumber":41,"sourceCode":"import org.slf4j.LoggerFactory;\nimport org.sonar.server.authentication.event.AuthenticationException;\nimport org.sonar.server.v2.api.model.RestError;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\n\n@RestControllerAdvice\n@Order(Ordered.LOWEST_PRECEDENCE - 1)\npublic class ServerRestResponseEntityExceptionHandler {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ServerRestResponseEntityExceptionHandler.class);\n\n  @ExceptionHandler(AuthenticationException.class)\n  protected ResponseEntity<RestError> handleAuthenticationException(AuthenticationException ex) {\n    LOGGER.warn(ex.getPublicMessage());\n    return ResponseEntity.status(HttpStatus.UNAUTHORIZED)\n        .body(new RestError(ErrorMessages.AUTHENTICATION_FAILED.getMessage()));\n  }\n}\n","sourceCodeStart":23,"sourceCodeEnd":46,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/common/ServerRestResponseEntityExceptionHandler.java#L23-L46","documentation":"Spring @ExceptionHandler for AuthenticationException in the v2 REST API. Instead of leaking internals, it logs the exception's public message and returns HTTP 401 with a generic RestError body 'Authentication failed'.","triggerScenarios":"Any request to a v2 web API endpoint whose authentication (token/session/Basic credentials) fails, causing Spring Security to raise AuthenticationException which is routed to handleAuthenticationException.","commonSituations":"Expired or revoked user tokens; wrong Basic auth credentials in scripts/CI; calling v2 endpoints with tokens valid only for the legacy web API; missing Authorization header on protected endpoints.","solutions":["Check the server log for the public message logged just before the 401 to see why auth failed","Regenerate the user token and update the client/CI secret","Send the Authorization header correctly (Bearer <token> or Basic base64(login:password))","Verify the account is active and not locked/deactivated locally"],"exampleFix":"// before\ncurl -u wronguser:badpass http://localhost:9000/api/v2/... \n// after\ncurl -H \"Authorization: Bearer <valid-token>\" http://localhost:9000/api/v2/...","handlingStrategy":"validation","validationCode":"if (token == null || token.isBlank()) throw new IllegalStateException(\"Supply a bearer token before calling the API\");","typeGuard":"boolean hasAuth(HttpHeaders h) { return h != null && h.getFirst(\"Authorization\") != null && !h.getFirst(\"Authorization\").isBlank(); }","tryCatchPattern":"try { return api.call(); } catch (HttpClientErrorException.Unauthorized e) { refreshToken(); return api.call(); }","preventionTips":["Rotate user tokens regularly and store them in a secret manager","Send Authorization: Bearer/Basic headers on every v2 API call","Check account status before scripting against the API"],"tags":["authentication","http-401","rest-api"],"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"}