如果您的 Firebase 客户端应用与自定义后端服务器通信,您可能需要标识该服务器上当前已登录的用户。若要安全地执行此操作,请在用户成功登录后,使用 HTTPS 将该用户的 ID 令牌发送到您的服务器。然后,在服务器上验证 ID 令牌的完整性和真实性,并从中检索 uid
。您可以使用以这种方式传输的 uid
,安全地标识服务器上当前已登录的用户。
准备工作
为了使用 Firebase Admin SDK 验证 ID 令牌,您必须拥有一个服务账号。请参阅 Admin SDK 设置说明,详细了解如何使用服务账号初始化 Admin SDK。
在客户端上检索 ID 令牌
当用户或设备成功登录后,Firebase 会创建一个相应的 ID 令牌以进行唯一标识,并向其授予多个资源(例如 Firebase Realtime Database 和 Cloud Storage)的访问权限。您还可以将该 ID 令牌用于标识自定义后端服务器上的用户或设备。如需从客户端检索 ID 令牌,请确保用户已登录,然后从已登录的用户处获取 ID 令牌:
iOS+
Objective-C
FIRUser *currentUser = [FIRAuth auth].currentUser;
[currentUser getIDTokenForcingRefresh:YES
completion:^(NSString *_Nullable idToken,
NSError *_Nullable error) {
if (error) {
// Handle error
return;
}
// Send token to your backend via HTTPS
// ...
}];
Swift
let currentUser = FIRAuth.auth()?.currentUser
currentUser?.getIDTokenForcingRefresh(true) { idToken, error in
if let error = error {
// Handle error
return;
}
// Send token to your backend via HTTPS
// ...
}
Android
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
Unity
Firebase.Auth.FirebaseUser user = auth.CurrentUser;
user.TokenAsync(true).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("TokenAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("TokenAsync encountered an error: " + task.Exception);
return;
}
string idToken = task.Result;
// Send token to your backend via HTTPS
// ...
});
C++
firebase::auth::User user = auth->current_user();
if (user.is_valid()) {
firebase::Future<std::string> idToken = user.GetToken(true);
// Send token to your backend via HTTPS
// ...
}
Web
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
}).catch(function(error) {
// Handle error
});
拥有 ID 令牌后,您就可以将该 JWT 发送到您的后端,并使用 Firebase Admin SDK 进行验证,或者使用第三方 JWT 库(如果您的服务器使用某种非 Firebase 原生支持的语言编写)进行验证。
使用 Firebase Admin SDK 验证 ID 令牌
Firebase Admin SDK 内置了用于验证和解码 ID 令牌的方法。如果提供的 ID 令牌格式正确、未过期且经过正确签名,则该方法会返回已解码的 ID 令牌。您可以从已解码的令牌中获取用户或设备的 uid
。
请按照 Admin SDK 安装说明,使用服务账号初始化 Admin SDK。然后,使用 verifyIdToken()
方法验证 ID 令牌:
Node.js
// idToken comes from the client app
getAuth()
.verifyIdToken(idToken)
.then((decodedToken) => {
const uid = decodedToken.uid;
// ...
})
.catch((error) => {
// Handle error
});
Java
// idToken comes from the client app (shown above)
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
Python
# id_token comes from the client app (shown above)
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']
Go
client, err := app.Auth(ctx)
if err != nil {
log.Fatalf("error getting Auth client: %v\n", err)
}
token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
log.Fatalf("error verifying ID token: %v\n", err)
}
log.Printf("Verified ID token: %v\n", token)
C#
FirebaseToken decodedToken = await FirebaseAuth.DefaultInstance
.VerifyIdTokenAsync(idToken);
string uid = decodedToken.Uid;
如需验证 ID 令牌,您需要一个项目 ID。Firebase Admin SDK 将通过以下方法之一,尝试获取项目 ID:
- 如果您是使用显式
projectId
应用选项对 SDK 执行初始化,则 SDK 将使用该选项的值。 - 如果您是使用服务账号凭据对 SDK 执行初始化,则 SDK 将使用服务账号 JSON 对象的
project_id
字段。 - 如果您设置了
GOOGLE_CLOUD_PROJECT
环境变量,则 SDK 会将此环境变量值用作项目 ID。此环境变量适用于在 Google 基础设施(例如 App Engine 和 Compute Engine)上运行的代码。
使用第三方 JWT 库验证 ID 令牌
即使您的后端使用的语言不受 Firebase Admin SDK 支持,您也仍然可以验证 ID 令牌。首先,找到适合您的语言的第三方 JWT 库。然后验证 ID 令牌的标头、载荷和签名。
验证 ID 令牌的标头符合以下限制:
ID 令牌标头声明 | ||
---|---|---|
alg |
算法 | "RS256" |
kid |
密钥 ID | 必须与以下网址上列出的其中一个公钥相对应:
https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
|
验证 ID 令牌的载荷符合以下限制:
ID 令牌载荷声明 | ||
---|---|---|
exp |
到期时间 | 必须是将来的时间。时间从 UNIX 计时原点开始计算,以秒为单位。 |
iat |
颁发时间 | 必须是过去的时间。时间从 UNIX 计时原点开始计算,以秒为单位。 |
aud |
目标设备 | 必须是您的 Firebase 项目 ID(您的 Firebase 项目的唯一标识符),可在该项目控制台的网址中找到。 |
iss |
颁发者 | 必须是 "https://securetoken.google.com/<projectId>" ,其中 <projectId> 是用于上述 aud 的同一项目 ID。 |
sub |
主题 | 必须是非空字符串,并且必须是用户或设备的 uid 。 |
auth_time
|
身份验证时间 | 必须是过去的时间。指的是用户通过身份验证的时间。 |
最后,请确保 ID 令牌是通过与令牌的 kid
声明相对应的私钥进行签名的。从 https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
获取公钥并使用 JWT 库来验证签名。使用来自该端点的响应的 Cache-Control
标头中的 max-age
的值来了解何时刷新公钥。
如果上述所有验证都成功完成,您就可以使用 ID 令牌的主体 (sub
) 作为相应用户或设备的 uid
。