验证 ID 令牌

如果您的 Firebase 客户端应用与自定义后端服务器通信,您可能需要标识当前服务器上已登录的用户。要安全地执行此操作,请在用户成功登录后,使用 HTTPS 将用户的 ID 令牌发送到服务器,然后在服务器上验证 ID 令牌的完整性和真实性,并从中检索 uid。您可以使用以这种方式传输的 uid 来安全地标识服务器上当前已登录的用户。

开始之前

要使用 Firebase Admin SDK 验证 ID 令牌,您必须拥有一个服务帐号。请参阅 Admin SDK 设置说明,详细了解如何使用服务帐号初始化 Admin SDK。

在客户端上检索 ID 令牌

当用户或设备成功登录后,Firebase 会创建一个相应的 ID 令牌,此令牌可以唯一标识他们,并授予他们访问多个资源(例如 Firebase 实时数据库和云端存储)的权限。您还可以将该 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 != nullptr) {
  firebase::Future<std::string> idToken = user->GetToken(true);

  // Send token to your backend via HTTPS
  // ...
}

网页

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 (shown above)

admin.auth().verifyIdToken(idToken)
  .then(function(decodedToken) {
    var uid = decodedToken.uid;
    // ...
  }).catch(function(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(context.Background())
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)

使用第三方 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

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面