عوامل تشغيل حظر المصادقة


تتيح لك دوال الحظر تنفيذ رمز مخصّص يعدّل نتيجة تسجيل المستخدم أو تسجيل الدخول إلى تطبيقك. على سبيل المثال، يمكنك منع مستخدم من إثبات الهوية إذا لم يستوفِ معايير معيّنة، أو تعديل معلومات المستخدم قبل إرسالها إلى تطبيق العميل.

قبل البدء

لاستخدام وظائف الحظر، يجب ترقية مشروعك على Firebase إلى Firebase Authentication with Identity Platform. إذا لم يسبق لك الترقية، عليك إجراء ذلك أولاً.

فهم وظائف الحظر

يمكنك تسجيل وظائف الحظر لهذه الأحداث:

  • beforeCreate: يتم تشغيل هذا المشغّل قبل حفظ مستخدم جديد في قاعدة بيانات Firebase Authentication وقبل عرض رمز مميّز لتطبيق العميل.

  • beforeSignIn: يتم تشغيلها بعد التحقّق من بيانات اعتماد المستخدم، ولكن قبل أن تعرض الدالة Firebase Authentication رمز تعريف إلى تطبيق العميل. إذا كان تطبيقك يستخدم المصادقة المتعدّدة العوامل، يتم تشغيل الدالة بعد أن يتحقّق المستخدم من العامل الثاني. يُرجى العِلم أنّ إنشاء مستخدم جديد يؤدي أيضًا إلى تشغيل beforeSignIn، بالإضافة إلى beforeCreate.

  • beforeEmail (Node.js فقط): يتم تشغيله قبل إرسال رسالة إلكترونية إلى المستخدم (على سبيل المثال،
    رسالة إلكترونية لتسجيل الدخول أو إعادة ضبط كلمة المرور).

  • beforeSms (Node.js فقط): يتم تشغيله قبل إرسال رسالة SMS إلى مستخدم، وذلك في حالات مثل المصادقة المتعددة العوامل.

يُرجى مراعاة ما يلي عند استخدام وظائف الحظر:

  • يجب أن تستجيب الدالة في غضون 7 ثوانٍ. بعد 7 ثوانٍ، تعرض Firebase Authentication خطأ، ويتعذّر تنفيذ عملية العميل.

  • يتم تمرير رموز استجابة HTTP غير 200 إلى تطبيقات العميل. تأكَّد من أنّ رمز العميل يعالج أي أخطاء يمكن أن تعرضها الدالة.

  • تنطبق الدوال على جميع المستخدمين في مشروعك، بما في ذلك أي مستخدمين مضمّنين في مستأجر. توفّر Firebase Authentication معلومات عن المستخدمين لوظيفتك، بما في ذلك أي مستأجرين ينتمون إليهم، حتى تتمكّن من الردّ وفقًا لذلك.

  • يؤدي ربط مقدّم خدمة هوية آخر بحساب إلى إعادة تشغيل أي وظائف beforeSignIn مسجّلة.

  • لا تؤدي المصادقة المجهولة والمخصّصة إلى تشغيل وظائف الحظر.

نشر دالة حظر

لإدراج الرمز المخصّص في مسارات مصادقة المستخدم، عليك نشر دوال الحظر. بعد نشر وظائف الحظر، يجب أن يكتمل الرمز المخصّص بنجاح لكي تنجح عملية المصادقة وإنشاء المستخدم.

يمكنك نشر دالة حظر بالطريقة نفسها التي تنشر بها أي دالة. (يمكنك الاطّلاع على صفحة Cloud Functions بدء الاستخدام لمزيد من التفاصيل). وباختصار:

  1. اكتب دالة تعالج الحدث المستهدَف.

    على سبيل المثال، للبدء، يمكنك إضافة دالة no-op مثل ما يلي إلى index.js:

    const functions = require('firebase-functions/v1');
    
    exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
      // TODO
    });
    
    The above example has omitted the implementation of custom auth logic. See
    the following sections to learn how to implement your blocking functions and
    [Common scenarios](#common-scenarios) for specific examples.
    
  1. يمكنك نشر الدوال باستخدام واجهة سطر الأوامر Firebase باتّباع الخطوات التالية:

    firebase deploy --only functions
    

    يجب إعادة نشر الدوال في كل مرة تعدّلها.

الحصول على معلومات المستخدم والسياق

يوفّر الحدثان beforeSignIn وbeforeCreate العنصرَين User وEventContext اللذين يحتويان على معلومات حول المستخدم الذي يسجّل الدخول. استخدِم هذه القيم في الرمز لتحديد ما إذا كان سيتم السماح بإجراء عملية ما.

للاطّلاع على قائمة بالسمات المتاحة في العنصر User، يُرجى الرجوع إلى UserRecord مرجع واجهة برمجة التطبيقات.

يحتوي الكائن EventContext على السمات التالية:

الاسم الوصف مثال
locale تمثّل هذه السمة لغة التطبيق. يمكنك ضبط اللغة باستخدام حزمة SDK للعميل أو من خلال تمرير عنوان اللغة في واجهة REST API. fr أو sv-SE
ipAddress عنوان IP للجهاز الذي يسجّل منه المستخدم النهائي أو يسجّل الدخول. 114.14.200.1
userAgent وكيل المستخدم الذي يشغّل وظيفة الحظر. Mozilla/5.0 (X11; Linux x86_64)
eventId المعرّف الفريد للحدث. rWsyPtolplG2TBFoOkkgyg
eventType نوع الحدث. تقدّم هذه السمة معلومات عن اسم الحدث، مثل beforeSignIn أو beforeCreate، وطريقة تسجيل الدخول المرتبطة به، مثل Google أو البريد الإلكتروني/كلمة المرور. providers/cloud.auth/eventTypes/user.beforeSignIn:password
authType USER دائمًا USER
resource Firebase Authentication المشروع أو المستأجر projects/project-id/tenants/tenant-id
timestamp الوقت الذي تم فيه تشغيل الحدث، ويكون منسَّقًا كسلسلة RFC 3339. Tue, 23 Jul 2019 21:10:57 GMT
additionalUserInfo عنصر يحتوي على معلومات حول المستخدم. AdditionalUserInfo
credential عنصر يحتوي على معلومات حول بيانات اعتماد المستخدم. AuthCredential

حظر التسجيل أو تسجيل الدخول

لحظر محاولة تسجيل أو تسجيل دخول، أضِف HttpsError إلى الدالة. على سبيل المثال:

Node.js
throw new functions.auth.HttpsError('permission-denied');

يسرد الجدول التالي الأخطاء التي يمكنك إثارتها، بالإضافة إلى رسالة الخطأ التلقائية:

الاسم الرمز الرسالة
invalid-argument 400 حدّد العميل وسيطة غير صالحة.
failed-precondition 400 لا يمكن تنفيذ الطلب في حالة النظام الحالية.
out-of-range 400 حدّد العميل نطاقًا زمنيًا غير صالح.
unauthenticated 401 رمز OAuth المميز مفقود أو غير صالح أو منتهي الصلاحية.
permission-denied 403 لا يملك العميل الأذونات الكافية.
not-found 404 تعذّر العثور على المورد المحدّد.
aborted 409 حدث تعارض في التزامن، مثلاً تعارض في الكتابة والتعديل والقراءة.
already-exists 409 المورد الذي حاول العميل إنشاءه متوفّر مسبقًا.
resource-exhausted 429 نفذت حصة الموارد أو بلغت حدّ السعر الأقصى المسموح به.
cancelled 499 ألغى العميل الطلب.
data-loss 500 ثمة بيانات تالفة أو بيانات مفقودة ويتعذّر استرجاعها.
unknown 500 حدث خطأ غير معروف في الخادم.
internal 500 حدث خطأ في الخادم الداخلي.
not-implemented 501 لم يطبّق الخادم طريقة واجهة برمجة التطبيقات.
unavailable 503 الخدمة غير متاحة.
deadline-exceeded 504 انتهت المهلة النهائية لتقديم الطلب.

يمكنك أيضًا تحديد رسالة خطأ مخصّصة:

Node.js
throw new functions.auth.HttpsError('permission-denied', 'Unauthorized request origin!');

يوضّح المثال التالي كيفية حظر المستخدمين الذين لا ينتمون إلى نطاق معيّن من التسجيل في تطبيقك:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  // (If the user is authenticating within a tenant context, the tenant ID can be determined from
  // user.tenantId or from context.resource, e.g. 'projects/project-id/tenant/tenant-id-1')

  // Only users of a specific domain can sign up.
  if (user.email.indexOf('@acme.com') === -1) {
    throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email "${user.email}"`);
  }
});

بغض النظر عمّا إذا كنت تستخدم رسالة تلقائية أو مخصّصة، تغلف Cloud Functions الخطأ وتعيده إلى العميل كخطأ داخلي. على سبيل المثال:

throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);

يجب أن يرصد تطبيقك الخطأ ويتعامل معه وفقًا لذلك. على سبيل المثال:

JavaScript
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
firebase.auth().createUserWithEmailAndPassword('johndoe@example.com', 'password')
  .then((result) => {
    result.user.getIdTokenResult()
  })
  .then((idTokenResult) => {
    console.log(idTokenResult.claim.admin);
  })
  .catch((error) => {
    if (error.code !== 'auth/internal-error' && error.message.indexOf('Cloud Function') !== -1) {
      // Display error.
    } else {
      // Registration succeeds.
    }
  });

تعديل مستخدم

بدلاً من حظر محاولة تسجيل أو تسجيل دخول، يمكنك السماح بمواصلة العملية، ولكن مع تعديل العنصر User الذي يتم حفظه في قاعدة بيانات Firebase Authentication وإرجاعه إلى العميل.

لتعديل مستخدم، عليك عرض عنصر من معالج الأحداث يحتوي على الحقول المطلوب تعديلها. يمكنك تعديل الحقول التالية:

  • displayName
  • disabled
  • emailVerified
  • photoUrl
  • customClaims
  • sessionClaims (beforeSignIn فقط)

باستثناء sessionClaims، يتم حفظ جميع الحقول المعدَّلة في قاعدة بيانات Firebase Authentication، ما يعني تضمينها في الرمز المميز للرد واستمرارها بين جلسات المستخدم.

يوضّح المثال التالي كيفية ضبط اسم معروض تلقائي:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  return {
    // If no display name is provided, set it to "Guest".
    displayName: user.displayName || 'Guest';
  };
});

في حال تسجيل معالج أحداث لكلّ من beforeCreate وbeforeSignIn، يُرجى العِلم بأنّ beforeSignIn يتم تنفيذه بعد beforeCreate. تظهر حقول المستخدم التي تم تعديلها في beforeCreate في beforeSignIn. إذا ضبطت حقلًا غير sessionClaims في كلتا دالتَي معالجة الأحداث، ستتجاوز القيمة المضبوطة في beforeSignIn القيمة المضبوطة في beforeCreate. بالنسبة إلى sessionClaims فقط، يتم نقلها إلى مطالبات الرمز المميز للجلسة الحالية، ولكن لا يتم الاحتفاظ بها أو تخزينها في قاعدة البيانات.

على سبيل المثال، إذا تم ضبط أي sessionClaims، ستعرض beforeSignIn هذه القيم مع أي مطالبات beforeCreate، وسيتم دمجهما. عند دمجهما، إذا تطابق مفتاح sessionClaims مع مفتاح في customClaims، سيتم استبدال customClaims المطابق في مطالبات الرمز المميّز بمفتاح sessionClaims. ومع ذلك، سيظل المفتاح customClaims الذي تم استبداله محفوظًا في قاعدة البيانات للطلبات المستقبلية.

بيانات اعتماد OAuth والبيانات المتوافقة

يمكنك تمرير بيانات اعتماد OAuth والبيانات إلى وظائف الحظر من مختلف مزوّدي خدمات تحديد الهوية. يعرض الجدول التالي بيانات الاعتماد والبيانات المتوافقة مع كل موفّر هوية:

موفِّر الهوية الرمز المميّز لتعريف الهوية رمز الدخول وقت انتهاء الصلاحية: الرمز المميز السرّي الرمز المميّز لإعادة التحميل مطالبات تسجيل الدخول
Google نعم نعم نعم لا نعم لا
Facebook لا نعم نعم لا لا لا
Twitter لا نعم لا نعم لا لا
GitHub لا نعم لا لا لا لا
Microsoft نعم نعم نعم لا نعم لا
LinkedIn لا نعم نعم لا لا لا
Yahoo نعم نعم نعم لا نعم لا
Apple نعم نعم نعم لا نعم لا
SAML لا لا لا لا لا نعم
OIDC نعم نعم نعم لا نعم نعم

رموز إعادة التحميل

لاستخدام رمز مميّز لإعادة التحميل في دالة حظر، عليك أولاً وضع علامة في مربّع الاختيار في صفحة دوال الحظر في وحدة تحكّم Firebase.

لن تعرض أي من الجهات التي توفّر خدمات تحديد الهوية رموزًا مميّزة لإعادة التحقّق عند تسجيل الدخول مباشرةً باستخدام بيانات اعتماد OAuth، مثل رمز التعريف أو رمز الدخول. في هذه الحالة، سيتم تمرير بيانات اعتماد OAuth نفسها من جهة العميل إلى وظيفة الحظر.

تصف الأقسام التالية كل نوع من أنواع موفّري خدمات تحديد الهوية وبيانات الاعتماد والبيانات المتوافقة معها.

مقدّمو خدمات OIDC العامون

عندما يسجّل المستخدم الدخول باستخدام موفّر OIDC عام، سيتم تمرير بيانات الاعتماد التالية:

  • الرمز المميّز لتعريف الهوية: يتم توفيره في حال اختيار مسار id_token.
  • رمز الدخول: يتم توفيره في حال اختيار تدفّق الرمز. يُرجى العِلم أنّ عملية الحصول على الرمز لا تتوفّر حاليًا إلا من خلال واجهة REST API.
  • الرمز المميز لإعادة التحقّق: يتم توفيره في حال اختيار النطاق offline_access.

مثال:

const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);

Google

عندما يسجّل المستخدم الدخول باستخدام Google، سيتم تمرير بيانات الاعتماد التالية:

  • الرمز المميّز لتعريف الهوية
  • رمز الدخول
  • رمز إعادة التحميل: يتم توفيره فقط إذا تم طلب المَعلمات المخصّصة التالية:
    • access_type=offline
    • prompt=consent، إذا وافق المستخدم سابقًا ولم يتم طلب نطاق جديد

مثال:

const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
  'access_type': 'offline',
  'prompt': 'consent'
});
firebase.auth().signInWithPopup(provider);

مزيد من المعلومات عن رموز إعادة التحميل من Google

Facebook

عندما يسجّل المستخدم الدخول باستخدام Facebook، سيتم تمرير بيانات الاعتماد التالية:

GitHub

عندما يسجّل المستخدم الدخول باستخدام GitHub، سيتم تمرير بيانات الاعتماد التالية:

  • رمز الدخول: لا تنتهي صلاحيته ما لم يتم إبطاله.

Microsoft

عندما يسجّل المستخدم الدخول باستخدام Microsoft، سيتم تمرير بيانات الاعتماد التالية:

  • الرمز المميّز لتعريف الهوية
  • رمز الدخول
  • الرمز المميز لإعادة التحقّق: يتم تمريره إلى دالة الحظر إذا تم اختيار النطاق offline_access.

مثال:

const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);

Yahoo

عندما يسجّل المستخدم الدخول باستخدام Yahoo، سيتم تمرير بيانات الاعتماد التالية بدون أي مَعلمات أو نطاقات مخصّصة:

  • الرمز المميّز لتعريف الهوية
  • رمز الدخول
  • الرمز المميز لإعادة التحميل

LinkedIn

عندما يسجّل مستخدم الدخول باستخدام LinkedIn، سيتم تمرير بيانات الاعتماد التالية:

  • رمز الدخول

Apple

عندما يسجّل المستخدم الدخول باستخدام Apple، سيتم تمرير بيانات الاعتماد التالية بدون أي معلَمات أو نطاقات مخصّصة:

  • الرمز المميّز لتعريف الهوية
  • رمز الدخول
  • الرمز المميز لإعادة التحميل

السيناريوهات الشائعة

توضّح الأمثلة التالية بعض حالات الاستخدام الشائعة لوظائف الحظر:

السماح بالتسجيل من نطاق محدّد فقط

يوضّح المثال التالي كيفية منع المستخدمين غير التابعين للنطاق example.com من التسجيل في تطبيقك:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (!user.email || user.email.indexOf('@example.com') === -1) {
    throw new functions.auth.HttpsError(
      'invalid-argument', `Unauthorized email "${user.email}"`);
  }
});

حظر المستخدمين الذين لديهم عناوين بريد إلكتروني غير مؤكَّدة من التسجيل

يوضّح المثال التالي كيفية منع المستخدمين الذين لديهم عناوين بريد إلكتروني غير مثبَتة من التسجيل في تطبيقك:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (user.email && !user.emailVerified) {
    throw new functions.auth.HttpsError(
      'invalid-argument', `Unverified email "${user.email}"`);
  }
});

طلب إثبات الملكية باستخدام عنوان البريد الإلكتروني عند التسجيل

يوضّح المثال التالي كيفية إلزام المستخدم بتأكيد عنوان بريده الإلكتروني بعد التسجيل:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  const locale = context.locale;
  if (user.email && !user.emailVerified) {
    // Send custom email verification on sign-up.
    return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
      return sendCustomVerificationEmail(user.email, link, locale);
    });
  }
});

exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
 if (user.email && !user.emailVerified) {
   throw new functions.auth.HttpsError(
     'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
  }
});

التعامل مع بعض الرسائل الإلكترونية من موفِّر الهوية على أنّها تم التحقّق منها

يوضّح المثال التالي كيفية التعامل مع عناوين البريد الإلكتروني للمستخدمين من بعض موفّري خدمات تحديد الهوية على أنّها عناوين تم إثبات ملكيتها:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (user.email && !user.emailVerified && context.eventType.indexOf(':facebook.com') !== -1) {
    return {
      emailVerified: true,
    };
  }
});

حظر تسجيل الدخول من عناوين IP معيّنة

يوضّح المثال التالي كيفية حظر تسجيل الدخول من نطاقات عناوين IP معيّنة:

Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
  if (isSuspiciousIpAddress(context.ipAddress)) {
    throw new functions.auth.HttpsError(
      'permission-denied', 'Unauthorized access!');
  }
});

ضبط المطالبات المخصّصة ومطالبات الجلسة

يوضّح المثال التالي كيفية ضبط المطالبات المخصّصة ومطالبات الجلسة:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (context.credential &&
      context.credential.providerId === 'saml.my-provider-id') {
    return {
      // Employee ID does not change so save in persistent claims (stored in
      // Auth DB).
      customClaims: {
        eid: context.credential.claims.employeeid,
      },
      // Copy role and groups to token claims. These will not be persisted.
      sessionClaims: {
        role: context.credential.claims.role,
        groups: context.credential.claims.groups,
      }
    }
  }
});

تتبُّع عناوين IP لمراقبة النشاط المريب

يمكنك منع سرقة الرموز المميزة من خلال تتبُّع عنوان IP الذي يسجّل المستخدم الدخول منه، ومقارنته بعنوان IP في الطلبات اللاحقة. إذا بدا الطلب مريبًا، مثلاً إذا كانت عناوين IP من مناطق جغرافية مختلفة، يمكنك أن تطلب من المستخدم تسجيل الدخول مرة أخرى.

  1. استخدِم مطالبات الجلسة لتتبُّع عنوان IP الذي يسجّل المستخدم الدخول باستخدامه:

    Node.js
    exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
      return {
        sessionClaims: {
          signInIpAddress: context.ipAddress,
        },
      };
    });
    
  2. عندما يحاول مستخدم الوصول إلى موارد تتطلّب المصادقة باستخدام Firebase Authentication، قارِن عنوان IP في الطلب بعنوان IP المستخدَم لتسجيل الدخول:

    Node.js
    app.post('/getRestrictedData', (req, res) => {
      // Get the ID token passed.
      const idToken = req.body.idToken;
      // Verify the ID token, check if revoked and decode its payload.
      admin.auth().verifyIdToken(idToken, true).then((claims) => {
        // Get request IP address
        const requestIpAddress = req.connection.remoteAddress;
        // Get sign-in IP address.
        const signInIpAddress = claims.signInIpAddress;
        // Check if the request IP address origin is suspicious relative to
        // the session IP addresses. The current request timestamp and the
        // auth_time of the ID token can provide additional signals of abuse,
        // especially if the IP address suddenly changed. If there was a sudden
        // geographical change in a short period of time, then it will give
        // stronger signals of possible abuse.
        if (!isSuspiciousIpAddressChange(signInIpAddress, requestIpAddress)) {
          // Suspicious IP address change. Require re-authentication.
          // You can also revoke all user sessions by calling:
          // admin.auth().revokeRefreshTokens(claims.sub).
          res.status(401).send({error: 'Unauthorized access. Please login again!'});
        } else {
          // Access is valid. Try to return data.
          getData(claims).then(data => {
            res.end(JSON.stringify(data);
          }, error => {
            res.status(500).send({ error: 'Server error!' })
          });
        }
      });
    });
    

فحص صور المستخدمين

يوضّح المثال التالي كيفية تنظيف صور الملفات الشخصية للمستخدمين:

Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (user.photoURL) {
    return isPhotoAppropriate(user.photoURL)
      .then((status) => {
        if (!status) {
          // Sanitize inappropriate photos by replacing them with guest photos.
          // Users could also be blocked from sign-up, disabled, etc.
          return {
            photoUrl: PLACEHOLDER_GUEST_PHOTO_URL,
          };
        }
      });
});

لمزيد من المعلومات حول كيفية رصد الصور وتنظيفها، يُرجى الاطّلاع على مستندات Cloud Vision.

الوصول إلى بيانات اعتماد OAuth الخاصة بموفّر هوية المستخدم

يوضّح المثال التالي كيفية الحصول على رمز مميز لإعادة التحميل لمستخدم سجّل الدخول باستخدام Google، وكيفية استخدامه لاستدعاء واجهات برمجة التطبيقات في "تقويم Google". يتم تخزين رمز التحديث للسماح بالوصول بلا إنترنت.

Node.js
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');
// ...
// Initialize Google OAuth client.
const keys = require('./oauth2.keys.json');
const oAuth2Client = new OAuth2Client(
  keys.web.client_id,
  keys.web.client_secret
);

exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  if (context.credential &&
      context.credential.providerId === 'google.com') {
    // Store the refresh token for later offline use.
    // These will only be returned if refresh tokens credentials are included
    // (enabled by Cloud console).
    return saveUserRefreshToken(
        user.uid,
        context.credential.refreshToken,
        'google.com'
      )
      .then(() => {
        // Blocking the function is not required. The function can resolve while
        // this operation continues to run in the background.
        return new Promise((resolve, reject) => {
          // For this operation to succeed, the appropriate OAuth scope should be requested
          // on sign in with Google, client-side. In this case:
          // https://www.googleapis.com/auth/calendar
          // You can check granted_scopes from within:
          // context.additionalUserInfo.profile.granted_scopes (space joined list of scopes).

          // Set access token/refresh token.
          oAuth2Client.setCredentials({
            access_token: context.credential.accessToken,
            refresh_token: context.credential.refreshToken,
          });
          const calendar = google.calendar('v3');
          // Setup Onboarding event on user's calendar.
          const event = {/** ... */};
          calendar.events.insert({
            auth: oauth2client,
            calendarId: 'primary',
            resource: event,
          }, (err, event) => {
            // Do not fail. This is a best effort approach.
            resolve();
          });
      });
    })
  }
});

تجاوز قرار reCAPTCHA Enterprise بشأن عملية المستخدم

يوضّح المثال التالي كيفية إلغاء قرار reCAPTCHA Enterprise في مسارات المستخدمين المتوافقة.

راجِع مقالة تفعيل reCAPTCHA Enterprise لمعرفة المزيد عن دمج reCAPTCHA Enterprise مع Firebase Authentication.

يمكن استخدام دوال الحظر للسماح بالتدفقات أو حظرها استنادًا إلى عوامل مخصّصة، وبالتالي إلغاء النتيجة التي تقدّمها reCAPTCHA Enterprise.

Node.js
const functions = require("firebase-functions/v1");
exports.beforesmsv1 = functions.auth.user().beforeSms((context) => {
 if (
   context.smsType === "SIGN_IN_OR_SIGN_UP" &&
   context.additionalUserInfo.phoneNumber.includes('+91')
 ) {
   return {
     recaptchaActionOverride: "ALLOW",
   };
 }

 // Allow users to sign in with recaptcha score greater than 0.5
 if (event.additionalUserInfo.recaptchaScore > 0.5) {
   return {
     recaptchaActionOverride: 'ALLOW',
   };
 }

 // Block all others.
 return  {
   recaptchaActionOverride: 'BLOCK',
 }
});