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

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

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

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

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

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

Solutions Collecting From Web of "使用Firebase身份validation进行身份validation后检索Google Access令牌"

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


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

  • Firebase ID令牌

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

  • 身份提供者令牌

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

  • Firebase自定义令牌

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


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

它很容易获得身份提供者令牌,它只是您显示的步骤之前的一步。

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

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

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


(简而言之,如果您已经完成设置,请查看下面的第5步。)


代码

  1. 配置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. 将Google登录按钮添加到您的应用

      
  3. 设置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. 在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. 使用Google SignInAccount进行Firebase身份validation

     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() { @Override public void onComplete(@NonNull Task 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. 最后一步:为Firebasevalidation监听器

     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); } } 

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

希望能帮助到你 !


更新:

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


更新:

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

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

代码:

 ... OkHttpClient client = new OkHttpClient(); RequestBody requestBody = new FormEncodingBuilder() .add("grant_type", "authorization_code") .add("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(); } } }); 

以下是根据需要具有访问令牌的输出:

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

希望现在有所帮助!

尝试使用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 { } } } 

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

 public class GetToken extends AsyncTask { 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; } } 

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