{"record":{"id":"79d614fbe49972dc","repo":"pentaho/pentaho-kettle","slug":"unable-to-get-authorization-token","errorCode":null,"errorMessage":"Unable to get authorization token ","messagePattern":"Unable to get authorization token ","errorType":"exception","errorClass":"HttpException","httpStatus":null,"severity":"error","filePath":"plugins/email-messages/impl/src/main/java/org/pentaho/di/trans/steps/mailinput/MailInputMeta.java","lineNumber":1048,"sourceCode":"    try (CloseableHttpClient client = HttpClientManager.getInstance().createDefaultClient()) {\n      HttpPost httpPost = new HttpPost( variables.environmentSubstitute( tokenUrl ) );\n      List<NameValuePair> form = new ArrayList<>();\n      form.add(new BasicNameValuePair(\"scope\", variables.environmentSubstitute( scope ) ) );\n      form.add(new BasicNameValuePair(\"client_id\", variables.environmentSubstitute( clientId ) ));\n      form.add(new BasicNameValuePair(\"client_secret\", variables.environmentSubstitute( secretKey ) ) );\n      form.add(new BasicNameValuePair(\"grant_type\", grantType));\n      if (grantType.equals(GRANTTYPE_REFRESH_TOKEN)) {\n        form.add(new BasicNameValuePair(GRANTTYPE_REFRESH_TOKEN, variables.environmentSubstitute( refreshToken ) ) );\n      }\n      if (grantType.equals(GRANTTYPE_AUTHORIZATION_CODE)) {\n        form.add(new BasicNameValuePair(\"code\", variables.environmentSubstitute( authorizationCode ) ) );\n        form.add(new BasicNameValuePair(\"redirect_uri\", variables.environmentSubstitute( redirectUri ) ) );\n      }\n      UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, Consts.UTF_8);\n      httpPost.setEntity(entity);\n      try (CloseableHttpResponse response = client.execute(httpPost)) {\n        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {\n          throw new HttpException(\"Unable to get authorization token \" + response.getStatusLine().toString());\n        }\n        ObjectMapper mapper = new ObjectMapper();\n        return mapper.readValue(EntityUtils.toString(response.getEntity()), EmailAuthenticationResponse.class);\n      } catch ( HttpException | IOException e) {\n        throw new RuntimeException(e);\n      }\n    } catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n","sourceCodeStart":1030,"sourceCodeEnd":1060,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/email-messages/impl/src/main/java/org/pentaho/di/trans/steps/mailinput/MailInputMeta.java#L1030-L1060","documentation":"Thrown while MailInputMeta exchanges an authorization code (or credentials) for an OAuth2 access token via HTTP POST. Any non-200 status from the token endpoint raises HttpException, which is rethrown as a RuntimeException, aborting authentication for the Mail Input step.","triggerScenarios":"POSTing the token request (redirect_uri, client id/secret form entity) to the OAuth provider and receiving a status other than 200 — bad client secret, expired/mismatched redirect URI, or unreachable/blocked endpoint. Also on IOException/HttpException during response read.","commonSituations":"Misconfigured OAuth app (wrong redirect URI or client secret), tenant/admin consent missing in Microsoft 365, network proxy blocking the token endpoint, or using a deactivated client.","solutions":["Check the wrapped cause and the status line (response.getStatusLine()) for the provider's error (e.g. 400 invalid_grant)","Verify client ID, client secret, tenant, and redirect_uri exactly match the OAuth app registration","Ensure the environment variables substituted via variables.environmentSubstitute() resolve to correct values","Confirm network/proxy access to login.microsoftonline.com or the configured token endpoint","Regenerate the authorization code — codes are single-use and expire in minutes"],"exampleFix":"// before\nif ( response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {\n  throw new HttpException( \"Unable to get authorization token \" + response.getStatusLine().toString() );\n}\n// after\nif ( response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {\n  String body = EntityUtils.toString( response.getEntity() );\n  throw new HttpException( \"Token endpoint returned \" + response.getStatusLine()\n    + \": \" + body );\n}","handlingStrategy":"validation","validationCode":"boolean tokenConfigValid = clientId != null && !clientId.isEmpty()\n  && clientSecret != null && !clientSecret.isEmpty()\n  && redirectUri != null && redirectUri.startsWith( \"https://\" );\nif ( !tokenConfigValid ) {\n  throw new IllegalArgumentException( \"OAuth client id/secret/redirect_uri must be set before token exchange\" );\n}","typeGuard":null,"tryCatchPattern":"try {\n  EmailAuthenticationResponse resp = meta.getAuthenticationResponse(...);\n} catch ( RuntimeException e ) {\n  // inspect cause: HttpException status line or IOException\n  logError( \"Token exchange failed: \" + e.getCause().getMessage() );\n}","preventionTips":["Verify redirect_uri exactly matches the OAuth app registration","Regenerate authorization codes right before use (they expire quickly)","Check proxy/firewall access to the token endpoint","Validate env-variable substitutions resolve to non-empty values"],"tags":["oauth2","http","authentication","mail-input"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}