We're using the goole-client-api library to verify google accounts from our backend. This implementation runs on Google Cloud Platform (GCP) using App Engine and DataStore.
What we're seeing so far is for the GoogleIdTokenVerifier to work but only returns email and uid along with token signature.
The token and uid used does return all profile infos when run against our servlet but does not through our App Engine Endpoint.
Here is the code used:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.logging.Logger;
public class GoogleVerifier implements TokenVerifier {
final Logger logger = Logger.getLogger(GoogleVerifier.class.getName());
private static GoogleVerifier instance = null;
private String privAppId;
private UrlFetchTransport httpTransport; //library required to run on GCP
private JsonFactory jsonFactory;
private GoogleVerifier() {
}
private static GoogleVerifier getInstance() {
if (instance == null) {
instance = new GoogleVerifier();
}
return instance;
}
public static void setAppId(String appId) {
getInstance().setPrivAppId(appId);
getInstance().setHttpTransport(new UrlFetchTransport());
getInstance().setJsonFactory(new JacksonFactory());
}
public static String[] verify(String token, String uid) {
return getInstance().verifyPrivate(token, uid);
}
public String[] verifyPrivate(String token, String uid) {
@SuppressWarnings("unused")
GoogleCredential credential = new GoogleCredential().setAccessToken(token);
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(httpTransport, jsonFactory)
.setAudience(Collections.singletonList(privAppId))
.build();
String[] payloadInfo = new String[5];
try {
GoogleIdToken idToken = verifier.verify(token);
if (idToken != null) {
GoogleIdToken.Payload payload = idToken.getPayload();
if (payload.getSubject().equals(uid)) {
logger.info("Matching google id: " + uid);
payloadInfo[0] = payload.getSubject();
payloadInfo[1] = payload.get("given_name").toString();
payloadInfo[2] = payload.get("family_name").toString();
payloadInfo[3] = payload.get("picture").toString();
payloadInfo[4] = payload.getEmail();
return payloadInfo;
} else {
logger.info("Mismatching google id: " + uid);
return payloadInfo;
}
}
}
catch (Exception e) {
e.printStackTrace();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
logger.warning(sw.toString());
return payloadInfo;
}
return payloadInfo;
}
private void setPrivAppId(String appId) {
this.privAppId = appId;
}
private void setHttpTransport(UrlFetchTransport httpTransport) {
this.httpTransport = httpTransport;
}
private void setJsonFactory(JsonFactory jsonFactory) {
this.jsonFactory = jsonFactory;
}
}
Here is our App Engine Endpoint:
@ApiMethod(name = "loginSocial", path = "loginSocial", httpMethod = HttpMethod.PUT)
public Response loginSocial(@Named("token") String token,
@Named("uid") String uid,
@Named("socialWebSite") SOCIALWEBSITE socialWebSite,
HttpServletRequest request) throws DatabaseException, IOException {
Response response = new Response();
//make sure parameters and not null or empty
if (token != null && uid != null && socialWebSite != null &&
!token.trim().isEmpty() && !uid.trim().isEmpty()){
String [] userInfo = new String[5];
//validate token and retrieve info first
if (socialWebSite.equals(SOCIALWEBSITE.GOOGLE)){
GoogleVerifier.setAppId(APP_ID);
userInfo = GoogleVerifier.verify(token, uid);
}else if(socialWebSite.equals(APP_ID);
userInfo = FacebookVerifier.verify(token, uid);
}
}
}
Thanks!