How can you get the current user's Google+ profile when using Google Cloud Endpoint (Java) built in authentication?
My setup
Backend: Google App Engine (Java) with Google Cloud Endpoints using Endpoint Built in Authentication
Frontend: AngularJS Web Application
Problem
I need to get a Google+ profile for my users. The "me" keyword can usually be used to get the profile of the current Google+ user, however, since all authentication to Google cloud endpoints is done under the hood, I still don't see the credentials or tokens for the current user. You all get the object com.google.appengine.api.users.User
.
Is there a way to get user credentials or access token when using Google Cloud Endpoint built in authentication?
Note. Google+ Profile ID is different from Google Account ID.
Possible Solution
I could just use the Google+ JS client with the "me" keyword and send the user my Google+ ID and then save it and bind it to their Google Account ID, but that would be incredibly insecure as the user could hack their submit path any Google+ account ID.
source to share
It is possible to get a user access token when using Google Cloud Endpoint built in authentication.
-
Add the parameter
HttpServletRequest request
to the Google Cloud endpoint as shown below. This will allow you to receive the unhandled request. -
Then you will need to restore the header titled Authentication. This will obtain a subscriber access token, which will allow you to create credentials to impersonate the authenticated user.
-
Then you will use this access token to create the object
com.google.api.client.googleapis.auth.oauth2.GoogleCredential
. You will need this to create the Plus service. -
Use the Plus constructor to create a Plus service object with the credentials 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 .
source to share
Complementary answer for Android clients
Problem
In addition to Marc's answer, it is important that GoogleCredentials
-Object needs a access_token
request header.
If you call the endpoint using apiExplorer or javascript endpoint , this token is already served in the authorization header. But if you follow the docs for android client your request header contains id_token
, so GoogleCredentials.setAccessToken
doesn't work.
Decision
To change the authorization type to access_token
just create GoogleAccountCredential
-Object in Android with usingOAuth2
instead 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 Api as it is explained by the documentation
Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY,credential);
source to share