驗證 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.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 進行驗證,或使用第三方 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
  });

爪哇

// 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應用程式選項初始化的,則 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鑰匙編號必須對應於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