Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you get the Google+ Profile of the current user when using Google Cloud Endpoint's (Java) built in authentication?

My Setup

Backend: Google App Engine (Java) w/ Google Cloud Endpoints using Endpoint's built in authentication

Frontend: AngularJS web app

Problem

I need to get the Google+ profile for my users. The keyword "me" can generally be used to get the current user's Google+ profile, however since all the authentication, in Google Cloud Endpoints, is done under the hood, I don't see anyway to get credentials, nor a token, for the current user. All you get it the com.google.appengine.api.users.User object.

Is there any way to get user credentials, or the access token, when using Google Cloud Endpoint's built in authentication?

Note: Google+ profile ID is different form Google account ID.

Possible Solution

I could just use the Google+ JS client with the keyword "me" and have the user send their Google+ ID and then subsequently store it and tie it to their Google Account ID, but this would be incredible insecure as the user could hack their way to sending the ID of any Google+ account.

like image 648
Marc M. Avatar asked Nov 28 '25 11:11

Marc M.


2 Answers

It is possible to get the user access token when using Google Cloud Endpoint's built in authentication.

  1. Add the parameter HttpServletRequest request to your Google Cloud endpoint as shown below. This will allow you to get the raw request.

  2. You will then need to retreive the header called Authentication. This will get a Bearer access token that will allow you to build credentials to impersonate the authenticated user.

  3. Next you will use that Bearer access token to build a com.google.api.client.googleapis.auth.oauth2.GoogleCredential object. You will need this to build the Plus service.

  4. Use the Plus builder to build a Plus service object with the credential you just created.

Sample Code

@ApiMethod(path = "myPath")
public void myEndpoint(HttpServletRequest request, ParmOne paramOne, ...) throws OAuthRequestException {

    if (user == null) {
        throw new OAuthRequestException("Authentication error!");
    }

    GoogleCredential credentialAsUser = new GoogleCredential().setAccessToken(request.getHeader("Authorization").substring(7)); // Start string at index position 7 to remove prefix "Bearer" from token.

    Plus plus = new Plus.Builder(new UrlFetchTransport(), new JacksonFactory(), credentialAsUser).setApplicationName("my-app").build();
    Person profile = plus.people().get("me").execute();

}

Documentation

The Java docs for the Google Plus client can be found here.

The Java docs for instructions on creating Google credentials can be found here.

like image 102
Marc M. Avatar answered Dec 01 '25 02:12

Marc M.


Additional Answer for Android Clients

Problem

In addition to the Marc's answer it is important that the GoogleCredentials-Object needs an access_token in the request-header.

If you call the endpoint with your apiExplorer or a javascript endpoint, this token is already served in the Authorization-header. But if you follow the docs for an android client your requests header contains an id_token, so GoogleCredentials.setAccessToken does not work.

Solution

To change the type of authorization to an access_token simply create your GoogleAccountCredential-Object in Android with usingOAuth2 instead of usingAudience.

Example

Replace this code in your Android App

credential = GoogleAccountCredential.usingAudience(this,
"server:client_id:1-web-app.apps.googleusercontent.com");

with this

credential = GoogleAccountCredential.usingOAuth2(this, 
Collections.singleton(Scopes.PLUS_LOGIN));

and send it to your Api, as it is explained by the documentation

Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT,
  AppConstants.JSON_FACTORY,credential);
like image 26
Jokus Avatar answered Dec 01 '25 02:12

Jokus