Skip to content

Instantly share code, notes, and snippets.

@jrichardsz
Created September 26, 2021 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrichardsz/a91cd2500404e717753fdb23e9d6fd35 to your computer and use it in GitHub Desktop.
Save jrichardsz/a91cd2500404e717753fdb23e9d6fd35 to your computer and use it in GitHub Desktop.
google oauth2 java client, googleoaauth2
package org.jrichardsz.horus.third.google.client;
import java.util.Map;
import org.jrichardsz.horus.exceptions.BadGoogleResponseException;
import org.jrichardsz.horus.exceptions.GoogleOauthRestApiException;
public interface GoogleClient {
public String getAuthorizeUrl(String redirectUri, String scope, String clientId);
public Map<String, Object> getAccessToken(String authorizationCode, String clientId,
String clientSecret, String redirect) throws GoogleOauthRestApiException;
public String getDataUserFromPlusApi(String accessToken)
throws BadGoogleResponseException, GoogleOauthRestApiException;
public String getDataUserFromPeopleApi(String accessToken)
throws BadGoogleResponseException, GoogleOauthRestApiException;
}
package org.jrichardsz.horus.third.google.client.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import org.jrichardsz.horus.common.HorusCommon;
import org.jrichardsz.horus.exceptions.BadGoogleResponseException;
import org.jrichardsz.horus.exceptions.GoogleOauthRestApiException;
import org.jrichardsz.horus.third.google.client.GoogleClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
@Component
public class GoogleClientImpl implements GoogleClient {
private static final Logger logger = LoggerFactory.getLogger(GoogleClientImpl.class);
public final String googleAuthUrlTemplate = "https://accounts.google.com/o/oauth2/v2/auth?"
+ "response_type=code&redirect_uri=%s&scope=%s&client_id=%s";
private final String googleTokenGeneratorUrl = "https://accounts.google.com/o/oauth2/token?";
private final String googlePeopleApiUrl = "https://people.googleapis.com/v1/people/me";
private final String googlePlusApiUrl = "https://www.googleapis.com/plus/v1/people/me";
private final String codeGrantType = "authorization_code";
private final String prefixAuthHeader = "Bearer";
public String getAuthorizeUrl(String redirectUri, String scope, String clientId) {
// scope encode
scope = encodeValue(scope);
return String.format(googleAuthUrlTemplate, redirectUri, scope, clientId);
}
// Method to encode a string value using `UTF-8` encoding scheme
private String encodeValue(String value) {
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex.getCause());
}
}
@SuppressWarnings("unchecked")
public Map<String, Object> getAccessToken(String authorizationCode, String clientId,
String clientSecret, String redirect) throws GoogleOauthRestApiException {
HttpURLConnection conn = null;
try {
StringBuilder urlParameters = new StringBuilder();
urlParameters.append("code=").append(authorizationCode).append("&client_id=").append(clientId)
.append("&client_secret=").append(clientSecret).append("&redirect_uri=").append(redirect)
.append("&grant_type=").append(codeGrantType);
URL url = new URL(googleTokenGeneratorUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters.toString());
writer.flush();
String tokenDataStr = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
tokenDataStr = tokenDataStr + line;
}
writer.close();
reader.close();
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> tokenData = mapper.readValue(tokenDataStr, Map.class);
return tokenData;
} catch (IOException e) {
String errorResponse = HorusCommon.inputStreamToString(conn.getErrorStream());
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error [%s] when oauth code was exchanged for the token.",
e.getMessage()), e);
} catch (HttpClientErrorException e) {
String errorResponse = e.getResponseBodyAsString();
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when oauth code was exchanged for the token. Endpoint: %s",
e.getRawStatusCode(), googleTokenGeneratorUrl), e);
} catch (HttpServerErrorException e) {
String errorResponse = e.getResponseBodyAsString();
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when oauth code was exchanged for the token. Endpoint: %s",
e.getRawStatusCode(), googleTokenGeneratorUrl), e);
} catch (Exception e) {
String errorResponse = HorusCommon.inputStreamToString(conn.getErrorStream());
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Unexpected error when oauth code was exchanged for the token in Google platform. Endpoint:%s",
googleTokenGeneratorUrl), e);
}
}
public String getDataUserFromPlusApi(String accessToken)
throws BadGoogleResponseException, GoogleOauthRestApiException {
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, prefixAuthHeader + " " + accessToken);
RestTemplate restTemplate = new RestTemplate();
String plusApiResponse = null;
try {
plusApiResponse = restTemplate
.exchange(googlePlusApiUrl, HttpMethod.GET, new HttpEntity<>(headers), String.class)
.getBody();
} catch (HttpClientErrorException e) {
String errorResponse = e.getResponseBodyAsString();
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when token was exchanged for the user information. Endpoint: %s",
e.getRawStatusCode(), googlePlusApiUrl), e);
} catch (HttpServerErrorException e) {
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when token was exchanged for the user information. Endpoint: %s",
e.getRawStatusCode(), googlePlusApiUrl), e);
} catch (Exception e) {
throw new GoogleOauthRestApiException(String.format(
"Unexpected error when oauth code was exchanged for the token in Google platform. Endpoint: %s",
googlePlusApiUrl), e);
}
String email = null;
try {
ReadContext ctx = JsonPath.parse(plusApiResponse);
email = ctx.read("$.emails[0].value");
Assert.notNull(email,
"email from google plus api response must not be null: " + googlePlusApiUrl);
} catch (IllegalArgumentException e) {
throw new BadGoogleResponseException(
"Email cannot be extracted from google plus api response: " + plusApiResponse,
"Email cannot be extracted from google plus api response", e);
} catch (Exception e) {
throw new BadGoogleResponseException(
"Email cannot be extracted from google plus api response: " + plusApiResponse,
"Email cannot be extracted from google plus api response", e);
}
return email;
}
@Override
public String getDataUserFromPeopleApi(String accessToken)
throws BadGoogleResponseException, GoogleOauthRestApiException {
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, prefixAuthHeader + " " + accessToken);
RestTemplate restTemplate = new RestTemplate();
String peopleApiResponse = null;
try {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(googlePeopleApiUrl)
.queryParam("personFields", "emailAddresses");
peopleApiResponse = restTemplate
.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity<>(headers), String.class)
.getBody();
} catch (HttpClientErrorException e) {
String errorResponse = e.getResponseBodyAsString();
logger.info("google response:" + errorResponse);
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when token was exchanged for the user information. Endpoint: %s",
e.getRawStatusCode(), googlePeopleApiUrl), e);
} catch (HttpServerErrorException e) {
throw new GoogleOauthRestApiException(String.format(
"Google platform returns a error status code: %s when token was exchanged for the user information. Endpoint: %s",
e.getRawStatusCode(), googlePeopleApiUrl), e);
} catch (Exception e) {
throw new GoogleOauthRestApiException(String.format(
"Unexpected error when oauth code was exchanged for the token in Google platform. Endpoint: %s",
googlePeopleApiUrl), e);
}
String email = null;
// expected response:
// https://gist.github.com/jrichardsz/585fba4ba7587dd41faea14fa32aa36b#file-personfields-emailaddresses
try {
ReadContext ctx = JsonPath.parse(peopleApiResponse);
email = ctx.read("$.emailAddresses[0].value");
Assert.notNull(email,
"email from google people api response must not be null: " + googlePeopleApiUrl);
} catch (IllegalArgumentException e) {
throw new BadGoogleResponseException(
"Email cannot be extracted from google people api response: " + peopleApiResponse,
"Email cannot be extracted from google people api response", e);
} catch (Exception e) {
throw new BadGoogleResponseException(
"Email cannot be extracted from google people api response: " + peopleApiResponse,
"Email cannot be extracted from google people api response", e);
}
return email;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment