تتيح لك وظائف الحظر تنفيذ تعليمات برمجية مخصصة تعدل نتيجة تسجيل المستخدم أو تسجيل الدخول إلى تطبيقك. على سبيل المثال ، يمكنك منع المستخدم من المصادقة إذا لم يستوف معايير معينة ، أو تحديث معلومات المستخدم قبل إعادتها إلى تطبيق العميل الخاص بك.
قبل ان تبدأ
لاستخدام وظائف الحظر ، يجب ترقية مشروع Firebase إلى Firebase Authentication مع Identity Platform. إذا لم تكن قد قمت بالترقية بالفعل ، فقم بذلك أولاً.
فهم وظائف الحجب
يمكنك تسجيل وظائف الحظر لحدثين:
beforeCreate
: المشغلات قبل حفظ مستخدم جديد في قاعدة بيانات Firebase Authentication ، وقبل إرجاع رمز مميز إلى تطبيق العميل.beforeSignIn
: المشغلات بعد التحقق من بيانات اعتماد المستخدم ، ولكن قبل أن تُرجع مصادقة Firebase رمزًا مميزًا للمعرف إلى تطبيق العميل الخاص بك. إذا كان تطبيقك يستخدم مصادقة متعددة العوامل ، يتم تشغيل الوظيفة بعد أن يتحقق المستخدم من العامل الثاني. لاحظ أن إنشاء مستخدم جديد يتم تشغيله أيضًاbeforeSignIn
، بالإضافة إلىbeforeCreate
.
ضع في اعتبارك ما يلي عند استخدام وظائف الحظر:
يجب أن تستجيب وظيفتك في غضون 7 ثوانٍ. بعد 7 ثوانٍ ، تُرجع مصادقة Firebase خطأً ، وتفشل عملية العميل.
يتم تمرير رموز استجابة HTTP بخلاف
200
إلى تطبيقات العميل. تأكد من أن رمز العميل الخاص بك يعالج أي أخطاء يمكن أن ترجعها وظيفتك.تنطبق الوظائف على جميع المستخدمين في مشروعك ، بما في ذلك أي وظائف موجودة في المستأجر . توفر مصادقة Firebase معلومات حول المستخدمين لوظيفتك ، بما في ذلك أي مستأجرين ينتمون إليهم ، حتى تتمكن من الاستجابة وفقًا لذلك.
يؤدي ربط موفر هوية آخر بحساب ما إلى إعادة تشغيل أي تسجيل
beforeSignIn
وظائف SignIn.لا تؤدي المصادقة المجهولة والمخصصة إلى تشغيل وظائف الحظر.
نشر وتسجيل وظيفة الحظر
لإدراج رمزك المخصص في تدفقات مصادقة المستخدم ، قم بنشر وظائف الحظر وتسجيلها. بمجرد نشر وظائف الحظر الخاصة بك وتسجيلها ، يجب أن يكتمل الرمز المخصص بنجاح للمصادقة وإنشاء المستخدم.
نشر وظيفة الحظر
تقوم بنشر وظيفة الحظر بنفس طريقة نشر أي وظيفة. (راجع صفحة بدء وظائف السحابة للحصول على التفاصيل). في ملخص:
اكتب وظائف السحابة التي تتعامل مع الحدث
beforeCreate
أو الحدثbeforeSignIn
أو كليهما.على سبيل المثال ، للبدء ، يمكنك إضافة وظائف no-op التالية إلى
index.js
:const functions = require('firebase-functions'); exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => { // TODO }); exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { // TODO });
حذفت الأمثلة أعلاه تنفيذ منطق المصادقة المخصص. راجع الأقسام التالية لمعرفة كيفية تنفيذ وظائف الحظر والسيناريوهات الشائعة للحصول على أمثلة محددة.
انشر وظائفك باستخدام Firebase CLI:
firebase deploy --only functions
يجب إعادة نشر وظائفك في كل مرة تقوم فيها بتحديثها.
تسجيل وظيفة الحظر
انتقل إلى صفحة إعدادات مصادقة Firebase في وحدة تحكم Firebase.
حدد علامة التبويب وظائف الحظر .
قم بتسجيل وظيفة الحظر الخاصة بك عن طريق تحديدها من القائمة المنسدلة ضمن إما قبل إنشاء الحساب (قبل الإنشاء) أو قبل تسجيل الدخول (قبل تسجيل الدخول) .
احفظ التغييرات.
الحصول على معلومات المستخدم والسياق
يوفر الحدثان beforeSignIn
و beforeCreate
كائنات User
و EventContext
التي تحتوي على معلومات حول المستخدم الذي قام بتسجيل الدخول. استخدم هذه القيم في التعليمات البرمجية لتحديد ما إذا كنت ستسمح لعملية ما بالمتابعة.
للحصول على قائمة بالخصائص المتوفرة في كائن User
، راجع مرجع UserRecord
API .
يحتوي كائن 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 أو المستأجر. | 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 | لم يتم تنفيذ طريقة API بواسطة الخادم. |
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}"`);
}
});
بغض النظر عما إذا كنت تستخدم رسالة افتراضية أو مخصصة ، فإن وظائف السحابة تقوم بتغليف الخطأ وإعادته إلى العميل كخطأ داخلي. على سبيل المثال:
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
يجب أن يكتشف تطبيقك الخطأ ، ويتعامل معه وفقًا لذلك. على سبيل المثال:
جافا سكريبت
// 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 إلى وظائف الحظر من موفري الهوية المختلفين. يوضح الجدول التالي بيانات الاعتماد والبيانات المدعومة لكل موفر هوية:
مزود الهوية | رمز الهوية | رمز وصول | تاريخ انتهاء الصلاحية | سر الرمز المميز | تحديث الرمز | مطالبات تسجيل الدخول |
---|---|---|---|---|---|---|
جوجل | نعم | نعم | نعم | لا | نعم | لا |
فيسبوك | لا | نعم | نعم | لا | لا | لا |
تويتر | لا | نعم | لا | نعم | لا | لا |
جيثب | لا | نعم | لا | لا | لا | لا |
مايكروسوفت | نعم | نعم | نعم | لا | نعم | لا |
ينكدين | لا | نعم | نعم | لا | لا | لا |
ياهو | نعم | نعم | نعم | لا | نعم | لا |
تفاحة | نعم | نعم | نعم | لا | نعم | لا |
SAML | لا | لا | لا | لا | لا | نعم |
OIDC | نعم | نعم | نعم | لا | نعم | نعم |
تحديث الرموز
لاستخدام رمز التحديث المميز في وظيفة الحظر ، يجب عليك أولاً تحديد مربع الاختيار في صفحة وظائف الحظر بوحدة تحكم Firebase.
لن يتم إرجاع الرموز المميزة للتحديث بواسطة أي موفري هوية عند تسجيل الدخول مباشرةً باستخدام بيانات اعتماد OAuth ، مثل الرمز المميز للمعرف أو رمز الوصول. في هذه الحالة ، سيتم تمرير نفس بيانات اعتماد OAuth من جانب العميل إلى وظيفة الحظر.
تصف الأقسام التالية كل أنواع موفري الهوية وبيانات اعتمادهم وبياناتهم المدعومة.
موفرو OIDC العام
عندما يقوم المستخدم بتسجيل الدخول باستخدام موفر OIDC عام ، سيتم تمرير بيانات الاعتماد التالية:
- رمز المعرف المميز : يتم توفيره إذا تم تحديد تدفق
id_token
. - رمز الوصول : يتم توفيره إذا تم تحديد تدفق التعليمات البرمجية. لاحظ أن تدفق الشفرة مدعوم حاليًا فقط عبر واجهة برمجة تطبيقات REST.
- تحديث الرمز المميز : يتم توفيره في حالة تحديد نطاق
offline_access
.
مثال:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
جوجل
عندما يقوم المستخدم بتسجيل الدخول باستخدام 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 ، سيتم تمرير بيانات الاعتماد التالية:
- رمز الوصول : لا تنتهي صلاحيته ما لم يتم إبطاله.
مايكروسوفت
عندما يقوم المستخدم بتسجيل الدخول مع Microsoft ، سيتم تمرير بيانات الاعتماد التالية:
- رمز الهوية
- رمز وصول
- رمز التحديث : يتم تمريره إلى وظيفة الحظر إذا تم تحديد نطاق
offline_access
.
مثال:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
ياهو
عندما يقوم المستخدم بتسجيل الدخول باستخدام Yahoo ، سيتم تمرير بيانات الاعتماد التالية دون أي معلمات أو نطاقات مخصصة:
- رمز الهوية
- رمز وصول
- تحديث الرمز
ينكدين
عندما يقوم المستخدم بتسجيل الدخول باستخدام LinkedIn ، سيتم تمرير بيانات الاعتماد التالية:
- رمز وصول
تفاحة
عندما يقوم المستخدم بتسجيل الدخول مع 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 من مناطق جغرافية مختلفة - يمكنك مطالبة المستخدم بتسجيل الدخول مرة أخرى.
استخدم مطالبات الجلسة لتتبع عنوان IP الذي يسجل المستخدم الدخول باستخدامه:
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { return { sessionClaims: { signInIpAddress: context.ipAddress, }, }; });
عندما يحاول المستخدم الوصول إلى الموارد التي تتطلب المصادقة باستخدام مصادقة Firebase ، قارن عنوان 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();
});
});
})
}
});