สร้างโทเค็นที่กำหนดเอง

Firebase ช่วยให้คุณควบคุมการตรวจสอบสิทธิ์ได้อย่างสมบูรณ์โดยให้คุณตรวจสอบสิทธิ์ผู้ใช้หรืออุปกรณ์โดยใช้โทเค็นเว็บ JSON (JWT) ที่ปลอดภัย คุณสร้าง โทเค็นเหล่านี้บนเซิร์ฟเวอร์ แล้วส่งกลับไปยังอุปกรณ์ไคลเอ็นต์ จากนั้นใช้ เพื่อตรวจสอบสิทธิ์ผ่านทางเมธอด signInWithCustomToken()

โดยคุณต้องสร้างปลายทางเซิร์ฟเวอร์ที่ยอมรับข้อมูลเข้าสู่ระบบ เช่น ชื่อผู้ใช้และรหัสผ่าน และหากข้อมูลเข้าสู่ระบบถูกต้อง ให้แสดงผล JWT ที่กําหนดเอง JWT ที่กำหนดเองที่แสดงผลจากเซิร์ฟเวอร์ของคุณสามารถ จะใช้โดยอุปกรณ์ไคลเอ็นต์เพื่อตรวจสอบสิทธิ์กับ Firebase (iOS+, Android, เว็บ) เมื่อตรวจสอบสิทธิ์แล้ว ระบบจะใช้ข้อมูลประจำตัวนี้เมื่อเข้าถึงบริการอื่นๆ ของ Firebase เช่น Firebase Realtime Database และ Cloud Storage นอกจากนี้ เนื้อหาของ JWT จะ ที่มีอยู่ในออบเจ็กต์ auth ใน Realtime Database Security Rules และ request.auth รายการใน Cloud Storage Security Rules

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

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

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

  • การใช้ไฟล์ JSON ของบัญชีบริการ -- ใช้วิธีการนี้ได้ในทุกสภาพแวดล้อม แต่คุณจะต้องแพ็กเกจไฟล์ JSON ของบัญชีบริการพร้อมกับโค้ด โปรดใช้ความระมัดระวังเป็นพิเศษเพื่อให้แน่ใจว่าไฟล์ JSON ของบัญชีบริการจะไม่แสดงต่อบุคคลภายนอก
  • การอนุญาตให้ Admin SDK ค้นหาบัญชีบริการ -- วิธีการนี้ใช้ได้ในสภาพแวดล้อมที่ Google จัดการ เช่น Google Cloud Functions และ App Engine คุณอาจต้องกำหนดค่าสิทธิ์เพิ่มเติมบางอย่างผ่านคอนโซล Google Cloud
  • การใช้รหัสบัญชีบริการ -- เมื่อใช้ในสภาพแวดล้อมที่ Google จัดการ วิธีการนี้จะลงนามในโทเค็นโดยใช้คีย์ของบัญชีบริการที่ระบุ แต่จะใช้เว็บเซอร์วิสระยะไกล และคุณอาจต้องกำหนดค่าสิทธิ์เพิ่มเติมสำหรับบัญชีบริการนี้ผ่านคอนโซล Google Cloud

การใช้ไฟล์ JSON ของบัญชีบริการ

ไฟล์ JSON ของบัญชีบริการมีข้อมูลทั้งหมดที่เกี่ยวข้องกับบัญชีบริการ (รวมถึงคีย์ส่วนตัว RSA) สามารถดาวน์โหลดได้จาก คอนโซล Firebase ทำตามวิธีการตั้งค่า Admin SDK เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเริ่มต้น Admin SDK ด้วยไฟล์ JSON ของบัญชีบริการ

วิธีการเริ่มต้นนี้เหมาะสำหรับการติดตั้งใช้งาน Admin SDK หลากหลายรูปแบบ นอกจากนี้ ยังช่วยให้ Admin SDK สร้างและลงนามโทเค็นที่กำหนดเองได้ด้วย ในเครื่อง โดยไม่ต้องเรียก API จากระยะไกล ข้อเสียหลักของการดำเนินการนี้ วิธีการคือคุณต้องสร้างแพ็กเกจไฟล์ JSON ของบัญชีบริการ พร้อมกับรหัสของคุณ นอกจากนี้ โปรดทราบว่าคีย์ส่วนตัวในไฟล์ JSON ของบัญชีบริการเป็นข้อมูลที่ละเอียดอ่อน และต้องระมัดระวังเป็นพิเศษเพื่อเก็บรักษาไว้เป็นความลับ กล่าวโดยละเอียดคือ โปรดอย่าเพิ่มไฟล์ JSON ของบัญชีบริการลงในระบบควบคุมเวอร์ชันแบบสาธารณะ

การให้ Admin SDK ค้นพบบัญชีบริการ

หากมีการทําให้โค้ดใช้งานได้ในสภาพแวดล้อมที่ Google จัดการ Admin SDK จะพยายามค้นหาวิธีลงนามโทเค็นที่กําหนดเองโดยอัตโนมัติ ดังนี้

  • หากมีการทำให้โค้ดใช้งานได้ในสภาพแวดล้อมมาตรฐานของ App Engine สำหรับ Java, Python หรือ Go, Admin SDK สามารถใช้ บริการ App Identity ที่มีอยู่ในสภาพแวดล้อมดังกล่าวเพื่อลงนามโทเค็นที่กำหนดเอง บริการระบุตัวตนของแอปจะเซ็นชื่อข้อมูลโดยใช้บัญชีบริการที่ Google App Engine จัดสรรไว้ให้แอปของคุณ

  • หากมีการทําให้โค้ดใช้งานได้ในสภาพแวดล้อมที่มีการจัดการอื่นๆ (เช่น Google Cloud Functions, Google Compute Engine) Firebase Admin SDK จะค้นหาสตริงรหัสบัญชีบริการจากเซิร์ฟเวอร์ข้อมูลเมตาในเครื่องโดยอัตโนมัติ จากนั้นระบบจะใช้รหัสบัญชีบริการที่ค้นพบร่วมกับบริการ IAM เพื่อลงนามในโทเค็นจากระยะไกล

หากต้องการใช้วิธีการลงนามเหล่านี้ ให้เริ่มต้น SDK ด้วย Google ข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชันและไม่ระบุสตริงรหัสบัญชีบริการ

Node.js

initializeApp();

Java

FirebaseApp.initializeApp();

Python

default_app = firebase_admin.initialize_app()

Go

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create();

หากต้องการทดสอบโค้ดเดียวกันในเครื่อง ให้ดาวน์โหลดไฟล์ JSON ของบัญชีบริการและตั้งค่าตัวแปรสภาพแวดล้อม GOOGLE_APPLICATION_CREDENTIALS ให้ชี้ไปยังไฟล์ดังกล่าว

หาก Firebase Admin SDK ต้องค้นหาสตริงรหัสบัญชีบริการ การดำเนินการนี้จะดำเนินการเมื่อโค้ดของคุณสร้างโทเค็นที่กำหนดเองเป็นครั้งแรก ผลลัพธ์จะได้รับการแคชและนำมาใช้ซ้ำสำหรับการดำเนินการลงนามโทเค็นครั้งต่อๆ ไป รหัสบัญชีบริการที่ค้นพบโดยอัตโนมัติมักจะเป็นหนึ่งในบริการเริ่มต้น บัญชีจาก Google Cloud:

เช่นเดียวกับรหัสบัญชีบริการที่ระบุไว้อย่างชัดเจน รหัสบัญชีบริการที่ค้นพบโดยอัตโนมัติต้องมีสิทธิ์ iam.serviceAccounts.signBlob เพื่อให้การสร้างโทเค็นที่กำหนดเองทำงานได้ คุณอาจต้องใช้ส่วน IAM และผู้ดูแลระบบของคอนโซล Google Cloud เพื่อมอบสิทธิ์ที่จำเป็นแก่บัญชีบริการเริ่มต้น โปรดดูรายละเอียดเพิ่มเติมที่ส่วนการแก้ปัญหาด้านล่าง

การใช้รหัสบัญชีบริการ

คุณสามารถระบุรหัสบัญชีบริการที่จะใช้คีย์เพื่อลงนามในโทเค็นเมื่อทํางานในสภาพแวดล้อมที่ Google จัดการ เพื่อให้แอปพลิเคชันส่วนต่างๆ ทำงานสอดคล้องกัน วิธีนี้ช่วยให้นโยบาย IAM ง่ายขึ้นและปลอดภัยยิ่งขึ้น รวมถึงไม่ต้องใส่ไฟล์ JSON ของบัญชีบริการไว้ในโค้ด

รหัสบัญชีบริการจะอยู่ใน คอนโซล Google Cloud, หรือในช่อง client_email ของไฟล์ JSON ของบัญชีบริการที่ดาวน์โหลดมา รหัสบัญชีบริการคืออีเมลในรูปแบบต่อไปนี้ <client-id>@<project-id>.iam.gserviceaccount.com ซึ่งจะระบุบัญชีบริการในโปรเจ็กต์ Firebase และ Google Cloud โดยไม่ซ้ำกัน

หากต้องการสร้างโทเค็นที่กำหนดเองโดยใช้รหัสบัญชีบริการแยกต่างหาก ให้เริ่มต้น SDK ดังที่แสดงด้านล่าง

Node.js

initializeApp({
  serviceAccountId: 'my-client-id@my-project-id.iam.gserviceaccount.com',
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setServiceAccountId("my-client-id@my-project-id.iam.gserviceaccount.com")
    .build();
FirebaseApp.initializeApp(options);

Python

options = {
    'serviceAccountId': 'my-client-id@my-project-id.iam.gserviceaccount.com',
}
firebase_admin.initialize_app(options=options)

Go

conf := &firebase.Config{
	ServiceAccountID: "my-client-id@my-project-id.iam.gserviceaccount.com",
}
app, err := firebase.NewApp(context.Background(), conf)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
    ServiceAccountId = "my-client-id@my-project-id.iam.gserviceaccount.com",
});

รหัสบัญชีบริการไม่ใช่ข้อมูลที่ละเอียดอ่อน ดังนั้นจึงเป็นการเปิดเผยข้อมูล อย่างไรก็ตาม หากต้องการลงนามโทเค็นที่กำหนดเองด้วยบัญชีบริการที่ระบุ Firebase Admin SDK จะต้องเรียกใช้บริการระยะไกล นอกจากนี้ คุณต้องตรวจสอบว่าบัญชีบริการที่ Admin SDK ใช้เรียกใช้การเรียกนี้ ซึ่งมักจะเป็น {project-name}@appspot.gserviceaccount.com มีiam.serviceAccounts.signBlobสิทธิ์ ดูรายละเอียดเพิ่มเติมได้ในส่วนการแก้ปัญหาด้านล่าง

สร้างโทเค็นที่กำหนดเองโดยใช้ Firebase Admin SDK

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

Node.js

const uid = 'some-uid';

getAuth()
  .createCustomToken(uid)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  });

Java

String uid = "some-uid";

String customToken = FirebaseAuth.getInstance().createCustomToken(uid);
// Send token back to client

Python

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

Go

client, err := app.Auth(context.Background())
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}

token, err := client.CustomToken(ctx, "some-uid")
if err != nil {
	log.Fatalf("error minting custom token: %v\n", err)
}

log.Printf("Got custom token: %v\n", token)

C#

var uid = "some-uid";

string customToken = await FirebaseAuth.DefaultInstance.CreateCustomTokenAsync(uid);
// Send token back to client

นอกจากนี้ คุณยังระบุการอ้างสิทธิ์เพิ่มเติมที่จะรวมไว้ในโทเค็นที่กําหนดเองได้ด้วย ตัวอย่างเช่น ด้านล่างนี้มีการเพิ่มช่อง premiumAccount ลงในโทเค็นที่กำหนดเอง ซึ่งจะอยู่ในออบเจ็กต์ auth / request.auth ในกฎการรักษาความปลอดภัย

Node.js

const userId = 'some-uid';
const additionalClaims = {
  premiumAccount: true,
};

getAuth()
  .createCustomToken(userId, additionalClaims)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  });

Java

String uid = "some-uid";
Map<String, Object> additionalClaims = new HashMap<String, Object>();
additionalClaims.put("premiumAccount", true);

String customToken = FirebaseAuth.getInstance()
    .createCustomToken(uid, additionalClaims);
// Send token back to client

Python

uid = 'some-uid'
additional_claims = {
    'premiumAccount': True
}

custom_token = auth.create_custom_token(uid, additional_claims)

Go

client, err := app.Auth(context.Background())
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}

claims := map[string]interface{}{
	"premiumAccount": true,
}

token, err := client.CustomTokenWithClaims(ctx, "some-uid", claims)
if err != nil {
	log.Fatalf("error minting custom token: %v\n", err)
}

log.Printf("Got custom token: %v\n", token)

C#

var uid = "some-uid";
var additionalClaims = new Dictionary<string, object>()
{
    { "premiumAccount", true },
};

string customToken = await FirebaseAuth.DefaultInstance
    .CreateCustomTokenAsync(uid, additionalClaims);
// Send token back to client

ชื่อโทเค็นที่กำหนดเองที่สงวนไว้

ลงชื่อเข้าใช้โดยใช้โทเค็นที่กำหนดเองในไคลเอ็นต์

หลังจากสร้างโทเค็นที่กำหนดเองแล้ว คุณควรส่งโทเค็นดังกล่าวไปยังแอปไคลเอ็นต์ โดยแอปไคลเอ็นต์จะตรวจสอบสิทธิ์ด้วยโทเค็นที่กำหนดเองโดยการเรียกใช้signInWithCustomToken()

iOS ขึ้นไป

Objective-C
[[FIRAuth auth] signInWithCustomToken:customToken
                           completion:^(FIRAuthDataResult * _Nullable authResult,
                                        NSError * _Nullable error) {
  // ...
}];
Swift
Auth.auth().signIn(withCustomToken: customToken ?? "") { user, error in
  // ...
}

Android

mAuth.signInWithCustomToken(mCustomToken)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // Sign in success, update UI with the signed-in user's information
                    Log.d(TAG, "signInWithCustomToken:success");
                    FirebaseUser user = mAuth.getCurrentUser();
                    updateUI(user);
                } else {
                    // If sign in fails, display a message to the user.
                    Log.w(TAG, "signInWithCustomToken:failure", task.getException());
                    Toast.makeText(CustomAuthActivity.this, "Authentication failed.",
                            Toast.LENGTH_SHORT).show();
                    updateUI(null);
                }
            }
        });

Unity

auth.SignInWithCustomTokenAsync(custom_token).ContinueWith(task => {
  if (task.IsCanceled) {
    Debug.LogError("SignInWithCustomTokenAsync was canceled.");
    return;
  }
  if (task.IsFaulted) {
    Debug.LogError("SignInWithCustomTokenAsync encountered an error: " + task.Exception);
    return;
  }

  Firebase.Auth.AuthResult result = task.Result;
  Debug.LogFormat("User signed in successfully: {0} ({1})",
      result.User.DisplayName, result.User.UserId);
});

C++

firebase::Future<firebase::auth::AuthResult> result =
    auth->SignInWithCustomToken(custom_token);

Web

firebase.auth().signInWithCustomToken(token)
  .then((userCredential) => {
    // Signed in
    var user = userCredential.user;
    // ...
  })
  .catch((error) => {
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

Web

import { getAuth, signInWithCustomToken } from "firebase/auth";

const auth = getAuth();
signInWithCustomToken(auth, token)
  .then((userCredential) => {
    // Signed in
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
    // ...
  });

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

ระบบจะป้อนข้อมูล uid ของผู้ใช้ลงในออบเจ็กต์ auth ใน Realtime Database Security Rules และออบเจ็กต์ request.auth ใน Cloud Storage Security Rules ในลักษณะเดียวกับวิธีการลงชื่อเข้าใช้อื่นๆ (เช่น signInWithEmailAndPassword() และ signInWithCredential()) ในกรณีนี้ uid จะเป็นค่าที่คุณระบุไว้เมื่อสร้างโทเค็นที่กําหนดเอง

กฎฐานข้อมูล

{
  "rules": {
    "adminContent": {
      ".read": "auth.uid === 'some-uid'"
    }
  }
}

กฎพื้นที่เก็บข้อมูล

service firebase.storage {
  match /b/<your-firebase-storage-bucket>/o {
    match /adminContent/{filename} {
      allow read, write: if request.auth != null && request.auth.uid == "some-uid";
    }
  }
}

หากโทเค็นที่กำหนดเองมีการอ้างสิทธิ์เพิ่มเติม จะสามารถอ้างอิงได้จาก auth.token (Firebase Realtime Database) หรือ request.auth.token (Cloud Storage) ในกฎของคุณ:

กฎฐานข้อมูล

{
  "rules": {
    "premiumContent": {
      ".read": "auth.token.premiumAccount === true"
    }
  }
}

กฎพื้นที่เก็บข้อมูล

service firebase.storage {
  match /b/<your-firebase-storage-bucket>/o {
    match /premiumContent/{filename} {
      allow read, write: if request.auth.token.premiumAccount == true;
    }
  }
}

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

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

การอ้างสิทธิ์โทเค็นที่กำหนดเอง
alg อัลกอริทึม "RS256"
iss ผู้ออก อีเมลบัญชีบริการของโปรเจ็กต์
sub เรื่อง อีเมลบัญชีบริการของโปรเจ็กต์
aud กลุ่มเป้าหมาย "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat เวลาที่ออก เวลาปัจจุบันเป็นวินาทีนับตั้งแต่ Epoch ของ UNIX
exp เวลาหมดอายุ เวลาเป็นวินาทีนับตั้งแต่ UNIX Epoch ที่โทเค็นหมดอายุ ทั้งนี้ สามารถอยู่ห่างออกไปไม่เกิน 3,600 วินาที iat
หมายเหตุ: ตัวเลือกนี้จะควบคุมเฉพาะเวลาที่โทเค็นที่กำหนดเองจะหมดอายุเท่านั้น แต่เมื่อคุณลงชื่อเข้าใช้ signInWithCustomToken() พวกเขาจะยังคงลงชื่อเข้าใช้ อุปกรณ์จนกว่าเซสชันของผู้ใช้จะใช้งานไม่ได้ หรือผู้ใช้จะออกจากระบบ
uid ตัวระบุที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้ต้องเป็นสตริงที่มีความยาวระหว่าง 1-128 อักขระ (รวม 2 ตัวเลขนี้ด้วย) uid ที่สั้นลงจะมีประสิทธิภาพดีกว่า
claims (ไม่บังคับ) การอ้างสิทธิ์ที่กําหนดเองซึ่งไม่บังคับให้รวมไว้ในตัวแปรกฎความปลอดภัย auth / request.auth

ต่อไปนี้เป็นตัวอย่างการใช้งานวิธีสร้างโทเค็นที่กำหนดเองใน ภาษาต่างๆ ที่ Firebase Admin SDK ไม่รองรับ ได้แก่

PHP

กำลังใช้ php-jwt:

// Requires: composer require firebase/php-jwt
use Firebase\JWT\JWT;

// Get your service account's email address and private key from the JSON key file
$service_account_email = "abc-123@a-b-c-123.iam.gserviceaccount.com";
$private_key = "-----BEGIN PRIVATE KEY-----...";

function create_custom_token($uid, $is_premium_account) {
  global $service_account_email, $private_key;

  $now_seconds = time();
  $payload = array(
    "iss" => $service_account_email,
    "sub" => $service_account_email,
    "aud" => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
    "iat" => $now_seconds,
    "exp" => $now_seconds+(60*60),  // Maximum expiration time is one hour
    "uid" => $uid,
    "claims" => array(
      "premium_account" => $is_premium_account
    )
  );
  return JWT::encode($payload, $private_key, "RS256");
}

Ruby

กำลังใช้ ruby-jwt:

require "jwt"

# Get your service account's email address and private key from the JSON key file
$service_account_email = "service-account@my-project-abc123.iam.gserviceaccount.com"
$private_key = OpenSSL::PKey::RSA.new "-----BEGIN PRIVATE KEY-----\n..."

def create_custom_token(uid, is_premium_account)
  now_seconds = Time.now.to_i
  payload = {:iss => $service_account_email,
             :sub => $service_account_email,
             :aud => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
             :iat => now_seconds,
             :exp => now_seconds+(60*60), # Maximum expiration time is one hour
             :uid => uid,
             :claims => {:premium_account => is_premium_account}}
  JWT.encode payload, $private_key, "RS256"
end

หลังจากที่คุณสร้างโทเค็นที่กำหนดเองแล้ว ให้ส่งไปยังแอปไคลเอ็นต์เพื่อใช้ในการ ตรวจสอบสิทธิ์ด้วย Firebase แล้ว ดูตัวอย่างโค้ดด้านบนสำหรับวิธีการ

การแก้ปัญหา

ส่วนนี้จะอธิบายปัญหาที่พบได้ทั่วไปซึ่งนักพัฒนาแอปอาจพบ การสร้างโทเค็นที่กำหนดเอง รวมถึงวิธีแก้ไข

ไม่ได้เปิดใช้ IAM API

หากคุณระบุรหัสบัญชีบริการสำหรับการลงนามในโทเค็น คุณอาจได้รับข้อผิดพลาดที่คล้ายกับข้อความต่อไปนี้

Identity and Access Management (IAM) API has not been used in project
1234567890 before or it is disabled. Enable it by visiting
https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project=1234567890
then retry. If you enabled this API recently, wait a few minutes for the action
to propagate to our systems and retry.

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

บัญชีบริการไม่มีสิทธิ์ที่จำเป็น

หากบัญชีบริการที่ Firebase Admin SDK ทำงานอยู่ไม่มีสิทธิ์ iam.serviceAccounts.signBlob คุณอาจเห็นข้อความแสดงข้อผิดพลาดดังต่อไปนี้

Permission iam.serviceAccounts.signBlob is required to perform this operation
on service account projects/-/serviceAccounts/{your-service-account-id}.

วิธีที่ง่ายที่สุดในการแก้ปัญหานี้คือให้บทบาท IAM "ผู้สร้างโทเค็นบัญชีบริการ" แก่บัญชีบริการที่เป็นปัญหา ซึ่งโดยปกติแล้ว{project-name}@appspot.gserviceaccount.com

  1. เปิดหน้า IAM และผู้ดูแลระบบในคอนโซล Google Cloud
  2. เลือกโปรเจ็กต์แล้วคลิก "ต่อไป"
  3. คลิกไอคอนแก้ไขที่ตรงกับบัญชีบริการที่คุณต้องการอัปเดต
  4. คลิก "เพิ่มบทบาทอื่น"
  5. พิมพ์ "Service Account Token Creator" ลงในตัวกรองการค้นหา แล้วเลือก จากผลการค้นหา
  6. คลิก "บันทึก" เพื่อยืนยันการให้สิทธิ์บทบาท

โปรดดูรายละเอียดเพิ่มเติมเกี่ยวกับกระบวนการนี้ในเอกสารประกอบ IAM หรือดูวิธีอัปเดตบทบาทโดยใช้เครื่องมือบรรทัดคำสั่ง gcloud

ระบุบัญชีบริการไม่สำเร็จ

หากได้รับข้อความแสดงข้อผิดพลาดที่คล้ายกับข้อความต่อไปนี้ Firebase Admin SDK ยังไม่ได้เริ่มกำหนดค่าอย่างถูกต้อง

Failed to determine service account ID. Initialize the SDK with service account
credentials or specify a service account ID with iam.serviceAccounts.signBlob
permission.

หากคุณใช้ SDK เพื่อค้นหารหัสบัญชีบริการโดยอัตโนมัติ ให้ตรวจสอบว่าได้ติดตั้งใช้งานโค้ดในสภาพแวดล้อม Google ที่มีการจัดการซึ่งมีเซิร์ฟเวอร์ข้อมูลเมตา ไม่เช่นนั้น ก็อย่าลืมระบุไฟล์ JSON ของบัญชีบริการหรือรหัสบัญชีบริการ ตั้งแต่การเริ่มต้น SDK