Search code examples
androidgoogle-signingoogle-authenticationgoogle-api-nodejs-client

Authenticate with backend w/o user intervention (using the new Sign-in APIs)


We're currently able to authenticate requests between our Android client and server using a deprecated approach:

String scope = "audience:server:client_id:" + SERVER_CLIENT_ID;
String account = getAnyGoogleAccountFromDevice();
String idToken = GoogleAuthUtil.getToken(context, account, scope);

On the server side we validate the idToken using Google's certificates and verify the audience is our client.

This works well, but it seems Google has deprecated this approach and wants developers to switch to the new Sign-in APIs from PlayServices 8.3+:
https://android-developers.googleblog.com/2015/11/improvements-to-sign-in-with-google.html
https://developers.googleblog.com/2016/11/moving-to-google-sign-in-for-a-better-user-experience-and-higher-conversion-rates.html

But the new docs approach, explained here and here, doesn't allow use of some Google account we give it, but instead requires the user to sign-in to the app. We want to have a transparent way of authenticating with the backend, without any user intervention or UI, we don't need the user's name/email/profile information, just require some token to validate the requests are coming from our own client.

Is there a way to do that using the new Google Sign-in APIs?


Solution

  • If you already know the user's email address you can refresh the ID token with the following:

    // Run on a non-UI thread
    
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .setAccountName(emailAddress)
        .requestIdToken(SERVER_CLIENT_ID)
        .build();
    
    GoogleApiClient client = new Builder(context)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();
    
    ConnectionResult conn = client.blockingConnect();
    if (!conn.isSuccess()) {
        Log.e(TAG, "Couldn't connect GoogleApiClient");
        return;
    }
    
    GoogleSignInResult result = Auth.GoogleSignInApi.silentSignIn(client).await();
    GoogleSignInAccount acct = result.getSignInAccount();
    Log.d(TAG, "ID Token: " + acct.getIdToken());
    
    client.disconnect();