I am trying to follow https://developers.google.com/identity/protocols/oauth2/web-server#exchange-authorization-code to exchange a code for an access token. I am able to get my local endpoint to trigger and in the controller I run the following. The issue is that I am getting a 400 from ‘https://oauth2.googleapis.com/token’ endpoint. I do not see a response body, which is where would usually look for the error message. Does anyone know how I can debug or what the issue might be? Note that I have ‘http://localhost:8080/oauthtokengmail’ as one of my ‘Authorized redirect URIs’, and that the redirect is working, so I do not think the issue is there.
I was successfully able to use curl to get the values … so I know it must be something in the java code.
I am executing the following code:
private String getTokenJson(String code, boolean isProduction) {
RequestConfig requestConfig = getRequestConfig();
BasicHttpClientConnectionManager cm = getConnectionManager();
HttpPost post = new HttpPost("https://oauth2.googleapis.com/token");
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("code", code));
pairs.add(new BasicNameValuePair("client_id", gmailSecretsService.getClientId()));
pairs.add(new BasicNameValuePair("client_secret", gmailSecretsService.getClientSecret()));
pairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
pairs.add(new BasicNameValuePair("redirect_uri", getRedirectUri(isProduction)));
post.setEntity(new UrlEncodedFormEntity(pairs));
//////////////////////
try (CloseableHttpClient httpclient = HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build()) {
try (CloseableHttpResponse response = httpclient.execute(post)) {
// Get status code
if (response.getCode() != 200) {
LOGGER.info("Seeing response.code()={}", response.getCode());
return null;
}
HttpEntity entity = response.getEntity();
// Get response information
String resultContent = EntityUtils.toString(entity);
LOGGER.info("Seeing result={}", resultContent);
return resultContent;
}
} catch (IOException | ParseException e) {
LOGGER.info("Seeing exception", e);
return null;
}
}
private static BasicHttpClientConnectionManager getConnectionManager() {
ConnectionConfig connConfig = ConnectionConfig.custom()
.setConnectTimeout(15000, TimeUnit.MILLISECONDS)
.setSocketTimeout(15000, TimeUnit.MILLISECONDS)
.build();
BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
cm.setConnectionConfig(connConfig);
return cm;
}
private static RequestConfig getRequestConfig() {
return RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.ofMilliseconds(15000))
.build();
}
private static String getRedirectUri(boolean isProduction) {
if (isProduction) {
return "https://example.com/oauthtokengmail";
} else {
return "http://localhost:8080/oauthtokengmail";
}
}
The issue was that the redirect_uri was mismatched between production and local. When the prod server used the non-localhost version, that (naturally) did not match the localhost version. Otherwise, the code works perfectly.