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

يمنحك Firebase تحكمًا كاملاً في المصادقة من خلال السماح لك بمصادقة المستخدمين أو الأجهزة باستخدام رموز JSON للويب (JWT) الآمنة. تُنشئ هذه الرموز المميزة على خادمك، وتعيدها إلى جهاز عميل، ثم تستخدمها للمصادقة عبر طريقة signInWithCustomToken().

لتحقيق ذلك، يجب إنشاء نقطة نهاية للخادم تقبل بيانات اعتماد تسجيل الدخول، مثل اسم المستخدم وكلمة المرور، وإذا كانت بيانات الاعتماد صالحة، تعرض JWT مخصّصًا. ويمكن لجهاز العميل استخدام JWT المخصّص الذي تم عرضه من الخادم بعد ذلك للمصادقة باستخدام Firebase (iOS+ وAndroid والويب). وبعد المصادقة، سيتم استخدام هذه المعلومات عند الوصول إلى خدمات Firebase الأخرى، مثل "قاعدة بيانات Firebase في الوقت الفعلي" وCloud Storage. بالإضافة إلى ذلك، سيكون محتوى JWT متاحًا في العنصر auth في قواعد أمان قاعدة البيانات في الوقت الفعلي والعنصر request.auth في قواعد أمان Cloud Storage.

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

قبل البدء

الرموز المميّزة المخصّصة هي ملفات JWT موقّعة حيث ينتمي المفتاح الخاص المستخدَم للتوقيع إلى حساب خدمة Google. هناك عدّة طرق لتحديد حساب خدمة Google الذي يجب استخدامه بواسطة حزمة تطوير البرامج (SDK) لمشرف Firebase لتوقيع الرموز المميّزة المخصّصة:

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

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

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

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

السماح لحزمة تطوير البرامج (SDK) للمشرف باكتشاف حساب خدمة

إذا تم نشر الرمز في بيئة تديرها Google، يمكن أن تحاول حزمة تطوير البرامج (SDK) للمشرف الاكتشاف التلقائي بوسيلة لتوقيع الرموز المميزة المخصصة:

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

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

للاستفادة من طُرق التوقيع هذه، عليك إعداد حزمة تطوير البرامج (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 للإشارة إليه.

إذا احتاجت "حزمة تطوير البرامج (SDK) لمشرف Firebase" إلى اكتشاف سلسلة رقم تعريف حساب الخدمة، سيؤدّي ذلك إلى إنشاء رمز مميّز مخصَّص لأول مرة. ويتم تخزين النتيجة مؤقتًا وإعادة استخدامها في العمليات اللاحقة لتوقيع الرمز المميّز. يكون عادةً معرّف حساب الخدمة الذي يتم اكتشافه تلقائيًا أحد حسابات الخدمة التلقائية التي توفّرها Google Cloud:

وكما هو الحال مع أرقام تعريف حسابات الخدمة المحدّدة بشكل واضح، يجب أن تتضمّن أرقام تعريف حسابات الخدمة التي يتم اكتشافها تلقائيًا إذن iam.serviceAccounts.signBlob حتى تعمل عملية إنشاء الرموز المميّزة المخصّصة. قد تحتاج إلى استخدام قسم إدارة الهوية وإمكانية الوصول والمشرف في وحدة تحكّم Google Cloud لمنح حسابات الخدمة التلقائية الأذونات اللازمة. لمعرفة مزيد من التفاصيل، يُرجى الاطّلاع على قسم تحديد المشاكل وحلّها أدناه.

استخدام رقم تعريف حساب الخدمة

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

يمكن العثور على رقم تعريف حساب الخدمة في Google Cloud Console، أو في الحقل 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",
});

لا تُعدّ أرقام تعريف حسابات الخدمة معلومات حساسة، وبالتالي ليس من الضروري الاستفادة منها. ومع ذلك، لتوقيع الرموز المميّزة المخصّصة باستخدام حساب الخدمة المحدّد، يجب أن تستدعي حزمة تطوير البرامج (SDK) لمشرف Firebase خدمة عن بُعد. بالإضافة إلى ذلك، عليك التأكّد أيضًا من أنّ حساب الخدمة الذي تستخدمه "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);
  });

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 في قواعد أمان قاعدة البيانات في الوقت الفعلي وعنصر 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 في الوقت الفعلي) أو 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 وقت انتهاء الصلاحية الوقت بالثواني منذ حقبة UNIX والذي تنتهي فيه صلاحية الرمز المميّز. ويمكن أن تتأخر العلامة بمقدار 3,600 ثانية كحدّ أقصى عن السمة iat.
ملاحظة: تتحكّم هذه الميزة فقط في وقت انتهاء صلاحية الرمز المميّز المخصّص نفسه. ولكن بعد تسجيل دخول المستخدم من خلال signInWithCustomToken()، سيظل مسجِّلاً الدخول إلى الجهاز إلى أن يتم إلغاء صلاحية الجلسة أو تسجيل خروج المستخدم.
uid يجب أن يكون المعرّف الفريد للمستخدم الذي سجّل الدخول سلسلةً يتراوح طولها بين حرف واحد و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 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.

تستخدم "حزمة SDK للمشرف" في Firebase واجهة برمجة التطبيقات لإدارة الهوية وإمكانية الوصول لتوقيع الرموز المميّزة. يشير هذا الخطأ إلى أنّ واجهة برمجة التطبيقات IAM API غير مفعّلة حاليًا لمشروعك على Firebase. افتح الرابط في رسالة الخطأ في متصفح الويب، وانقر فوق الزر "Enable API" (تمكين واجهة برمجة التطبيقات) لتمكينه لمشروعك.

لا يتضمّن حساب الخدمة الأذونات المطلوبة

في حال تشغيل حساب الخدمة "SDK لمشرف Firebase" لأنّه لا يملك إذن 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).