使用Firebase身份验证进行身份验证后检索Google Access令牌

时间:2022-12-03 21:55:38

I am trying to retrieve Google Access Token to access Google REST API such as YouTube Data API from an authenticated user (using Firebase Authentication).

我正在尝试从经过身份验证的用户(使用Firebase身份验证)检索Google Access令牌以访问Google REST API,例如YouTube Data API。

I have successfully integrated Google Sign-In in my app with the help of Firebase-UI for Android - Auth library. The token retrieved from FirebaseUser.getToken() method is not a valid Google Access Token for REST API.

我已经在Firebase-UI for Android - Auth库的帮助下成功地在我的应用中集成了Google登录。从FirebaseUser.getToken()方法检索的令牌不是REST API的有效Google Access令牌。

user.getToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
    public void onComplete(@NonNull Task<GetTokenResult> task) {
        if (task.isSuccessful()) {
            String token = task.getResult().getToken();
            // 'token' is not a Google Access Token
        }
    }
});

In Google Sign-In for Web guide, it's possible to get the access token by calling var token = result.credential.accessToken;, but I can't find the similar method in Android.

在Google Sign-In for Web指南中,可以通过调用var token = result.credential.accessToken;来获取访问令牌,但我在Android中找不到类似的方法。

Any inputs? Please comment here if I do not provide enough information. Thank you :)

有什么输入?如果我没有提供足够的信息,请在这里发表评论。谢谢 :)

3 个解决方案

#1


34  

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

你正在做的方式会给你firebase id令牌,请看这里。


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

您将在firebase中遇到三种类型的令牌:

  • Firebase ID tokens

    Firebase ID令牌

    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.

    用户登录Firebase应用时由Firebase创建。这些令牌是签名的JWT,可以安全地识别Firebase项目中的用户。这些令牌包含用户的基本配置文件信息,包括用户的ID字符串,这是Firebase项目所特有的。由于可以验证ID令牌的完整性,因此您可以将它们发送到后端服务器以识别当前登录的用户。

  • 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.

    由联合身份提供商(如Google和Facebook)创建。这些令牌可以具有不同的格式,但通常是OAuth 2.0访问令牌。 Firebase应用使用这些令牌来验证用户是否已成功通过身份提供商进行身份验证,然后将其转换为Firebase服务可用的凭据。

  • Firebase Custom tokens

    Firebase自定义令牌

    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.

    由您的自定义身份验证系统创建,允许用户使用您的身份验证系统登录Firebase应用。自定义令牌是使用服务帐户的私钥签名的JWT。 Firebase应用程序使用这些令牌非常类似于使用联合身份提供程序返回的令牌。


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

现在,你得到的是firebase Id令牌,你需要的是身份提供者令牌。

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.

因此,我们在这里提到了使用firebase登录谷歌的方式。

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.

我将在下面添加完整的代码,在UI中显示一个按钮,点击该按钮,将用户登录到Google帐户。然后我将获得google访问令牌,然后将其发送到firebase,然后将其转换为firebase令牌ID。

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

我认为你已经为谷歌登录配置了Android应用程序,如果没有,你可以在这里详细介绍。


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

  1. Configure Google SignIn and GoogleApiClient :

    配置Google SignIn和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

    将Google登录按钮添加到您的应用

    <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

    设置SignIn单击“侦听器”

    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 :

    在Activity中覆盖OnActivityResult方法:

    @Override
    public 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

    使用Google SignInAccount进行Firebase身份验证

    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

    最后一步:为Firebase验证监听器

    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    
    @Override
    protected 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");
                }
                // ...
            }
       };
       // ...
    }
    
    //...
    
    @Override
    public void onStart() {
        super.onStart();
        mAuth.addAuthStateListener(mAuthListener);
    }
    
    @Override
    public 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.

所以,你的答案在于第5步,就在你对firebase进行身份验证之前,以及在google登录后进行身份验证之后。

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.

重要的是,在步骤1中,您请求令牌ID,否则在步骤5中,您将获得空令牌ID。有关详情,请参阅此处我已经更新了第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 :

根据讨论,检索到的令牌是这里写的JWT令牌。我们需要的是谷歌访问令牌。下面的代码使用JWT令牌在OAuth后端触发并检索此访问令牌:

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

(注意:我使用过okhttp 2.6.0版,其他版本可能有不同的方法)

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 !

希望现在有所帮助!

#2


18  

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

尝试使用GoogleAuthUtil.getToken,其范围类似于“oauth2:scope1 scope2 scope3”

@Override
protected 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);
}

@Override
protected 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 {
        }
    }
}

#3


2  

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:

我正在关注@vovkas解决方案,并希望告诉您,通过上次更新11.6.0,您可以更轻松地获得所需的帐户,因此您可以随时随地使用方便的花花公子AsyncTask中的所有内容:

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).

关键是要使用GoogleSignIn.getLastSignedInAccount(context)。

#1


34  

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

你正在做的方式会给你firebase id令牌,请看这里。


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

您将在firebase中遇到三种类型的令牌:

  • Firebase ID tokens

    Firebase ID令牌

    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.

    用户登录Firebase应用时由Firebase创建。这些令牌是签名的JWT,可以安全地识别Firebase项目中的用户。这些令牌包含用户的基本配置文件信息,包括用户的ID字符串,这是Firebase项目所特有的。由于可以验证ID令牌的完整性,因此您可以将它们发送到后端服务器以识别当前登录的用户。

  • 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.

    由联合身份提供商(如Google和Facebook)创建。这些令牌可以具有不同的格式,但通常是OAuth 2.0访问令牌。 Firebase应用使用这些令牌来验证用户是否已成功通过身份提供商进行身份验证,然后将其转换为Firebase服务可用的凭据。

  • Firebase Custom tokens

    Firebase自定义令牌

    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.

    由您的自定义身份验证系统创建,允许用户使用您的身份验证系统登录Firebase应用。自定义令牌是使用服务帐户的私钥签名的JWT。 Firebase应用程序使用这些令牌非常类似于使用联合身份提供程序返回的令牌。


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

现在,你得到的是firebase Id令牌,你需要的是身份提供者令牌。

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.

因此,我们在这里提到了使用firebase登录谷歌的方式。

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.

我将在下面添加完整的代码,在UI中显示一个按钮,点击该按钮,将用户登录到Google帐户。然后我将获得google访问令牌,然后将其发送到firebase,然后将其转换为firebase令牌ID。

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

我认为你已经为谷歌登录配置了Android应用程序,如果没有,你可以在这里详细介绍。


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

  1. Configure Google SignIn and GoogleApiClient :

    配置Google SignIn和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

    将Google登录按钮添加到您的应用

    <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

    设置SignIn单击“侦听器”

    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 :

    在Activity中覆盖OnActivityResult方法:

    @Override
    public 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

    使用Google SignInAccount进行Firebase身份验证

    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

    最后一步:为Firebase验证监听器

    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    
    @Override
    protected 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");
                }
                // ...
            }
       };
       // ...
    }
    
    //...
    
    @Override
    public void onStart() {
        super.onStart();
        mAuth.addAuthStateListener(mAuthListener);
    }
    
    @Override
    public 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.

所以,你的答案在于第5步,就在你对firebase进行身份验证之前,以及在google登录后进行身份验证之后。

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.

重要的是,在步骤1中,您请求令牌ID,否则在步骤5中,您将获得空令牌ID。有关详情,请参阅此处我已经更新了第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 :

根据讨论,检索到的令牌是这里写的JWT令牌。我们需要的是谷歌访问令牌。下面的代码使用JWT令牌在OAuth后端触发并检索此访问令牌:

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

(注意:我使用过okhttp 2.6.0版,其他版本可能有不同的方法)

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 !

希望现在有所帮助!

#2


18  

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

尝试使用GoogleAuthUtil.getToken,其范围类似于“oauth2:scope1 scope2 scope3”

@Override
protected 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);
}

@Override
protected 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 {
        }
    }
}

#3


2  

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:

我正在关注@vovkas解决方案,并希望告诉您,通过上次更新11.6.0,您可以更轻松地获得所需的帐户,因此您可以随时随地使用方便的花花公子AsyncTask中的所有内容:

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).

关键是要使用GoogleSignIn.getLastSignedInAccount(context)。