Search code examples
androidgoogle-oauthgoogle-signingoogle-account

Get CODE from Google Cross-Client Authentication on Android


I'm working on an Android app that requires a Google OAuth 2.0 API code for Google account sign-in which will be used by the web app under the same project.

I failed to get that code, I'm getting an AccessToken instead.

I followed this docs by Google Using their AsyncTask calss

public class GetUsernameTask extends AsyncTask<Void, Void, Void> {
    Activity mActivity;
    String mScope;
    String mEmail;
    private String token;

    public GetUsernameTask(Activity activity, String name, String scope) {
            this.mActivity = activity;
            this.mScope = scope;
            this.mEmail = name;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            DialogsUtil.showProgressDialog(mActivity, DialogsUtil.PROGRESS_SIGNIN);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                token = fetchToken();
                if (token != null) {
                    // My method to make a backend call using the `token`
                    loginWithGoogleToken(token); 
                }
            } catch (IOException e) {
            }
            DialogsUtil.dismissProgressDialog();
            return null;
        }

        protected String fetchToken() throws IOException {
            try {
                return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
            } catch (UserRecoverableAuthException userRecoverableException) {
            } catch (GoogleAuthException fatalException) {
            }
            return null;
        }
    }

I'm showing the AccountPicker on a button click as:

String[] accountTypes = new String[]{"com.google"};
Intent intent = AccountPicker.newChooseAccountIntent(null, null,accountTypes, false, null, null, null, null);
startActivityForResult(intent, RC_SIGN_IN);

Then in onActivityResult:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == RC_SIGN_IN) {
        // Initialize scope
        String clientID = context.getResources().getString(R.string.server_client_id);
        String audienceScope = "audience:server:client_id:" + clientID;
        String email = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
        new GetUsernameTask(activity, email, audienceScope).execute();
    }}

Using the scope audience:server:client_id: + clientID makes GoogleAuthUtil.getToken()return an AccessToken which not I want.

Using scope as String.format("oauth2:server:client_id:%s:api_scope:https://www.googleapis.com/auth/userinfo.profile", clientID); makes GoogleAuthUtil.getToken()return a null not the expected Code I want!


Solution

  • the short code used by the server is called serverAuthCode and you can get it by following these steps :

    Firstly setting up sdk with server-client-id and scopes

    String serverClientId = getString(R.string.server_client_id);
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
           .requestScopes(new Scope(Scopes.PLUS_ME))
           .requestServerAuthCode(serverClientId, false)
           .build();
    
    // Build GoogleAPIClient with the Google Sign-In API and the above options.
    GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
           .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
           .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
           .build();
    
    
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
    

    and on activity result

    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
    if (result.isSuccess()) {
        GoogleSignInAccount acct = result.getSignInAccount();
        String idToken = acct.getServerAuthCode();
        Log.e(TAG, "ServerToken : " + acct.getServerAuthCode());
    
        // send token to your backend
        loginWithGoogleToken(idToken);
    } else {
         Log.e(TAG, "Error getting token");
    }