ยืนยันโทเค็นรหัส

หากแอปไคลเอ็นต์ Firebase สื่อสารกับเซิร์ฟเวอร์แบ็กเอนด์ที่กำหนดเอง คุณอาจต้องระบุผู้ใช้ที่ลงชื่อเข้าใช้อยู่ในเซิร์ฟเวอร์นั้น ทั้งนี้เพื่อความปลอดภัย หลังจากลงชื่อเข้าใช้สำเร็จ ให้ส่งโทเค็นรหัสของผู้ใช้ไปยังเซิร์ฟเวอร์ของคุณโดยใช้ HTTPS จากนั้นตรวจสอบความถูกต้องและความน่าเชื่อถือของโทเค็นรหัสบนเซิร์ฟเวอร์ และเรียกข้อมูล uid จากโทเค็นนี้ คุณใช้ uid ที่ส่งด้วยวิธีนี้เพื่อระบุผู้ใช้ที่ลงชื่อเข้าใช้อยู่ในเซิร์ฟเวอร์ได้อย่างปลอดภัย

ก่อนเริ่มต้น

หากต้องการยืนยันโทเค็นรหัสด้วย Firebase Admin SDK คุณต้องมีบัญชีบริการ โปรดทำตามวิธีการตั้งค่า Admin SDK เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเริ่มต้นใช้งาน Admin SDK ด้วยบัญชีบริการ

เรียกโทเค็นรหัสในไคลเอ็นต์

เมื่อผู้ใช้หรืออุปกรณ์ลงชื่อเข้าใช้สำเร็จ Firebase จะสร้างโทเค็นรหัสที่สอดคล้องกันที่ระบุผู้ใช้หรืออุปกรณ์ได้อย่างไม่ซ้ำกันและมอบสิทธิ์เข้าถึงทรัพยากรหลายรายการ เช่น ฐานข้อมูลเรียลไทม์ของ Firebase และ Cloud Storage คุณสามารถนำโทเค็นรหัสนั้นมาใช้ซ้ำเพื่อระบุผู้ใช้หรืออุปกรณ์ในเซิร์ฟเวอร์แบ็กเอนด์ที่กำหนดเอง หากต้องการดึงข้อมูลโทเค็นรหัสจากไคลเอ็นต์ ให้ตรวจสอบว่าผู้ใช้ลงชื่อเข้าใช้แล้ว รับโทเค็นรหัสจากผู้ใช้ที่ลงชื่อเข้าใช้ โดยทำดังนี้

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

เมื่อมีโทเค็นรหัสแล้ว คุณสามารถส่ง JWT นั้นไปยังแบ็กเอนด์และตรวจสอบความถูกต้องของโดยใช้ Firebase Admin SDK หรือใช้ไลบรารี JWT ของบุคคลที่สามหากเซิร์ฟเวอร์ของคุณเขียนด้วยภาษาที่ Firebase ไม่รองรับโดยค่าเริ่มต้น

ยืนยันโทเค็นรหัสโดยใช้ Firebase Admin SDK

Firebase Admin SDK มีเมธอดในตัวสำหรับการยืนยันและถอดรหัสโทเค็นรหัส หากโทเค็นรหัสที่ระบุมีรูปแบบที่ถูกต้อง ไม่หมดอายุ และมีลายเซ็นอย่างถูกต้อง เมธอดจะแสดงโทเค็นรหัสที่ถอดรหัสแล้ว คุณสามารถคว้า uid ของผู้ใช้หรืออุปกรณ์จากโทเค็นที่ถอดรหัสแล้ว

ทำตามวิธีการตั้งค่า Admin SDK เพื่อเริ่มต้น Admin SDK ด้วยบัญชีบริการ จากนั้นใช้เมธอด verifyIdToken() เพื่อยืนยันโทเค็นรหัส

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;

การยืนยันโทเค็นรหัสต้องใช้รหัสโปรเจ็กต์ Firebase Admin SDK จะพยายามรับรหัสโปรเจ็กต์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้

  • หากเริ่มต้น SDK ด้วยตัวเลือกแอป projectId ที่ชัดเจน SDK จะใช้ค่าของตัวเลือกนั้น
  • หากเริ่มต้น SDK ด้วยข้อมูลเข้าสู่ระบบของบัญชีบริการ SDK จะใช้ช่อง project_id ของออบเจ็กต์ JSON ของบัญชีบริการ
  • หากตั้งค่าตัวแปรสภาพแวดล้อม GOOGLE_CLOUD_PROJECT แล้ว SDK จะใช้ค่าเป็นรหัสโปรเจ็กต์ ตัวแปรสภาพแวดล้อมนี้พร้อมใช้งานสำหรับโค้ดที่ทำงานบนโครงสร้างพื้นฐานของ Google เช่น App Engine และ Compute Engine

ยืนยันโทเค็นรหัสโดยใช้ไลบรารี JWT ของบุคคลที่สาม

หากแบ็กเอนด์เป็นภาษาที่ Firebase Admin SDK ไม่รองรับ คุณจะยังยืนยันโทเค็นรหัสได้ ก่อนอื่น ให้หาไลบรารี JWT ของบุคคลที่สามสำหรับภาษาของคุณ จากนั้นยืนยันส่วนหัว เพย์โหลด และลายเซ็นของโทเค็นรหัส

ตรวจสอบว่าส่วนหัวของโทเค็นรหัสสอดคล้องกับข้อจำกัดต่อไปนี้

การอ้างสิทธิ์ส่วนหัวของโทเค็นรหัส
alg อัลกอริทึม "RS256"
kid รหัสคีย์ ต้องตรงกับคีย์สาธารณะที่ระบุไว้ใน https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

ยืนยันว่าเพย์โหลดของโทเค็นรหัสเป็นไปตามข้อจำกัดต่อไปนี้

การอ้างสิทธิ์เพย์โหลดโทเค็นรหัส
exp เวลาหมดอายุ ต้องเป็นวันที่ในอนาคต เวลาจะวัดในหน่วยวินาทีนับตั้งแต่ UNIX Epoch
iat เวลาที่ออก ต้องเป็นวันที่ในอดีต เวลาจะวัดในหน่วยวินาทีนับตั้งแต่ UNIX Epoch
aud กลุ่มเป้าหมาย ต้องเป็นรหัสโปรเจ็กต์ Firebase ซึ่งเป็นตัวระบุที่ไม่ซ้ำกันสำหรับโปรเจ็กต์ Firebase ของคุณ ซึ่งดูได้ใน URL ของคอนโซลโปรเจ็กต์นั้น
iss ผู้ออก ต้องเป็น "https://securetoken.google.com/<projectId>" โดยที่ <projectId> คือรหัสโปรเจ็กต์เดียวกันกับที่ใช้สำหรับ aud ด้านบน
sub เรื่อง ต้องเป็นสตริงที่ไม่ว่างเปล่าและต้องเป็น uid ของผู้ใช้หรืออุปกรณ์
auth_time เวลาในการตรวจสอบสิทธิ์ ต้องเป็นวันที่ในอดีต เวลาที่ผู้ใช้ตรวจสอบสิทธิ์

สุดท้าย ให้ตรวจสอบว่าโทเค็นรหัสมีการลงชื่อโดยคีย์ส่วนตัวที่ตรงกับการอ้างสิทธิ์ kid ของโทเค็น ดึงคีย์สาธารณะจาก https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com และใช้ไลบรารี JWT เพื่อยืนยันลายเซ็น ใช้ค่า max-age ในส่วนหัว Cache-Control ของการตอบกลับจากปลายทางนั้นเพื่อให้ทราบเวลาที่จะรีเฟรชคีย์สาธารณะ

หากการยืนยันทั้งหมดข้างต้นประสบความสำเร็จ คุณจะใช้หัวเรื่อง (sub) ของโทเค็นรหัสเป็น uid ของผู้ใช้หรืออุปกรณ์ที่เกี่ยวข้องได้