Check out what’s new from Firebase at Google I/O 2022. Learn more

驗證 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