0

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!

LMG
  • 1,330
  • 11
  • 21
  • Which scopes have you required for the user authentication? – Deviling Master Apr 17 '17 at 18:23
  • Short answer: email and profile. – LMG Apr 17 '17 at 20:25
  • Long answer: the user currently connects to a web page that goes through a servlet. This servlet is able to retrieve few things: email, profile, uid, token, etc... While trying to retrieve the same info through App Engine using the same APP ID, uid and token, the methods does not return profile infos. – LMG Apr 17 '17 at 20:35
  • I reversed things - sorry. In you EP, you should add the profile scope when you auth. – Les Vogel - Google DevRel Apr 25 '17 at 03:09

1 Answers1

0

I ended up using a different library which is much simpler and provided the same information.

https://stackoverflow.com/questions/22516693

Community
  • 1
  • 1
LMG
  • 1,330
  • 11
  • 21