{"record":{"id":"364fed8882438b19","repo":"SonarSource/sonarqube","slug":"unable-to-get-a-token","errorCode":null,"errorMessage":"Unable to get a token: ","messagePattern":"Unable to get a token: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java","lineNumber":37,"sourceCode":" */\npackage org.sonar.server.oauth;\n\nimport com.github.scribejava.core.builder.ServiceBuilder;\nimport com.github.scribejava.core.oauth.OAuth20Service;\nimport java.io.IOException;\nimport java.util.concurrent.ExecutionException;\n\npublic class OAuthMicrosoftRestClient {\n\n  public String getAccessTokenFromClientCredentialsGrantFlow(String host, String clientId, String clientSecret, String tenant, String scope) {\n    final OAuth20Service service = new ServiceBuilder(clientId)\n      .apiSecret(clientSecret)\n      .defaultScope(scope)\n      .build(new ScribeMicrosoftOauth2Api(host, tenant));\n    try {\n      return service.getAccessTokenClientCredentialsGrant().getAccessToken();\n    } catch (IOException | ExecutionException e) {\n      throw new IllegalStateException(\"Unable to get a token: \" + e);\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      throw new IllegalStateException(\"Interrupted while getting a token: \" + e);\n    }\n  }\n}\n","sourceCodeStart":19,"sourceCodeEnd":44,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java#L19-L44","documentation":"OAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow calls ScribeJava's client-credentials token request to Azure AD. If that call fails with IOException or ExecutionException (network failure, bad credentials, malformed response), it rethrows as IllegalStateException 'Unable to get a token: <cause>'.","triggerScenarios":"Calling the Microsoft OAuth client-credentials flow when Azure AD returns an error (invalid client secret, wrong tenant/host), or network connectivity to login.microsoftonline.com fails.","commonSituations":"Expired or wrong client secret; tenant id or host misconfigured; Azure AD app not granting admin consent; proxy blocking outbound HTTPS; Azure outage.","solutions":["Verify client id, client secret, tenant and scope values; rotate the secret if expired.","Test connectivity to the token endpoint (curl https://login.microsoftonline.com) including proxy settings.","Check the nested cause in logs for Azure's OAuth error (invalid_client, unauthorized_client) and fix the app registration.","Confirm the ScribeMicrosoftOauth2Api host/tenant configuration matches your Azure tenant."],"exampleFix":"// before\nnew OAuthMicrosoftRestClient(wrongTenantHost, clientId, oldSecret, scope);\n// after\nnew OAuthMicrosoftRestClient(new Host(\"https://login.microsoftonline.com\", \"<tenant-id>\"), clientId, rotatedSecret, scope);","handlingStrategy":"try-catch","validationCode":"// pre-flight checks before exchanging the token\nObjects.requireNonNull(clientId); Objects.requireNonNull(clientSecret);\ntry (var s = new java.net.Socket(host.url().getHost(), 443)) { /* reachable */ }","typeGuard":null,"tryCatchPattern":"try { token = oauthClient.getAccessTokenFromClientCredentialsGrantFlow(); } catch (IllegalStateException e) { log.error(\"Microsoft token exchange failed: {}\", e.getMessage(), e); throw new AuthenticationException(e.getMessage(), e); }","preventionTips":["Rotate and verify Azure client secrets before expiry","Confirm tenant id and host match your Azure AD setup","Check outbound proxy/firewall access to login.microsoftonline.com","Log and inspect the nested cause for Azure OAuth error codes"],"tags":["oauth","azure","authentication","network"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}