获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

验证 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
          // ...
}];
迅速
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
  // ...
}

安卓

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

统一

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 验证它,或者如果您的服务器是用 Firebase 本身不支持的语言编写的,则可以使用第三方 JWT 库。

使用 Firebase Admin SDK 验证 ID 令牌

Firebase Admin SDK 具有用于验证和解码 ID 令牌的内置方法。如果提供的 ID 令牌具有正确的格式、未过期且已正确签名,则该方法返回解码后的 ID 令牌。您可以从解码的令牌中获取用户或设备的uid

按照Admin SDK 设置说明使用服务帐户初始化 Admin SDK。然后,使用verifyIdToken()方法验证 ID 令牌:

节点.js

// idToken comes from the client app
getAuth()
  .verifyIdToken(idToken)
  .then((decodedToken) => {
    const uid = decodedToken.uid;
    // ...
  })
  .catch((error) => {
    // Handle error
  });

爪哇

// 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']

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:

  • 如果 SDK 使用显式projectId app 选项初始化,则 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 项目的唯一标识符,可以在该项目控制台的 URL 中找到。
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