驗證 ID 權杖

如果您的 Firebase 用戶端應用程式與自訂後端伺服器通訊,您可能需要在該伺服器上找出目前登入的使用者。為了以安全的方式完成此作業,請在成功登入後,使用 HTTPS 將使用者的 ID 權杖傳送至您的伺服器。接著,在伺服器上驗證 ID 權杖的完整性和真實性,並從中擷取 uid。您可以使用以這種方式傳輸的 uid,安全地識別伺服器上目前登入的使用者。

事前準備

如要透過 Firebase Admin SDK 驗證 ID 權杖,您必須擁有服務帳戶。請參閱「Admin SDK 設定操作說明」,進一步瞭解如何使用服務帳戶初始化 Admin SDK。

在用戶端擷取 ID 權杖

當使用者或裝置成功登入時,Firebase 會建立對應的 ID 符記來識別使用者,並授予他們多項資源的存取權,例如 Firebase 即時資料庫和 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
  // ...
}

網站

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 權杖:

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:

  • 如果 SDK 是透過明確的 projectId 應用程式選項初始化,SDK 會使用該選項的值。
  • 如果 SDK 是使用服務帳戶憑證初始化,SDK 會使用服務帳戶 JSON 物件的 project_id 欄位。
  • 如果設定了 GOOGLE_CLOUD_PROJECT 環境變數,SDK 會使用其值做為專案 ID。在 App Engine 和 Compute Engine 等 Google 基礎架構上執行的程式碼,都能使用這個環境變數。

使用第三方 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 專案的專屬 ID,你可以在該專案控制台的網址中找到這個 ID。
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