How to get access token after user is signed in from Gmail in Android? How to get access token after user is signed in from Gmail in Android? android android

How to get access token after user is signed in from Gmail in Android?


For your requirements, you can use the following code:

Firstly, make sure you have a valid Web OAuth 2.0 Client ID:

<!-- Server Client ID.  This should be a valid Web OAuth 2.0 Client ID obtained         from https://console.developers.google.com/ -->    <string name="server_client_id">...e4p8.apps.googleusercontent.com</string>

Then inside Activity class:

@Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    ...    // For sample only: make sure there is a valid server client ID.    validateServerClientID();    // [START configure_signin]    // Configure sign-in to request offline access to the user's ID, basic    // profile, and Google Drive. The first time you request a code you will    // be able to exchange it for an access token and refresh token, which    // you should store. In subsequent calls, the code will only result in    // an access token. By asking for profile access (through    // DEFAULT_SIGN_IN) you will also get an ID Token as a result of the    // code exchange.    String serverClientId = getString(R.string.server_client_id);    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)            .requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))            .requestServerAuthCode(serverClientId)            .requestEmail()            .build();    // [END configure_signin]    // Build GoogleAPIClient with the Google Sign-In API and the above options.    mGoogleApiClient = new GoogleApiClient.Builder(this)            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)            .build();}private void getAuthCode() {    // Start the retrieval process for a server auth code.  If requested, ask for a refresh    // token.  Otherwise, only get an access token if a refresh token has been previously    // retrieved.  Getting a new access token for an existing grant does not require    // user consent.    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);    startActivityForResult(signInIntent, RC_GET_AUTH_CODE);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == RC_GET_AUTH_CODE) {        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);        Log.d(TAG, "onActivityResult:GET_AUTH_CODE:success:" + result.getStatus().isSuccess());        if (result.isSuccess()) {            // [START get_auth_code]            GoogleSignInAccount acct = result.getSignInAccount();            String authCode = acct.getServerAuthCode();            // Show signed-in UI.            mAuthCodeTextView.setText(getString(R.string.auth_code_fmt, authCode));            updateUI(true);            // TODO(user): send code to server and exchange for access/refresh/ID tokens.            // [END get_auth_code]        } else {            // Show signed-out UI.            updateUI(false);        }    }}

You can see the entire code at the following ServerAuthCodeActivity.java

The result, if you use that sample, looks like the following screenshot:

BNK's screenshot

Then, you can follow the steps mentioned at the Google's documentation below (from step #3. Send the auth code to your app's backend using HTTPS POST):

Google Sign-In for Android - Enabling Server-Side Access


UPDATE: from the comments, if you want to get access token directly from android client app, please use the following sample code (replaced with your client_id, client_secret and the auth code)

OkHttpClient client = new OkHttpClient();    RequestBody requestBody = new FormEncodingBuilder()            .add("grant_type", "authorization_code")            .add("client_id", "812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com")            .add("client_secret", "{clientSecret}")            .add("redirect_uri","")            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8")            .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();            }        }    });

Please use compile 'com.squareup.okhttp:okhttp:2.6.0' (ver 3-RC1 will have different classes)

With a sucessful response, you will have the following info in logcat:

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


BNK has it spot on for the most part. The Activity class is the same as BNKs answer only with adding the OkHttp part once you get the GoogleSignInAccount in the onActivityResult() method.

But I was still getting errors with the OkHttp request part. Finally after a bit of testing(and part luck) around in Postman, I found that I was missing the id_token parameter. The OkHttp request was missing one parameter i.e the id_token. Use the ID token that you get from the GoogleSignInAccount something like this

GoogleSignInAccount acct = result.getSignInAccount();String idTokenString = acct.getIdToken();

Now use this idTokenString along with all the parameters in the OkHttp part of BNK's answer somewhat like this

...RequestBody requestBody = new FormEncodingBuilder()            .add("grant_type", "authorization_code")            .add("client_id", "alpha-numeric-string-here.apps.googleusercontent.com")            .add("client_secret", "{clientSecret}")            .add("redirect_uri","")            .add("code", "4/4-alphabetic-string-here")            .add("id_token", idTokenString) // Added this extra parameter here            .build();...

The response one gets is same as BNKs answer

{  "access_token": "ya29.CjBgA_I58IabCJ...remainingAccessTokenHere",  "token_type": "Bearer",  "expires_in": 3577,  "id_token": "eyJhbGciOiJS...veryLongStringHere"}

Now send this access_token to your backend server to authenticate just like you used to do during the times of GoogleAuthUtil and PlusAPI.

Hope this helps :) Special thanks to BNK!


Here it`s my approach with Kotlin, (this is my first Answer on StackOverflow, if there is something wrong, missing, or that i can do it better, let me know)

On the Login Actvity

private fun configureGoogleSignIn() {    mGoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)        .requestIdToken(getString(R.string.default_web_client_id))        .requestServerAuthCode(getString(R.string.server_client_id_oauth))        .requestEmail()        .build()    mGoogleSignInClient = GoogleSignIn.getClient(this, mGoogleSignInOptions)}private fun signInWithGoogle() {    val signInIntent: Intent = mGoogleSignInClient.signInIntent    startActivityForResult(signInIntent, RC_SIGN_IN)}

Make sure to Call configureGoogleSignIn() function on the OnCreate

Then to get the result

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {    super.onActivityResult(requestCode, resultCode, data)    callbackManager?.onActivityResult(requestCode, resultCode, data)    if (requestCode == RC_SIGN_IN) {        val tag = "onActivityResult RC_SIGN_IN"        val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)        try {            val account = task.getResult(ApiException::class.java)            firebaseAuthWithGoogle(account!!)            getIdTokenFromFirebaseAuth()            var acct = GoogleSignIn.getLastSignedInAccount(this)            if (acct != null) {                var personName = acct.displayName                firstName = acct.givenName!!                lastName = acct.familyName!!                userEmail = acct.email!!                authCode = acct.serverAuthCode!! //THIS is what you looking for                googleIdToken2 = acct.idToken!!                Log.d(tag, authCode)                Log.d(tag, googleIdToken2)                var personId = acct.id                //todo pegar foto do google e por no cadastro do usuario                var personPhoto = acct.photoUrl                spinner.visibility = View.GONE                getGoogleAccessToken()            }        } catch (e: ApiException) {            spinner.visibility = View.GONE            infoToUserTextView.text = getString(R.string.ops_we_had_a_problem)        }    }}

Then make a Call To Google API (i`m using Retrofit), using this interface make :

@FormUrlEncoded@POSTfun getAccessTokenGoogle(    @Url url: String,    @Field("grant_type") grant_type: String,    @Field("client_id") client_id: String,    @Field("client_secret") client_secret: String,    @Field("redirect_uri") redirect_uri: String,    @Field("code") authCode: String,    @Field("id_token") id_token: String):Call<GoogleSignInAccessTokenDataClass>

Here it`s the GoogleSignInAccessTokenDataClass

data class GoogleSignInAccessTokenDataClass(val access_token: String,val expires_in: Int,val id_token: String,val token_type: String

)

Make the Call on the Login Activity

private fun getGoogleAccessToken(){    val call = RetrofitGet().userInfoGson().getAccessTokenGoogle(        grant_type = "authorization_code", client_id = getString(R.string.server_client_id_oauth),        client_secret = getString(R.string.server_client_secret_oauth), redirect_uri = "",        authCode = authCode, id_token =googleIdToken2, url = googleTokenUrl    )    call.enqueue(object : Callback<GoogleSignInAccessTokenDataClass>{        val tag = "getGoogleAccessToken"        override fun onFailure(call: Call<GoogleSignInAccessTokenDataClass>, t: Throwable) {            Log.e(tag, t.toString())        }        override fun onResponse(            call: Call<GoogleSignInAccessTokenDataClass>,            response: Response<GoogleSignInAccessTokenDataClass>        ) {            if (response.isSuccessful){                val responseBody = response.body()                googleAccessToken = responseBody!!.access_token                Log.d(tag, googleAccessToken)            }else{                try {                    val responseError = response.errorBody()!!.string()                    Log.e(tag, responseError)                }catch (e:Exception){Log.e(tag, e.toString())}            }        }    })}