Retrieve Google Access Token after authenticated using Firebase Authentication Retrieve Google Access Token after authenticated using Firebase Authentication android android

Retrieve Google Access Token after authenticated using Firebase Authentication


The way you are doing will give you firebase id token, see here.


There are three types of tokens you will come across in firebase :

  • Firebase ID tokens

    Created by Firebase when a user signs in to a Firebase app. These tokens are signed JWTs that securely identify a user in a Firebase project. These tokens contain basic profile information for a user, including the user's ID string, which is unique to the Firebase project. Because the integrity of ID tokens can be verified, you can send them to a backend server to identify the currently signed-in user.

  • Identity Provider tokens

    Created by federated identity providers, such as Google and Facebook. These tokens can have different formats, but are often OAuth 2.0 access tokens. Firebase apps use these tokens to verify that users have successfully authenticated with the identity provider, and then convert them into credentials usable by Firebase services.

  • Firebase Custom tokens

    Created by your custom auth system to allow users to sign in to a Firebase app using your auth system. Custom tokens are JWTs signed using a service account's private key. Firebase apps use these tokens much like they use the tokens returned from federated identity providers.


Now, what you are getting is firebase Id token, what you need is Identity Provider Token.

Its simple to get Identity Provider token, its just one step previous to the step you have shown.

So, the way we sign in google using firebase is mentioned here.

I will add below the complete code which displays a button in UI, which on clicked, will sign in user to google account. And then I will get the google access token, which is then send to firebase, where it is converted to firebase token Id.

I presume that you have configured android app for google sign in, if not, you can go into details here.


(To cut things short, just look at Step 5 below, if you have done setup already.)
Code :

  1. Configure Google SignIn and GoogleApiClient :

     // Configure sign-in to request the user's ID, email address, and basic // profile. ID and basic profile are included in DEFAULT_SIGN_IN. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)    .requestIdToken(getString(R.string.default_web_client_id))    .requestEmail()    .build(); // NOTE :  // The string passed to requestIdToken, default_web_client_id,  // can be obtained from credentials page (https://console.developers.google.com/apis/credentials). // There mentioned Web application type client ID is this string. // ...  // Build a GoogleApiClient with access to the Google Sign-In API and the // options specified by gso. mGoogleApiClient = new GoogleApiClient.Builder(this)    .enableAutoManage(this /* Activity */, this /* OnConnectionFailedListener */)    .addApi(Auth.GOOGLE_SIGN_IN_API, gso)    .build();
  2. Add the Google Sign-In button to your app

    <com.google.android.gms.common.SignInButton    android:id="@+id/sign_in_button"    android:layout_width="wrap_content"    android:layout_height="wrap_content" />
  3. Set SignIn Click Listener

    findViewById(R.id.sign_in_button).setOnClickListener(new OnClickListener() {    public void onClick(View v){        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);        startActivityForResult(signInIntent, RC_SIGN_IN);       }});
  4. Override OnActivityResult method in Activity :

    @Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);    if (requestCode == RC_SIGN_IN) {        // Google Sign In was successful, authenticate with Firebase        GoogleSignInAccount account = result.getSignInAccount();        firebaseAuthWithGoogle(account); // This method is implemented in step 5.    } else {        // Google Sign In failed, update UI appropriately        // ...    }}
  5. Firebase Authentication With Google SignInAccount

    String idTokenString = "";...private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {    Log.d(TAG, "Google User Id :" + acct.getId());    // --------------------------------- //    // BELOW LINE GIVES YOU JSON WEB TOKEN, (USED TO GET ACCESS TOKEN) :     Log.d(TAG, "Google JWT : " + acct.getIdToken());    // --------------------------------- //    // Save this JWT in global String :     idTokenString = acct.getIdToken();    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);    mAuth.signInWithCredential(credential)        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {            @Override            public void onComplete(@NonNull Task<AuthResult> task) {                Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());                if(task.isSuccessful()){                    // --------------------------------- //                    // BELOW LINE GIVES YOU FIREBASE TOKEN ID :                     Log.d(TAG, "Firebase User Access Token : " + task.getResult().getToken());                    // --------------------------------- //                }                // If sign in fails, display a message to the user. If sign in succeeds                // the auth state listener will be notified and logic to handle the                // signed in user can be handled in the listener.                else {                    Log.w(TAG, "signInWithCredential", task.getException());                    Toast.makeText(GoogleSignInActivity.this, "Authentication failed.",                            Toast.LENGTH_SHORT).show();                }            }        });}
  6. Final Step : Auth Listeners for Firebase

    private FirebaseAuth mAuth;private FirebaseAuth.AuthStateListener mAuthListener;@Overrideprotected void onCreate(Bundle savedInstanceState) {    // ...    mAuth = FirebaseAuth.getInstance();    mAuthListener = new FirebaseAuth.AuthStateListener() {        @Override        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {            FirebaseUser user = firebaseAuth.getCurrentUser();            if (user != null) {                // User is signed in                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());            } else {               // User is signed out               Log.d(TAG, "onAuthStateChanged:signed_out");            }            // ...        }   };   // ...}//...@Overridepublic void onStart() {    super.onStart();    mAuth.addAuthStateListener(mAuthListener);}@Overridepublic void onStop() {    super.onStop();    if (mAuthListener != null) {        mAuth.removeAuthStateListener(mAuthListener);    }}

So, your answer lies in Step 5, which was just before you authenticated to firebase and just after you authenticated in google sign in.

Hope it helps !


UPDATE :

Its important that in Step 1, you request for token Id, otherwise in Step 5, you will get null token id. For more see here. I have updated Step 1.


UPDATE :

As per discussion, the retrieved token was JWT token as written here. And what we need is google access token. Below code uses the JWT token to fire at OAuth backend and retrieve this access token :

(Note : I have used okhttp version 2.6.0, other versions might have different methods)

Code :

...OkHttpClient client = new OkHttpClient();RequestBody requestBody = new FormEncodingBuilder()            .add("grant_type", "authorization_code")            .add("client_id", "<Your-client-id>")   // something like : ...apps.googleusercontent.com            .add("client_secret", "{Your-client-secret}")            .add("redirect_uri","")            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8") // device code.            .add("id_token", idTokenString) // This is what we received in Step 5, the jwt token.            .build();final Request request = new Request.Builder()        .url("https://www.googleapis.com/oauth2/v4/token")        .post(requestBody)        .build();client.newCall(request).enqueue(new Callback() {    @Override    public void onFailure(final Request request, final IOException e) {        Log.e(LOG_TAG, e.toString());                    }    @Override    public void onResponse(Response response) throws IOException {        try {            JSONObject jsonObject = new JSONObject(response.body().string());            final String message = jsonObject.toString(5);            Log.i(LOG_TAG, message);                            } catch (JSONException e) {            e.printStackTrace();        }    }});

Here is the output which has access token as required :

I/onResponse: {          "expires_in": 3600,          "token_type": "Bearer",          "refresh_token": "1\/xz1eb0XU3....nxoALEVQ",          "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjQxMWY1Ym......yWVsUA",          "access_token": "ya29.bQKKYah-........_tkt980_qAGIo9yeWEG4"     }

Hope now it helps !


Try GoogleAuthUtil.getToken where scope is like "oauth2:scope1 scope2 scope3"

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)            .requestIdToken(getString(R.string.default_web_client_id))            .requestEmail()            .build();    mGoogleApiClient = new GoogleApiClient.Builder(this)            .enableAutoManage(this, this)            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)            .build();}private void signIn() {    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);    startActivityForResult(signInIntent, RC_SIGN_IN);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == RC_SIGN_IN) {        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);        if (result.isSuccess()) {            final GoogleSignInAccount account = result.getSignInAccount();                Runnable runnable = new Runnable() {                    @Override                    public void run() {                        try {                            String scope = "oauth2:"+Scopes.EMAIL+" "+ Scopes.PROFILE;                            String accessToken = GoogleAuthUtil.getToken(getApplicationContext(), account.getAccount(), scope, new Bundle());                            Log.d(TAG, "accessToken:"+accessToken); //accessToken:ya29.Gl...                        } catch (IOException e) {                            e.printStackTrace();                        } catch (GoogleAuthException e) {                            e.printStackTrace();                        }                    }                };                AsyncTask.execute(runnable);        } else {        }    }}


I'm following the @vovkas solution, and want to let you know that with the last update 11.6.0 you can get the Account needed more easily, so you can have everything inside a handy dandy AsyncTask to be reused whenever you want to:

public class GetToken extends AsyncTask<Void, Void, String> {    private final Context context;    public GetToken(Context context) {        this.context = context;    }    @Override    protected String doInBackground(Void... voids) {        try {            String scope = "oauth2:" + Scopes.EMAIL + " " + Scopes.PROFILE;            GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(context);            return GoogleAuthUtil.getToken(context, account.getAccount(), scope, new Bundle());        } catch (IOException e) {            e.printStackTrace();        } catch (GoogleAuthException e) {            e.printStackTrace();        }        return null;    }}

The key is to use GoogleSignIn.getLastSignedInAccount(context).