توابع مسدود کردن به شما امکان می دهند کد سفارشی را اجرا کنید که نتیجه ثبت نام یا ورود کاربر به برنامه شما را تغییر می دهد. برای مثال، میتوانید از احراز هویت کاربر در صورت عدم رعایت معیارهای خاص جلوگیری کنید یا اطلاعات کاربر را قبل از بازگرداندن آن به برنامه مشتری خود بهروزرسانی کنید.
قبل از شروع
برای استفاده از توابع مسدود کردن، باید پروژه Firebase خود را به Firebase Authentication with Identity Platform ارتقا دهید. اگر قبلاً ارتقاء نداده اید، ابتدا این کار را انجام دهید.
درک عملکردهای مسدود کردن
می توانید توابع مسدود کردن را برای این رویدادها ثبت کنید:
قبل از ایجاد کاربر : قبل از ذخیره شدن کاربر جدید در پایگاه داده Firebase Authentication و قبل از بازگرداندن رمز به برنامه مشتری شما فعال می شود.
قبل از اینکه کاربر به سیستم وارد شود : پس از تأیید اعتبار کاربر، اما قبل از اینکه Firebase Authentication یک کد شناسه را به برنامه مشتری شما بازگرداند، فعال میشود. اگر برنامه شما از احراز هویت چند عاملی استفاده میکند، این تابع پس از تأیید فاکتور دوم توسط کاربر فعال میشود. توجه داشته باشید که ایجاد یک کاربر جدید هر دو این رویدادها را نیز آغاز می کند.
قبل از ارسال ایمیل (فقط Node.js) : قبل از ایمیل فعال می شود (به عنوان مثال،
یک ایمیل ورود به سیستم یا تنظیم مجدد رمز عبور) برای یک کاربر ارسال می شود.قبل از ارسال پیام کوتاه (فقط Node.js) : برای مواردی مانند احراز هویت چند عاملی، قبل از ارسال پیام SMS به کاربر فعال می شود.
هنگام استفاده از توابع مسدود کردن موارد زیر را در نظر داشته باشید:
تابع شما باید در عرض 7 ثانیه پاسخ دهد. پس از 7 ثانیه، Firebase Authentication خطایی را برمیگرداند و عملیات کلاینت با شکست مواجه میشود.
کدهای پاسخ HTTP غیر از
200
به برنامه های مشتری شما منتقل می شوند. اطمینان حاصل کنید که کد مشتری شما خطاهایی را که عملکرد شما می تواند برگرداند، کنترل کند.توابع برای همه کاربران پروژه شما اعمال می شود، از جمله هر کدام که در یک مستاجر وجود دارد. Firebase Authentication اطلاعاتی در مورد کاربران تابع شما، از جمله مستاجرینی که به آنها تعلق دارند، ارائه میکند، بنابراین میتوانید مطابق با آن پاسخ دهید.
پیوند دادن یک ارائهدهنده هویت دیگر به یک حساب، هر توابع ثبتشده
beforeUserSignedIn
دوباره فعال میکند.احراز هویت ناشناس و سفارشی باعث ایجاد توابع مسدود نمی شود.
یک تابع مسدود کننده را مستقر کنید
برای درج کد سفارشی خود در جریان های احراز هویت کاربر، توابع مسدود کننده را مستقر کنید. هنگامی که توابع مسدود کردن شما مستقر شدند، کد سفارشی شما باید با موفقیت تکمیل شود تا احراز هویت و ایجاد کاربر موفقیت آمیز باشد.
شما یک تابع مسدود کننده را به همان روشی که هر تابعی را استقرار می دهید، مستقر می کنید. (برای جزئیات به صفحه شروع Cloud Functions مراجعه کنید). به طور خلاصه:
تابعی بنویسید که رویداد مورد نظر را مدیریت کند.
به عنوان مثال، برای شروع، می توانید یک تابع no-op مانند زیر را به منبع خود اضافه کنید:
Node.js
import { beforeUserCreated, } from "firebase-functions/v2/identity"; export const beforecreated = beforeUserCreated((event) => { // TODO return; });
پایتون
@identity_fn.before_user_created() def created_noop(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None: return
مثال بالا اجرای منطق احراز هویت سفارشی را حذف کرده است. برای یادگیری نحوه اجرای توابع مسدود کننده و سناریوهای مشترک برای مثال های خاص ، به بخش های زیر مراجعه کنید.
توابع خود را با استفاده از Firebase CLI مستقر کنید:
firebase deploy --only functions
شما باید هر بار که آنها را به روز کنید ، کارکردهای خود را دوباره مستقر کنید.
دریافت اطلاعات کاربر و زمینه
رویدادهای مسدود کردن یک شی AuthBlockingEvent
را ارائه می دهد که حاوی اطلاعاتی در مورد ورود کاربر به سیستم است. از این مقادیر در کد خود استفاده کنید تا تعیین کنید که آیا اجازه می دهید عملیات ادامه یابد یا خیر.
شی شامل ویژگی های زیر است:
نام | توضیحات | مثال |
---|---|---|
locale | محل برنامه. می توانید محل را با استفاده از SDK مشتری یا با عبور از عنوان محلی در API REST تنظیم کنید. | 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
import { HttpsError } from "firebase-functions/v2/identity";
throw new HttpsError('invalid-argument');
پایتون
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT)
همچنین می توانید یک پیام خطای سفارشی را مشخص کنید:
Node.js
throw new HttpsError('permission-denied', 'Unauthorized request origin!');
پایتون (پیش نمایش)
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="Unauthorized request origin!"
)
مثال زیر نشان می دهد که چگونه می توان کاربرانی را که در دامنه خاصی نیستند از ثبت نام برای برنامه خود مسدود کرد:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
// (If the user is authenticating within a tenant context, the tenant ID can be determined from
// user.tenantId or from event.resource, e.g. 'projects/project-id/tenant/tenant-id-1')
// Only users of a specific domain can sign up.
if (!user?.email?.includes('@acme.com')) {
throw new HttpsError('invalid-argument', "Unauthorized email");
}
});
پایتون
# Block account creation with any non-acme email address.
@identity_fn.before_user_created()
def validatenewuser(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
# User data passed in from the CloudEvent.
user = event.data
# Only users of a specific domain can sign up.
if user.email is None or "@acme.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email")
صرف نظر از اینکه از یک پیام پیشفرض یا سفارشی استفاده میکنید، Cloud Functions خطا را جمعبندی میکند و آن را به عنوان یک خطای داخلی به مشتری برمیگرداند. به عنوان مثال:
Node.js
throw new HttpsError('invalid-argument', "Unauthorized email");
پایتون
# Only users of a specific domain can sign up.
if user.email is None or "@acme.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email")
برنامه شما باید خطا را دریافت کند و مطابق آن با آن برخورد کند. به عنوان مثال:
جاوا اسکریپت
import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth';
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
const auth = getAuth();
try {
const result = await createUserWithEmailAndPassword(auth)
const idTokenResult = await result.user.getIdTokenResult();
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
(فقطbeforeUserSignedIn
)
به استثنای sessionClaims
، همه فیلدهای اصلاح شده در پایگاه داده Firebase Authentication ذخیره میشوند، به این معنی که در نشانه پاسخ گنجانده شده و بین جلسات کاربر باقی میمانند.
مثال زیر نحوه تنظیم یک نام نمایشی پیش فرض را نشان می دهد:
Node.js
export const beforecreated = beforeUserCreated((event) => {
return {
// If no display name is provided, set it to "Guest".
displayName: event.data.displayName || 'Guest'
};
});
پایتون
@identity_fn.before_user_created()
def setdefaultname(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
return identity_fn.BeforeCreateResponse(
# If no display name is provided, set it to "Guest".
display_name=event.data.display_name if event.data.display_name is not None else "Guest")
اگر یک کنترل کننده رویداد برای beforeUserCreated
و beforeUserSignedIn
ثبت می کنید، توجه داشته باشید که beforeUserSignedIn
بعد از beforeUserCreated
اجرا می شود. فیلدهای کاربر به روز شده در beforeUserCreated
در beforeUserSignedIn
قابل مشاهده است. اگر فیلدی غیر از sessionClaims
در هر دو کنترل کننده رویداد تنظیم کنید، مقدار تنظیم شده در beforeUserSignedIn
مقدار تنظیم شده در beforeUserCreated
را بازنویسی می کند. فقط برای sessionClaims
، آنها به ادعاهای رمز جلسه جاری منتشر می شوند، اما در پایگاه داده باقی نمی مانند یا ذخیره نمی شوند.
به عنوان مثال، اگر هر sessionClaims
تنظیم شده باشد، beforeUserSignedIn
آنها را با هر ادعای beforeUserCreated
برمی گرداند و ادغام می شوند. هنگامی که آنها ادغام می شوند، اگر یک کلید sessionClaims
با یک کلید در customClaims
مطابقت داشته باشد، customClaims
منطبق با کلید sessionClaims
در ادعاهای نشانه بازنویسی می شود. با این حال، کلید customClaims
بازنویسی شده همچنان در پایگاه داده برای درخواستهای آینده باقی خواهد ماند.
اطلاعات و اطلاعات کاربری OAuth پشتیبانی می شود
میتوانید اعتبارنامهها و دادههای OAuth را برای مسدود کردن توابع از ارائهدهندگان هویت مختلف ارسال کنید. جدول زیر نشان می دهد که چه اعتبارنامه ها و داده هایی برای هر ارائه دهنده هویت پشتیبانی می شود:
ارائه دهنده هویت | شناسه شناسه | رمز دسترسی | زمان انقضا | رمز رمز | Refresh Token | ادعاهای ورود به سیستم |
---|---|---|---|---|---|---|
گوگل | بله | بله | بله | خیر | بله | خیر |
فیس بوک | خیر | بله | بله | خیر | خیر | خیر |
توییتر | خیر | بله | خیر | بله | خیر | خیر |
GitHub | خیر | بله | خیر | خیر | خیر | خیر |
مایکروسافت | بله | بله | بله | خیر | بله | خیر |
لینکدین | خیر | بله | بله | خیر | خیر | خیر |
یاهو | بله | بله | بله | خیر | بله | خیر |
اپل | بله | بله | بله | خیر | بله | خیر |
SAML | خیر | خیر | خیر | خیر | خیر | بله |
OIDC | بله | بله | بله | خیر | بله | بله |
توکن های OAuth
برای استفاده از یک نشانه شناسه، نشانه دسترسی، یا نشانه بازخوانی در یک عملکرد مسدود کننده، ابتدا باید کادر تأیید صفحه توابع مسدود کردن کنسول Firebase را انتخاب کنید.
هنگام ورود مستقیم با اعتبار OAuth، مانند رمز شناسایی یا رمز دسترسی، هیچ ارائهدهنده هویتی، نشانههای Refresh را برگرداند. در این شرایط، همان اعتبار OAuth سمت کلاینت به تابع مسدود کننده منتقل می شود.
بخشهای زیر هر نوع ارائهدهنده هویت و اعتبارنامهها و دادههای پشتیبانیشده آنها را توضیح میدهد.
ارائه دهندگان عمومی OIDC
هنگامی که یک کاربر با یک ارائه دهنده OIDC عمومی وارد می شود، اعتبار زیر ارسال می شود:
- شناسه نشانه : در صورت انتخاب جریان
id_token
ارائه می شود. - نشانه دسترسی : در صورت انتخاب جریان کد ارائه می شود. توجه داشته باشید که جریان کد در حال حاضر فقط از طریق REST API پشتیبانی می شود.
- نشانه Refresh : در صورت انتخاب محدوده
offline_access
ارائه می شود.
مثال:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
گوگل
هنگامی که کاربر با Google وارد می شود، اعتبار زیر ارسال می شود:
- شناسه شناسه
- نشانه دسترسی
- نشانه Refresh : فقط در صورت درخواست پارامترهای سفارشی زیر ارائه می شود:
-
access_type=offline
-
prompt=consent
، اگر کاربر قبلاً رضایت داده باشد و دامنه جدیدی درخواست نشده باشد
-
مثال:
import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
const auth = getAuth();
const provider = new GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
signInWithPopup(auth, provider);
درباره نشانههای تازهسازی Google بیشتر بیاموزید.
فیس بوک
هنگامی که یک کاربر با فیس بوک وارد می شود، اعتبار زیر ارسال می شود:
- نشانه دسترسی : یک نشانه دسترسی برگردانده می شود که می تواند با یک نشانه دسترسی دیگر مبادله شود. درباره انواع مختلف توکن های دسترسی پشتیبانی شده توسط Facebook و نحوه مبادله آنها با توکن های با عمر طولانی بیشتر بیاموزید.
GitHub
هنگامی که کاربر با GitHub وارد می شود، اعتبار زیر ارسال می شود:
- نشانه دسترسی : منقضی نمی شود مگر اینکه لغو شود.
مایکروسافت
هنگامی که یک کاربر با مایکروسافت وارد می شود، اعتبار زیر ارسال می شود:
- شناسه شناسه
- نشانه دسترسی
- نشانه Refresh : در صورت انتخاب محدوده
offline_access
، به تابع مسدود کننده منتقل می شود.
مثال:
import { getAuth, signInWithPopup, OAuthProvider } from 'firebase/auth';
const auth = getAuth();
const provider = new OAuthProvider('microsoft.com');
provider.addScope('offline_access');
signInWithPopup(auth, provider);
یاهو
هنگامی که کاربر با یاهو وارد می شود، اعتبار زیر بدون هیچ گونه پارامتر یا محدوده سفارشی ارسال می شود:
- شناسه شناسه
- نشانه دسترسی
- نشانه تازه کردن
لینکدین
هنگامی که کاربر با لینکدین وارد می شود، اعتبار زیر ارسال می شود:
- نشانه دسترسی
اپل
هنگامی که کاربر با اپل وارد می شود، اعتبار زیر بدون هیچ گونه پارامتر یا محدوده سفارشی ارسال می شود:
- شناسه شناسه
- نشانه دسترسی
- نشانه تازه کردن
سناریوهای رایج
مثالهای زیر برخی از موارد استفاده رایج برای مسدود کردن توابع را نشان میدهند:
فقط اجازه ثبت از یک دامنه خاص
مثال زیر نشان می دهد که چگونه از ثبت نام کاربرانی که بخشی از دامنه example.com
در برنامه شما نیستند جلوگیری کنید:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (!user?.email?.includes('@example.com')) {
throw new HttpsError(
'invalid-argument', 'Unauthorized email');
}
});
پایتون (پیش نمایش)
@identity_fn.before_user_created()
def validatenewuser(
event: identity_fn.AuthBlockingEvent,
) -> identity_fn.BeforeCreateResponse | None:
# User data passed in from the CloudEvent.
user = event.data
# Only users of a specific domain can sign up.
if user.email is None or "@example.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email",
)
مسدود کردن کاربران با ایمیل های تایید نشده از ثبت نام
مثال زیر نشان میدهد که چگونه از ثبت نام کاربرانی که ایمیلهای تایید نشده در برنامه خود دارند جلوگیری کنید:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (user.email && !user.emailVerified) {
throw new HttpsError(
'invalid-argument', 'Unverified email');
}
});
پایتون
@identity_fn.before_user_created()
def requireverified(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.email is not None and not event.data.email_verified:
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="You must register using a trusted provider.")
بررسی ایمیلهای ارائهدهنده هویت خاص به عنوان تأیید شده
مثال زیر نشان می دهد که چگونه می توان با ایمیل های کاربر از ارائه دهندگان هویت خاص به عنوان تأیید شده برخورد کرد:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (user.email && !user.emailVerified && event.eventType.includes(':facebook.com')) {
return {
emailVerified: true,
};
}
});
پایتون
@identity_fn.before_user_created()
def markverified(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.email is not None and "@facebook.com" in event.data.email:
return identity_fn.BeforeSignInResponse(email_verified=True)
مسدود کردن ورود به سیستم از آدرسهای IP خاص
مثال زیر نحوه مسدود کردن ورود از محدوده آدرس IP خاص را نشان می دهد:
Node.js
export const beforesignedin = beforeUserSignedIn((event) => {
if (isSuspiciousIpAddress(event.ipAddress)) {
throw new HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
پایتون
@identity_fn.before_user_signed_in()
def ipban(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None:
if is_suspicious(event.ip_address):
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="IP banned.")
تنظیم ادعاهای سفارشی و جلسه
مثال زیر نحوه تنظیم ادعاهای سفارشی و جلسات را نشان می دهد:
Node.js
export const beforecreated = beforeUserCreated((event) => {
if (event.credential &&
event.credential.claims &&
event.credential.providerId === "saml.my-provider-id") {
return {
// Employee ID does not change so save in persistent claims (stored in
// Auth DB).
customClaims: {
eid: event.credential.claims.employeeid,
},
};
}
});
export const beforesignin = beforeUserSignedIn((event) => {
if (event.credential &&
event.credential.claims &&
event.credential.providerId === "saml.my-provider-id") {
return {
// Copy role and groups to token claims. These will not be persisted.
sessionClaims: {
role: event.credential.claims.role,
groups: event.credential.claims.groups,
},
};
}
});
پایتون
@identity_fn.before_user_created()
def setemployeeid(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if (event.credential is not None and event.credential.claims is not None and
event.credential.provider_id == "saml.my-provider-id"):
return identity_fn.BeforeCreateResponse(
custom_claims={"eid": event.credential.claims["employeeid"]})
@identity_fn.before_user_signed_in()
def copyclaimstosession(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None:
if (event.credential is not None and event.credential.claims is not None and
event.credential.provider_id == "saml.my-provider-id"):
return identity_fn.BeforeSignInResponse(session_claims={
"role": event.credential.claims["role"],
"groups": event.credential.claims["groups"]
})
ردیابی آدرس های IP برای نظارت بر فعالیت های مشکوک
میتوانید با ردیابی آدرس IP که کاربر از آن وارد میشود و مقایسه آن با آدرس IP در درخواستهای بعدی، از سرقت توکن جلوگیری کنید. اگر درخواست مشکوک به نظر می رسد - برای مثال، IP ها از مناطق جغرافیایی مختلف هستند - می توانید از کاربر بخواهید دوباره وارد شود.
از ادعاهای جلسه برای ردیابی آدرس IP که کاربر با آن وارد می شود استفاده کنید:
Node.js
export const beforesignedin = beforeUserSignedIn((event) => { return { sessionClaims: { signInIpAddress: event.ipAddress, }, }; });
پایتون
@identity_fn.before_user_signed_in() def logip(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None: return identity_fn.BeforeSignInResponse(session_claims={"signInIpAddress": event.ip_address})
هنگامی که کاربر سعی می کند با 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!' }) }); } }); });
پایتون (پیش نمایش)
from firebase_admin import auth, initialize_app import flask initialize_app() flask_app = flask.Flask(__name__) @flask_app.post() def get_restricted_data(req: flask.Request): # Get the ID token passed. id_token = req.json().get("idToken") # Verify the ID token, check if revoked, and decode its payload. try: claims = auth.verify_id_token(id_token, check_revoked=True) except: return flask.Response(status=500) # Get request IP address. request_ip = req.remote_addr # Get sign-in IP address. signin_ip = 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 is_suspicious_change(signin_ip, request_ip): # Suspicious IP address change. Require re-authentication. # You can also revoke all user sessions by calling: # auth.revoke_refresh_tokens(claims["sub"]) return flask.Response(status=401, response="Unauthorized access. Sign in again!") else: # Access is valid. Try to return data. return data_from_claims(claims)
غربالگری عکس های کاربران
مثال زیر نحوه پاکسازی عکس پروفایل کاربران را نشان می دهد:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
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,
};
}
});
});
پایتون
@identity_fn.before_user_created()
def sanitizeprofilephoto(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.photo_url is not None:
score = analyze_photo_with_ml(event.data.photo_url)
if score > THRESHOLD:
return identity_fn.BeforeCreateResponse(photo_url=PLACEHOLDER_URL)
برای کسب اطلاعات بیشتر در مورد نحوه شناسایی و پاکسازی تصاویر، به مستندات Cloud Vision مراجعه کنید.
دسترسی به اطلاعات کاربری OAuth ارائه دهنده هویت کاربر
مثال زیر نشان میدهد که چگونه میتوان برای کاربری که با Google وارد شده است، یک نشانه تازهسازی دریافت کرد و از آن برای فراخوانی APIهای تقویم 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
);
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (event.credential &&
event.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,
event.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:
// event.additionalUserInfo.profile.granted_scopes (space joined list of scopes).
// Set access token/refresh token.
oAuth2Client.setCredentials({
access_token: event.credential.accessToken,
refresh_token: event.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();
});
});
})
}
});
پایتون
@identity_fn.before_user_created()
def savegoogletoken(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
"""During sign-up, save the Google OAuth2 access token and queue up a task
to schedule an onboarding session on the user's Google Calendar.
You will only get an access token if you enabled it in your project's blocking
functions settings in the Firebase console:
https://console.firebase.google.com/project/_/authentication/settings
"""
if event.credential is not None and event.credential.provider_id == "google.com":
print(f"Signed in with {event.credential.provider_id}. Saving access token.")
firestore_client: google.cloud.firestore.Client = firestore.client()
doc_ref = firestore_client.collection("user_info").document(event.data.uid)
doc_ref.set({"calendar_access_token": event.credential.access_token}, merge=True)
tasks_client = google.cloud.tasks_v2.CloudTasksClient()
task_queue = tasks_client.queue_path(params.PROJECT_ID.value,
options.SupportedRegion.US_CENTRAL1,
"scheduleonboarding")
target_uri = get_function_url("scheduleonboarding")
calendar_task = google.cloud.tasks_v2.Task(http_request={
"http_method": google.cloud.tasks_v2.HttpMethod.POST,
"url": target_uri,
"headers": {
"Content-type": "application/json"
},
"body": json.dumps({
"data": {
"uid": event.data.uid
}
}).encode()
},
schedule_time=datetime.now() +
timedelta(minutes=1))
tasks_client.create_task(parent=task_queue, task=calendar_task)
لغو حکم reCAPTCHA Enterprise برای عملیات کاربر
مثال زیر نشان می دهد که چگونه می توان یک حکم reCAPTCHA Enterprise را برای جریان های کاربر پشتیبانی شده لغو کرد.
برای کسب اطلاعات بیشتر در مورد ادغام reCAPTCHA Enterprise با Firebase Authentication به فعال کردن reCAPTCHA Enterprise مراجعه کنید.
توابع مسدود کردن را می توان برای اجازه یا مسدود کردن جریان ها بر اساس عوامل سفارشی استفاده کرد، در نتیجه نتیجه ارائه شده توسط reCAPTCHA Enterprise را نادیده گرفت.
Node.js
const { beforeSmsSent } = require("firebase-functions/v2/identity");
exports.beforesmssentv2 = beforeSmsSent((event) => {
if (
event.smsType === "SIGN_IN_OR_SIGN_UP" &&
event.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',
}
});