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?
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());