您所做的方式将为您提供 firebase id 令牌,请参阅here.
您在 firebase 中会遇到三种类型的令牌:
-
Firebase ID 令牌
当用户登录 Firebase 应用时由 Firebase 创建。这些令牌是经过签名的 JWT,可安全地识别 Firebase 项目中的用户。这些令牌包含用户的基本个人资料信息,包括用户的 ID 字符串,该字符串对于 Firebase 项目是唯一的。由于可以验证 ID 令牌的完整性,因此您可以将它们发送到后端服务器来识别当前登录的用户。
-
身份提供商令牌
由联合身份提供商创建,例如 Google 和 Facebook。这些令牌可以具有不同的格式,但通常是 OAuth 2.0 访问令牌。 Firebase 应用使用这些令牌来验证用户是否已成功通过身份提供商的身份验证,然后将它们转换为 Firebase 服务可以使用的凭据。
-
Firebase 自定义令牌
由您的自定义身份验证系统创建,以允许用户使用您的身份验证系统登录 Firebase 应用。自定义令牌是使用服务帐户的私钥签名的 JWT。 Firebase 应用程序使用这些令牌的方式与使用从联合身份提供商返回的令牌非常相似。
现在,您得到的是 firebase Id 令牌,您需要的是身份提供者令牌。
获取身份提供商令牌很简单,只需比您所显示的步骤早一步即可。
那么,我们使用firebase登录google的方式就提到了here.
我将在下面添加完整的代码,该代码在用户界面中显示一个按钮,单击该按钮后,用户将登录到谷歌帐户。然后我将获取 google 访问令牌,然后将其发送到 firebase,在那里将其转换为 firebase 令牌 Id。
我假设你已经配置了android应用程序用于谷歌登录,如果没有,你可以详细说明here.
(To cut things short, just look at Step 5 below, if you have done setup already.)
Code :
-
配置 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();
-
将 Google 登录按钮添加到您的应用中
<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
-
设置登录点击监听器
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);
}
});
-
覆盖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
// ...
}
}
-
使用 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();
}
}
});
}
-
最后一步: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);
}
}
所以,你的答案就在第 5 步,即在你向 Firebase 进行身份验证之前以及在 google 登录中进行身份验证之后。
希望能帮助到你 !
UPDATE :
重要的是,在步骤 1 中,您请求令牌 Id,否则在步骤 5 中,您将得到空令牌 id。更多请参见here。我已经更新了步骤 1。
UPDATE :
根据讨论,检索到的令牌是所写的 JWT 令牌here。我们需要的是谷歌访问令牌。下面的代码使用 JWT 令牌在 OAuth 后端触发并检索此访问令牌:
(注:我使用的是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();
}
}
});
这是具有所需访问令牌的输出:
I/onResponse: {
"expires_in": 3600,
"token_type": "Bearer",
"refresh_token": "1\/xz1eb0XU3....nxoALEVQ",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjQxMWY1Ym......yWVsUA",
"access_token": "ya29.bQKKYah-........_tkt980_qAGIo9yeWEG4"
}
希望现在有帮助!