ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

قم بإنشاء رموز مخصصة

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

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

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

قبل ان تبدأ

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

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

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

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

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

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

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

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

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

للاستفادة من طرق التوقيع هذه ، قم بتهيئة SDK باستخدام بيانات اعتماد Google Application Default ولا تحدد سلسلة معرف حساب الخدمة:

Node.js

admin.initializeApp();

جافا

317547661 ج

بايثون

default_app = firebase_admin.initialize_app()

اذهب

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

سي #

FirebaseApp.Create();

لاختبار نفس الرمز محليًا ، قم بتنزيل ملف JSON لحساب الخدمة واضبط متغير بيئة GOOGLE_APPLICATION_CREDENTIALS للإشارة إليه.

إذا كان على Firebase Admin SDK اكتشاف سلسلة معرف حساب الخدمة ، فإنها تفعل ذلك عندما تنشئ شفرتك رمزًا مميزًا مخصصًا لأول مرة. يتم تخزين النتيجة مؤقتًا وإعادة استخدامها لعمليات توقيع الرمز المميز اللاحقة. عادةً ما يكون معرف حساب الخدمة المكتشف تلقائيًا أحد حسابات الخدمة الافتراضية التي يوفرها Google Cloud Platform:

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

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

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

يمكن العثور على معرّف حساب الخدمة في وحدة تحكم Google Cloud Platform ، أو في حقل client_email لملف JSON لحساب الخدمة الذي تم تنزيله. معرّفات حساب الخدمة هي عناوين بريد إلكتروني لها التنسيق التالي: <client-id>@<project-id>.iam.gserviceaccount.com . فهي تحدد بشكل فريد حسابات الخدمة في مشاريع Firebase و Google Cloud Platform.

لإنشاء رموز مخصصة باستخدام معرف حساب خدمة منفصل ، قم بتهيئة SDK كما هو موضح أدناه:

Node.js

admin.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);

بايثون

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)
}

سي #

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 . انظر قسم استكشاف الأخطاء وإصلاحها أدناه لمزيد من التفاصيل.

أنشئ رموزًا مخصصة باستخدام Firebase Admin SDK

تحتوي حزمة Firebase Admin SDK على طريقة مضمنة لإنشاء الرموز المميزة المخصصة. كحد أدنى ، تحتاج إلى توفير uid مستخدم ، والذي يمكن أن يكون أي سلسلة ولكن يجب أن يحدد بشكل فريد المستخدم أو الجهاز الذي تقوم بمصادقته. تنتهي صلاحية هذه الرموز المميزة بعد ساعة واحدة.

Node.js

let uid = 'some-uid';

admin.auth().createCustomToken(uid)
  .then(function(customToken) {
    // Send token back to client
  })
  .catch(function(error) {
    console.log('Error creating custom token:', error);
  });

جافا

String uid = "some-uid";

String customToken = FirebaseAuth.getInstance().createCustomToken(uid);
// Send token back to client

بايثون

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

اذهب

11024543 سم مكعب

سي #

var uid = "some-uid";

string customToken = await FirebaseAuth.DefaultInstance.CreateCustomTokenAsync(uid);
// Send token back to client

يمكنك أيضًا تحديد مطالبات إضافية اختياريًا ليتم تضمينها في الرمز المميز المخصص. على سبيل المثال ، أدناه ، تمت إضافة حقل premiumAccount إلى الرمز المميز المخصص ، والذي سيكون متاحًا في كائنات auth / request.auth في قواعد الأمان الخاصة بك:

Node.js

let userId = 'some-uid';
let additionalClaims = {
  premiumAccount: true
};

admin.auth().createCustomToken(userId, additionalClaims)
  .then(function(customToken) {
    // Send token back to client
  })
  .catch(function(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

بايثون

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)

سي #

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

ج موضوعية
[[FIRAuth auth] signInWithCustomToken:customToken
                           completion:^(FIRAuthDataResult * _Nullable authResult,
                                        NSError * _Nullable error) {
  // ...
}];
سويفت
Auth.auth().signIn(withCustomToken: customToken ?? "") { (user, error) in
  // ...
}

ذكري المظهر

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);
                }
            }
        });

وحدة

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.FirebaseUser newUser = task.Result;
  Debug.LogFormat("User signed in successfully: {0} ({1})",
      newUser.DisplayName, newUser.UserId);
});

C ++

firebase::Future<firebase::auth::User*> result =
    auth->SignInWithCustomToken(custom_token);

الويب

firebase.auth().signInWithCustomToken(token).catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});

إذا نجحت المصادقة ، فسيتم الآن تسجيل دخول المستخدم إلى تطبيق العميل الخاص بك باستخدام الحساب المحدد بواسطة uid المضمن في الرمز المميز المخصص. إذا لم يكن هذا الحساب موجودًا من قبل ، فسيتم إنشاء سجل لهذا المستخدم.

بنفس الطريقة كما هو الحال مع طرق تسجيل الدخول الأخرى (مثل signInWithEmailAndPassword() و signInWithCredential() signInWithEmailAndPassword() ، signInWithCredential() كائن auth في قواعد أمان قاعدة بيانات Firebase Realtime الخاصة بك وكائن request.auth في قواعد أمان التخزين السحابي الخاص بك مع المستخدم 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 (قاعدة بيانات auth.token Realtime) أو request.auth.token (التخزين السحابي) في auth.token :

قواعد قاعدة البيانات

{
  "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 ، الذي تنتهي عنده صلاحية الرمز المميز. يمكن أن يكون بحد أقصى 3600 ثانية بعد iat .
ملاحظة: يتحكم هذا فقط في الوقت الذي تنتهي فيه صلاحية الرمز المميز المخصص نفسه. ولكن بمجرد تسجيل دخول مستخدم باستخدام signInWithCustomToken() ، signInWithCustomToken() الدخول إلى الجهاز حتى يتم إبطال جلسته أو تسجيل خروج المستخدم.
uid يجب أن يكون المعرف الفريد للمستخدم الذي قام بتسجيل الدخول عبارة عن سلسلة يتراوح طولها بين 1-36 حرفًا
claims (اختياري) مطالبات مخصصة اختيارية لتضمينها في متغيرات auth / request.auth

في ما يلي بعض الأمثلة على عمليات التنفيذ لكيفية إنشاء رموز مخصصة في مجموعة متنوعة من اللغات التي لا تدعمها Firebase Admin SDK:

بي أتش بي

باستخدام 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-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 غير ممكَّنة حاليًا لمشروع Firebase. افتح الرابط الموجود في رسالة الخطأ في متصفح الويب ، وانقر فوق الزر "تمكين واجهة برمجة التطبيقات" لتمكينه لمشروعك.

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

إذا كان حساب الخدمة الذي يعمل عليه iam.serviceAccounts.signBlob Admin SDK لا يحتوي على إذن iam.serviceAccounts.signBlob ، فقد iam.serviceAccounts.signBlob رسالة خطأ كما يلي:

Permission iam.serviceAccounts.signBlob is required to perform this operation
on service account projects/-/serviceAccounts/{your-service-account-id}.

أسهل طريقة لحل هذه المشكلة هي منح دور IAM "منشئ حساب الخدمة" لحساب الخدمة المعني ، عادةً {project-name}@appspot.gserviceaccount.com :

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

راجع وثائق 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.