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