إنشاء الرموز المميّزة المخصّصة

تمنحك 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 الذي يجب أن تستخدمه حزمة Firebase Admin SDK لتوقيع علامات مخصّصة:

  • استخدام ملف JSON لحساب الخدمة: يمكن استخدام هذه الطريقة في أي بيئة، ولكنّها تتطلّب منك تجميع ملف JSON لحساب الخدمة مع الرمز البرمجي. يجب توخّي الحذر بشكل خاص لضمان عدم تعريضملف JSON لحساب الخدمة لجهات خارجية.
  • السماح لحزمة Admin SDK باكتشاف حساب خدمة -- يمكن استخدام هذه الطريقة في البيئات التي تديرها Google، مثل Google Cloud Functions وApp Engine. قد تحتاج إلى ضبط بعض الأذونات الإضافية من خلال وحدة تحكّم Google Cloud.
  • استخدام رقم تعريف حساب الخدمة: عند استخدام هذه الطريقة في بيئة تديرها Google، ستوقع هذه الطريقة الرموز المميّزة باستخدام مفتاح حساب الخدمة المحدّد. ومع ذلك، يستخدم هذا التطبيق خدمة ويب عن بُعد، وقد تحتاج إلى ضبط أذونات إضافية لهذا حساب الخدمة من خلال وحدة تحكّم Google Cloud.

استخدام ملف JSON لحساب الخدمة

تحتوي ملفات JSON لحسابات الخدمة على جميع المعلومات المرتبطة بحسابات الخدمة (بما في ذلك المفتاح الخاص بتنسيق RSA). ويمكن تنزيلها من وحدة تحكّم Firebase. اتّبِع تعليمات إعداد حزمة SDK للمشرف للحصول على مزيد من المعلومات حول كيفية تهيئة حزمة SDK للمشرف باستخدام ملف JSON لحساب الخدمة.

تُعدّ طريقة الإعداد هذه مناسبة لمجموعة كبيرة من عمليات بدء استخدام حزمة SDK المخصّصة للمشرفين. ويسمح هذا الإجراء أيضًا لحزمة Admin SDK بإنشاء الرموز المميّزة المخصّصة وتوقيعها على الجهاز، بدون إجراء أي طلبات بيانات من واجهة برمجة التطبيقات عن بُعد. يتمثل العيب الرئيسي في هذا الأسلوب في أنّه يتطلّب منك حزم ملف JSON لحساب الخدمة مع الرمز البرمجي. يُرجى العلم أيضًا أنّ المفتاح الخاص في ملف JSON لحساب الخدمة هو معلومات حسّاسة، ويجب توخي الحذر الشديد للحفاظ على سرّيته. وعلى وجه التحديد، يجب الامتناع عن إضافة ملفات JSON لحساب الخدمة إلى نظام التحكّم في الإصدارات العلني.

السماح لحزمة Admin SDK باكتشاف حساب خدمة

إذا تم نشر الرمز في بيئة تديرها Google، يمكن لحزمة Admin SDKمحاولة اكتشاف وسيلة لتوقيع الرموز المميّزة المخصّصة تلقائيًا:

  • إذا تم نشر الرمز في بيئة App Engine العادية لIDE IDE Java أو Python أو Go، يمكن أن تستخدم حزمة Admin SDK خدمة App Identity المتوفّرة في تلك البيئة لتوقيع الرموز المميّزة المخصّصة. توقع خدمة "هوية التطبيق" البيانات باستخدام حساب خدمة تم توفيره لتطبيقك من خلال "محرّك التطبيقات من Google".

  • في حال نشر الرمز في بيئة مُدارة أخرى (مثل Google Cloud Functions وGoogle Compute Engine)، يمكن لحزمة تطوير البرامج (SDK) الخاصة بمشرف Firebase اكتشاف سلسلة معرّف حساب الخدمة تلقائيًا من خادم البيانات الوصفية المحلي. بعد ذلك، يتم استخدام معرّف حساب الخدمة المكتشف مع خدمة IAM لتوقيع الرموز المميّزة عن بُعد.

للاستفادة من طُرق التوقيع هذه، عليك إعداد حزمة تطوير البرامج (SDK) باستخدام بيانات اعتماد Google Application Default وعدم تحديد سلسلة معرّف حساب الخدمة:

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 خدمة عن بُعد. بالإضافة إلى ذلك، يجب التأكّد أيضًا من أنّ حساب الخدمة الذي يستخدمه Admin 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 تابعة لجهة خارجية

إذا كانت الواجهة الخلفية بلغة لا تتضمّن حزمة تطوير برامج (SDK) رسمية لمشرف Firebase، سيظل بإمكانك إنشاء الرموز المميّزة المخصّصة يدويًا. أولاً، ابحث عن مكتبة JWT تابعة لجهة خارجية بلغتك. بعد ذلك، استخدِم مكتبة JWT هذه لإنشاء رمز JWT يتضمّن المطالبات التالية:

مطالبات الرموز المميّزة المخصّصة
alg خوارزمية "RS256"
iss جهة الإصدار عنوان البريد الإلكتروني لحساب الخدمة الخاص بمشروعك
sub الموضوع عنوان البريد الإلكتروني لحساب الخدمة الخاص بمشروعك
aud الجمهور "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat وقت الإصدار الوقت الحالي، بالثواني منذ بداية حقبة UNIX
exp وقت انتهاء الصلاحية الوقت الذي تنتهي فيه صلاحية الرمز المميّز، بالثواني منذ بداية حقبة يونكس يمكن أن يليه المحتوى بعد 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:

  1. افتح صفحة إدارة الهوية وإمكانية الوصول والمشرف في وحدة تحكّم Google Cloud.
  2. اختَر مشروعك وانقر على "متابعة".
  3. انقر على رمز التعديل الخاص بحساب الخدمة الذي تريد تعديله.
  4. انقر على "إضافة دور آخر".
  5. اكتب "Service Account Token Creator" (أداة إنشاء الرموز المميّزة لحساب الخدمة) في فلتر البحث، ثم اختَر هذه الأداة من النتائج.
  6. انقر على "حفظ" لتأكيد منح الدور.

يمكنك الرجوع إلى مستندات إدارة الهوية وإمكانية الوصول لمزيد من التفاصيل حول هذه العملية، أو التعرّف على كيفية تعديل الأدوار باستخدام أدوات سطر الأوامر 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).