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?
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.
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.
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.
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With