Search code examples
androidpermissionsgoogle-play-gamesscopes

Android getServerAuthCode() without extra permissions


I'm trying to authenticate an Android user with a backend server:

  • the app calls getServerAuthCode() and forwards the authorization code using HTTPS to our BE
  • the BE exchanges the server authorization code for an access token using GoogleAuthorizationCodeTokenRequest
  • the BE passes the access token to www.googleapis.com/games/v1/applications which returns the playerId (that's all I really need, I don't care for email and other user information)

The procedure is outlined here:

and here

If I use the the instruction from 2017 I'm able to getServerAuthCode() without requesting any extra permissions. The only permission is: Google Play / Manage your game activity for this game. This is possible by specifying GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN which is available on by using play-service 10.2.1. I'm unable to use 10.2.1 because of 3rd party dependencies.

The 2016 article explains how to getServerAuthCode() the 'old' way (using play-services 9.6.1), but I'm not able to get by without requesting some extra permissions.

If I do it like this, I get the asked for "Know who you are on google":

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
    .requestServerAuthCode(serverClientId)
    .requestScopes(Games.SCOPE_GAMES)
    .build();

mGoogleApiClient = new GoogleApiClient.Builder(this)
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
    .build();

        ...

protected void onActivityResult(int request, int response, Intent data) {
    super.onActivityResult(request, response, data);

    if (request == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

        if (result.isSuccess()) {
            GoogleSignInAccount acct = result.getSignInAccount();
            String authCode = acct.getServerAuthCode();
        }

If I remove .requestServerAuthCode(serverClientId) from gso, authCode is null.

Another thing I tried (using only Games.API sign in):

mGoogleApiClient = new GoogleApiClient.Builder(this, this, this)
    .addApi(Games.API)
    .build();

...

Games.GetServerAuthCodeResult result = Games.getGamesServerAuthCode(mGoogleApiClient, serverClinetId).await();

if (result.getStatus().isSuccess()) {
    String authCode = result.getCode();

I get result.getStatus().isSuccess()=false and result.getStatus().getStatusMessage() returns STATUS_CLIENT_RECONNECT_REQUIRED (2). In the logs I see:

[GetToken] GetToken failed with status code: NeedPermission
04-10 14:27:41.764: W/GamesServerAuthCodeOp(5775): Failed to retrieve the server auth code
04-10 14:27:41.764: W/GamesServerAuthCodeOp(5775): com.google.android.gms.auth.UserRecoverableAuthException: NeedPermission

Finnaly, the best I was able to achieve is to get 'only' the "View your basic profile info" permission doing this:

Scope scope = new Scope("https://www.googleapis.com/auth/userinfo.profile");

mGoogleApiClient = new GoogleApiClient.Builder(this, this, this)
    .addApi(Games.API)
    .addScope(scope)
    .build();

So to recap - I want to get the server authorization code using 9.6.1 without being prompted for any extra permissions (like in the 2017 article using 10.2.1 using DEFAULT_GAMES_SIGN_IN).

Are there any scopes I can use that will give me the server authorization code (to get the playerId) without requesting extra permissions?


Solution

  • Unfortunately, no. The scope you're already using is the right (and the simplest) way to retrieve an auth code and at the same time get a playerId.