Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use authorized Google Cloud Endpoints with Google Sign in

I have an app that uses Google Cloud Endpoints. Some methods need authorization so I followed this tutorial. This requires the GET_ACCOUNTS permissions.

I am updating the app to work with runtime permissions. I do not like to request permission to read contacts, but GET_ACCOUNTS is in the same group. Because of this I am looking to use authorization without GET_ACCOUNTS permission.

I think that Google Sign In could work but I am unable to find a way to use the result from Google Sign In.

This is the code used to create the object to make the calls to the endpoint:

Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT, AppConstants.JSON_FACTORY,credential);

The credential object must be a HttpRequestInitializer but from the Google Sign In I get a GoogleSignInAccount.

So, is it possible to do this? How should this be done?

like image 217
9and3r Avatar asked Dec 26 '15 23:12

9and3r


People also ask

Does sign in with Google use OAuth?

Google Sign-In manages the OAuth 2.0 flow and token lifecycle, simplifying your integration with Google APIs. A user always has the option to revoke access to an application at any time.

Does Google sign in use JWT?

The JWT ID Token is only needed during Sign-in. We just need to validate it once during Sign-in like so: client. verifyIdToken({idToken: token, audience: CLIENT_ID}) . The ID Token is not used to Authenticate a user to My Web App.

How do I add a Google login API?

Create or select a Google APIs project. If you already have a project for the Sign In With Google button or Google One Tap, use the existing project and the web client ID. If your project doesn't have a Web application-type client ID, click Create credentials > OAuth client ID to create one.


1 Answers

I finally found the solution. Using the tutorial found here.

You must add the Client id in the GoogleSignInOptions:

 GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(CLIENT_ID)
            .requestEmail()
            .build();

Following the tutorial you will finaly get a GoogleSignInAccount. Set the token from the GoogleSignInAccount in a GoogleCredential object:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
            .setJsonFactory(JacksonFactory.getDefaultInstance())
            .build();
credential.setAccessToken(GoogleSignInAccount.getIdToken());

This credential is ready to make authenticated calls to Google Cloud Enpoints.

Note that you must remove "server:client_id:" part from the CLIENT_ID. So if you were using this:

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

Your CLIENT_ID would be:

CLIENT_ID = "1-web-app.apps.googleusercontent.com"

Also note that the token is valid for a limited amount of time (Aprox. 1 hour in my testing)

To avoid the 1 hour token limitation, use GoogleSignInApi.silentSignIn() to get a new token before every call you make to your endpoint. For example if you are not in the UI thread:

GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail()
                .requestIdToken(CLIENT_ID)
                .build();
GoogleSignInClient client = GoogleSignIn.getClient(context, options);
GoogleSignInAccount user = Tasks.await(getGoogleSignInClient(context).silentSignIn());

// Use the new user token as before 
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
        .setJsonFactory(JacksonFactory.getDefaultInstance())
        .build();
credential.setAccessToken(user.getIdToken());
like image 129
9and3r Avatar answered Nov 14 '22 23:11

9and3r



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!