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

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 ด้วยไฟล์ JSON ของบัญชีบริการในวิธีการตั้งค่า Admin SDK

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

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

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

  • หากโค้ดของคุณได้รับการติดตั้งใช้งานในApp Engineสภาพแวดล้อมมาตรฐานสำหรับ Java, Python หรือ Go แล้ว Admin SDK จะใช้บริการข้อมูลประจำตัวของแอป ที่มีอยู่ในสภาพแวดล้อมนั้นเพื่อลงชื่อโทเค็นที่กำหนดเองได้ บริการข้อมูลประจำตัวของแอป ลงนามข้อมูลโดยใช้บัญชีบริการที่ 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 ที่รวมอยู่ในโทเค็นที่กำหนดเอง หากไม่มีบัญชีดังกล่าวมาก่อน ระบบจะสร้างบันทึกสำหรับผู้ใช้รายนั้น

ในลักษณะเดียวกับวิธีการลงชื่อเข้าใช้อื่นๆ (เช่น signInWithEmailAndPassword() และ signInWithCredential()) ออบเจ็กต์ auth ใน Realtime Database Security Rules และ ออบเจ็กต์ request.auth ใน Cloud Storage Security Rules จะมีข้อมูล uid ของผู้ใช้ ในกรณีนี้ 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 Admin SDK อย่างเป็นทางการ คุณก็ยังสร้างโทเค็นที่กำหนดเองได้ด้วยตนเอง ก่อนอื่น ให้ค้นหาไลบรารี JWT ของบุคคลที่สามสำหรับภาษาของคุณ จากนั้นใช้ไลบรารี JWT นั้นเพื่อสร้าง JWT ซึ่งมีคำกล่าวอ้างต่อไปนี้

การอ้างสิทธิ์โทเค็นที่กำหนดเอง
alg อัลกอริทึม "RS256"
iss ผู้ออก อีเมลบัญชีบริการของโปรเจ็กต์
sub เรื่อง อีเมลบัญชีบริการของโปรเจ็กต์
aud กลุ่มเป้าหมาย "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat เวลาที่ออก เวลาปัจจุบันเป็นวินาทีนับตั้งแต่ Epoch ของ UNIX
exp เวลาหมดอายุ เวลาเป็นวินาทีนับตั้งแต่ Epoch ของ UNIX ที่โทเค็นหมดอายุ โดยช้ากว่าiat ได้สูงสุด 3,600 วินาที
หมายเหตุ: การตั้งค่านี้จะควบคุมเฉพาะเวลาที่โทเค็นที่กำหนดเองหมดอายุ เท่านั้น แต่เมื่อคุณลงชื่อเข้าใช้ผู้ใช้โดยใช้ 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" เพื่อเปิดใช้สำหรับโปรเจ็กต์ของคุณ

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

หากบัญชีบริการที่ 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