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

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

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

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

ก่อนที่คุณจะเริ่ม

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

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

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

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

โหนด js

initializeApp();

ชวา

FirebaseApp.initializeApp();

หลาม

default_app = firebase_admin.initialize_app()

ไป

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

ค#

FirebaseApp.Create();

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

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

เช่นเดียวกับ ID บัญชีบริการที่ระบุอย่างชัดเจน ID บัญชีบริการที่ค้นพบอัตโนมัติจะต้องมีสิทธิ์ 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 ดังที่แสดงด้านล่าง:

โหนด js

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

ชวา

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

หลาม

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

ไป

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

ค#

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

โหนด js

const uid = 'some-uid';

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

ชวา

String uid = "some-uid";

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

หลาม

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

ไป

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)

ค#

var uid = "some-uid";

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

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

โหนด 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);
  });

ชวา

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

หลาม

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

custom_token = auth.create_custom_token(uid, additional_claims)

ไป

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)

ค#

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() :

ไอโอเอส+

วัตถุประสงค์-C
[[FIRAuth auth] signInWithCustomToken:customToken
                           completion:^(FIRAuthDataResult * _Nullable authResult,
                                        NSError * _Nullable error) {
  // ...
}];
สวิฟท์
Auth.auth().signIn(withCustomToken: customToken ?? "") { user, error in
  // ...
}

หุ่นยนต์

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

ความสามัคคี

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

ซี++

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

API เนมสเปซของเว็บ

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

API แบบโมดูลาร์ของเว็บ

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 ใน กฎการรักษาความปลอดภัยของฐานข้อมูลเรียลไทม์ ของคุณ และออบเจ็กต์ request.auth ใน กฎการรักษาความปลอดภัยของ Cloud Storage ของคุณจะถูกเติมด้วย 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 ออก ณ เวลา เวลาปัจจุบัน เป็นวินาทีนับตั้งแต่ยุค UNIX
exp เวลาหมดอายุ เวลาเป็นวินาทีนับตั้งแต่ยุค UNIX ซึ่งโทเค็นหมดอายุ โดยสามารถช้ากว่า iat ได้ สูงสุด 3600 วินาที
หมายเหตุ: สิ่งนี้จะควบคุมเฉพาะเวลาที่ โทเค็นแบบกำหนด เองหมดอายุเท่านั้น แต่เมื่อคุณลงชื่อเข้าใช้ผู้ใช้โดยใช้ signInWithCustomToken() พวกเขาจะยังคงลงชื่อเข้าใช้ในอุปกรณ์จนกว่าเซสชันจะใช้งานไม่ได้หรือผู้ใช้ออกจากระบบ
uid ตัวระบุเฉพาะของผู้ใช้ที่ลงชื่อเข้าใช้ต้องเป็นสตริงที่มีความยาวระหว่าง 1-128 อักขระ 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-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