Firebase ช่วยให้คุณควบคุมการตรวจสอบสิทธิ์ได้อย่างสมบูรณ์โดยอนุญาตให้คุณตรวจสอบสิทธิ์ผู้ใช้หรืออุปกรณ์โดยใช้ JSON Web Token (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 ที่รวมอยู่ในโทเค็นที่กำหนดเอง หากบัญชีนั้นไม่มีอยู่ก่อนหน้านี้ ระบบจะสร้างระเบียนสำหรับผู้ใช้รายนั้น
ในลักษณะเดียวกับวิธีการลงชื่อเข้าใช้อื่นๆ (เช่น 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 |
เวลาที่ออก | เวลาปัจจุบันในหน่วยวินาทีตั้งแต่ Unix Epoch |
exp |
เวลาหมดอายุ |
เวลาที่โทเค็นหมดอายุในหน่วยวินาทีนับตั้งแต่ Unix Epoch
โดยต้องช้ากว่า iat ไม่เกิน 3,600 วินาที
หมายเหตุ: การดำเนินการนี้จะควบคุมเฉพาะเวลาที่โทเค็นที่กำหนดเองหมดอายุเท่านั้น แต่เมื่อคุณลงชื่อเข้าใช้ให้ผู้ใช้โดยใช้ 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
การใช้ 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 ผู้สร้างโทเค็นบัญชีบริการให้กับบัญชีบริการที่เหมาะสม บัญชีบริการเริ่มต้นที่ใช้จะขึ้นอยู่กับสภาพแวดล้อมและเวอร์ชันของ Cloud Functions ดังนี้
- Cloud Functions (รุ่นที่ 1): ใช้บัญชีบริการ App Engine เริ่มต้น
- Cloud Functions (รุ่นที่ 2): ใช้บัญชีบริการ Compute Engine เริ่มต้น
ในคอนโซล Google Cloud ให้ไปที่ IAM และผู้ดูแลระบบ
คลิกไอคอนแก้ไขที่ตรงกับบัญชีบริการที่ต้องการอัปเดต
คลิกเพิ่มบทบาทอื่น
พิมพ์
"Service Account Token Creator"ลงในตัวกรองการค้นหา แล้วเลือกจากผลการค้นหาคลิกบันทึกเพื่อยืนยันการให้บทบาท
ดูรายละเอียดเพิ่มเติมเกี่ยวกับกระบวนการนี้ได้ในเอกสารประกอบของ 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