تمنحك 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
يمكنك إنشاء رمز مميّز مخصّص باستخدام حزمة تطوير البرامج (SDK) لمشرف Firebase، أو يمكنك استخدام مكتبة JWT تابعة لجهة خارجية إذا كان الخادم مكتوبًا لغة لا يتوافق معها Firebase في الأصل.
قبل البدء
الرموز المميّزة المخصّصة هي تنسيقات JWT موقَّعة يكون المفتاح الخاص المستخدَم في التوقيع تابعًا لحساب خدمة على Google. تتوفّر عدة طرق لتحديد خدمة Google. حساب يجب أن تستخدمه حزمة تطوير البرامج (SDK) لمشرف Firebase للتوقيع الرموز المميزة:
- استخدام ملف JSON لحساب الخدمة -- يمكن استخدام هذه الطريقة في ولكنه يتطلب منك تجميع ملف JSON لحساب الخدمة إلى جانب التعليمة البرمجية. يجب توخّي الحذر بشكل خاص لضمان عدم تعريضملف JSON لحساب الخدمة لجهات خارجية.
- السماح لحزمة Admin SDK باكتشاف حساب خدمة -- يمكن استخدام هذه الطريقة في البيئات التي تديرها Google، مثل Google Cloud Functions وApp Engine. قد تحتاج إلى ضبط بعض الأذونات الإضافية من خلال وحدة تحكّم Google Cloud.
- استخدام رقم تعريف حساب الخدمة -- وعند استخدامها في بيئة تديرها Google، ستوقِّع هذه الطريقة الرموز المميزة باستخدام مفتاح حساب الخدمة المحدّد. ومع ذلك، فإنه يستخدم خدمة ويب بعيدة، وقد تضطر إلى تهيئة أذونات إضافية لحساب الخدمة هذا عبر وحدة تحكّم "Google Cloud"
استخدام ملف JSON لحساب الخدمة
تحتوي ملفات JSON لحساب الخدمة على جميع المعلومات المقابلة للخدمة (بما في ذلك المفتاح الخاص لـ RSA). ويمكن تنزيلها من وحدة تحكّم Firebase. اتّبع إعداد SDK للمشرف تعليمات لمزيد من المعلومات حول كيفية إعداد حزمة تطوير البرامج (SDK) الخاصة بالمشرف باستخدام ملف JSON لحساب الخدمة
تناسب طريقة الإعداد هذه مجموعة كبيرة من حزمة SDK للمشرف وعمليات النشر. كما يمكّن SDK للمشرف من إنشاء رموز مميزة مخصصة وتوقيعها محليًا، بدون إجراء أي طلبات بيانات من واجهة برمجة التطبيقات عن بُعد. يتمثل العيب الرئيسي في هذا الأسلوب في أنّه يتطلّب منك حزم ملف JSON لحساب الخدمة مع الرمز البرمجي. يُرجى العلم أيضًا أنّ المفتاح الخاص في ملف JSON لحساب الخدمة هو معلومات حسّاسة، ويجب توخي الحذر الشديد للحفاظ على سرّيته. وعلى وجه التحديد، يجب الامتناع عن إضافة ملفات JSON لحساب الخدمة إلى نظام التحكّم في الإصدارات العلني.
السماح لحزمة تطوير البرامج (SDK) للمشرف باكتشاف حساب خدمة
في حال نشر الرمز في بيئة تديرها Google، يمكن لحزمة Admin SDKمحاولة اكتشاف وسيلة لتوقيع الرموز المميّزة المخصّصة تلقائيًا:
إذا تم نشر الرمز في بيئة App Engine العادية Java أو Python أو Go، يمكن لحزمة تطوير البرامج (SDK) للمشرف استخدام خدمة App Identity الموجودة في تلك البيئة لتوقيع الرموز المميزة المخصصة. تُوقّع خدمة "هوية التطبيق" البيانات باستخدام حساب خدمة تم توفيره لتطبيقك من خلال "محرّك التطبيقات من Google".
في حال نشر الرمز في بيئة مُدارة أخرى (مثل Google Cloud Functions وGoogle Compute Engine)، يمكن لحزمة تطوير البرامج (SDK) الخاصة بمشرف Firebase اكتشاف سلسلة رقم تعريف حساب الخدمة تلقائيًا من خادم البيانات الوصفية المحلي. بعد ذلك، يتم استخدام معرّف حساب الخدمة المكتشف مع خدمة IAM لتوقيع الرموز المميّزة عن بُعد.
للاستفادة من طُرق التوقيع هذه، عليك إعداد حزمة تطوير البرامج (SDK) بالتعاون مع Google. بيانات الاعتماد التلقائية للتطبيق وعدم تحديد سلسلة لرقم تعريف حساب الخدمة:
Node.js
initializeApp();
جافا
FirebaseApp.initializeApp();
Python
default_app = firebase_admin.initialize_app()
انتقال
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
) للإشارة إليه
إذا احتاجت حزمة تطوير البرامج (SDK) لمشرف Firebase إلى اكتشاف سلسلة رقم تعريف حساب الخدمة، ولذلك عندما ينشئ الرمز رمزًا مميزًا مخصصًا لأول مرة. ويتم تخزين النتيجة مؤقتًا وإعادة استخدامها في العمليات اللاحقة لتوقيع الرمز المميّز. عادةً ما يكون معرّف حساب الخدمة الذي تم اكتشافه تلقائيًا أحد حسابات الخدمة التلقائية التي يوفّرها Google Cloud:
وكما هو الحال مع معرّفات حسابات الخدمة المحددة بوضوح، يتم اكتشاف خدمة
يجب أن تتضمّن أرقام تعريف الحسابات إذن "iam.serviceAccounts.signBlob
" من أجل
لإنشاء رمز مخصص للعمل. قد تضطر إلى استخدام
قسم إدارة الهوية وإمكانية الوصول والمشرف
في وحدة تحكّم Google Cloud لمنح حسابات الخدمة التلقائية
الأذونات اللازمة. لمعرفة مزيد من التفاصيل، يُرجى الاطّلاع على قسم تحديد المشاكل وحلّها أدناه.
استخدام رقم تعريف حساب الخدمة
للحفاظ على الاتساق بين الأجزاء المختلفة من تطبيقك، يمكنك تحديد رقم تعريف حساب الخدمة الذي سيتم استخدام مفاتيحه لتوقيع الرموز المميّزة عند التشغيل في بيئة تديرها Google. يمكن أن يجعل ذلك سياسات إدارة الهوية وإمكانية الوصول أكثر بساطة وأمانًا، ويتجنّب الحاجة إلى تضمين ملف JSON لحساب الخدمة في الرمز البرمجي.
يمكن العثور على معرّف حساب الخدمة فيconsole
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',
});
جافا
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)
انتقال
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 خدمة عن بُعد.
علاوة على ذلك، يجب عليك أيضًا التأكد من أن حساب الخدمة الذي يتضمنه SDK للمشرف
تستخدمه لإجراء هذه المكالمة
—عادةً {project-name}@appspot.gserviceaccount.com
—
يتضمّن iam.serviceAccounts.signBlob
الإذن:
راجِع قسم تحديد المشاكل وحلّها أدناه لمعرفة المزيد من التفاصيل.
إنشاء رموز مخصّصة باستخدام حزمة تطوير البرامج (SDK) لمشرف Firebase
تحتوي حزمة تطوير البرامج (SDK) لمشرف Firebase على طريقة مدمجة لإنشاء رموز مميزة مخصصة. في
الحد الأدنى، فأنت بحاجة إلى تقديم uid
، والتي يمكن أن تكون أي سلسلة ولكن يجب
تحديد المستخدم أو الجهاز الذي تقوم بالمصادقة عليه بشكل فريد. تنتهي صلاحية هذه الرموز المميّزة
بعد ساعة واحدة.
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);
});
جافا
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)
انتقال
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);
});
جافا
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)
انتقال
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 الرسمي SDK، فلا يزال بإمكانك إنشاء رموز مميزة مخصصة يدويًا. أولاً، ابحث عن مكتبة JWT تابعة لجهة خارجية بلغتك. بعد ذلك، استخدم من مكتبة JWT لإنشاء JWT بما في ذلك المطالبات التالية:
مطالبات الرموز المميّزة المخصّصة | ||
---|---|---|
alg |
خوارزمية | "RS256" |
iss |
جهة الإصدار | عنوان البريد الإلكتروني لحساب الخدمة الخاص بمشروعك |
sub |
الموضوع | عنوان البريد الإلكتروني لحساب الخدمة الخاص بمشروعك |
aud |
الجمهور | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
وقت الإصدار | الوقت الحالي بالثواني منذ حقبة UNIX |
exp |
وقت انتهاء الصلاحية |
الوقت بالثواني منذ حقبة UNIX والذي تنتهي فيه صلاحية الرمز المميّز. يمكن أن يليه
المحتوى بعد 3600 ثانية كحد أقصى من iat .
ملاحظة: لا يتحكّم هذا الخيار إلا في الوقت الذي يصبح فيه الرمز المميّز المخصّص نفسه تنتهي صلاحيته. ولكن بعد تسجيل دخول مستخدم باستخدام signInWithCustomToken() ، سيظل مسجِّلاً الدخول إلى
الجهاز إلى أن تصبح جلسته غير صالحة أو يسجّل المستخدم الخروج.
|
uid |
يجب أن يكون المعرّف الفريد للمستخدم المسجّل دخوله عبارة عن سلسلة بين
من 1 إلى 128 حرفًا شاملة. تحقّق uid الأقصر أداءً
أفضل.
|
|
claims (اختياري) |
مطالبات مخصّصة اختيارية لتضمينها في متغيّرات auth /
request.auth في قواعد الأمان
|
في ما يلي بعض الأمثلة على عمليات التنفيذ لكيفية إنشاء رموز مخصّصة في مجموعة متنوعة من اللغات التي لا تتوافق مع حزمة SDK للمشرف في Firebase:
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)
في حال تحديد رقم تعريف لحساب الخدمة لتوقيع الرموز المميّزة، قد تظهر لك رسالة خطأ مشابهة لما يلي:
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. افتح الرابط في رسالة الخطأ في متصفّح ويب، ثم انقر على الزر "تفعيل واجهة برمجة التطبيقات" لتفعيلها لمشروعك.
لا يملك حساب الخدمة الأذونات المطلوبة.
إذا لم يكن حساب الخدمة الذي يتم تشغيل حزمة 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}.
أسهل طريقة لحل هذه المشكلة هي منح "منشئ الرمز المميز لحساب الخدمة"
دور "إدارة الهوية وإمكانية الوصول" في حساب الخدمة المعنيّ، عادةً
{project-name}@appspot.gserviceaccount.com
:
- افتح إدارة الهوية وإمكانية الوصول والمشرف في وحدة تحكُّم Google Cloud.
- اختَر مشروعك وانقر على "متابعة".
- انقر على رمز التعديل المقابل لحساب الخدمة الذي تريد تعديله.
- انقر على "إضافة دور آخر".
- اكتب "Service Account Token Creator" (أداة إنشاء الرموز المميّزة لحساب الخدمة) في فلتر البحث، ثم اختَر هذه الأداة من النتائج.
- انقر على "حفظ" لتأكيد منح الدور.
يمكنك الرجوع إلى مستندات إدارة الهوية وإمكانية الوصول لمزيد من التفاصيل حول هذه العملية، أو التعرّف على كيفية تعديل الأدوار باستخدام أدوات سطر الأوامر gcloud.
تعذّر تحديد حساب الخدمة
إذا ظهرت لك رسالة خطأ مشابهة لما يلي، حزمة SDK لمشرف Firebase لم يتم إعدادها بشكل صحيح.
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).