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

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

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

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

ดึงข้อมูลโทเค็นรหัสในไคลเอ็นต์

เมื่อผู้ใช้หรืออุปกรณ์ลงชื่อเข้าใช้สำเร็จ Firebase จะสร้างโทเค็นรหัสที่เกี่ยวข้อง ซึ่งระบุผู้ใช้หรืออุปกรณ์นั้นๆ ได้อย่างไม่ซ้ำกัน และให้สิทธิ์เข้าถึงทรัพยากรต่างๆ เช่น Firebase Realtime Database และ 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
});

เมื่อมีโทเค็นรหัสแล้ว คุณสามารถส่ง JSON Web Token (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 เวลาหมดอายุ ต้องเป็นเวลาในอนาคต เวลาจะวัดเป็นวินาทีนับตั้งแต่วันที่ 1 มกราคม ค.ศ. 1970 (Epoch)
iat เวลาที่ออก ต้องเป็นเวลาในอดีต เวลาจะวัดเป็นวินาทีนับตั้งแต่วันที่ 1 มกราคม ค.ศ. 1970 (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 ของผู้ใช้หรืออุปกรณ์ที่เกี่ยวข้องได้