اگر به Firebase Authentication with Identity Platform ارتقا دادهاید، میتوانید احراز هویت چند مرحلهای از طریق پیامک را به برنامه وب خود اضافه کنید.
احراز هویت چند عاملی امنیت برنامه شما را افزایش میدهد. در حالی که مهاجمان اغلب رمزهای عبور و حسابهای کاربری شبکههای اجتماعی را به خطر میاندازند، رهگیری یک پیام متنی دشوارتر است.
قبل از اینکه شروع کنی
حداقل یک ارائهدهنده که از احراز هویت چند عاملی پشتیبانی میکند را فعال کنید. همه ارائهدهندگان از MFA پشتیبانی میکنند، به جز احراز هویت از طریق تلفن، احراز هویت ناشناس و مرکز بازی اپل.
مناطقی را که قصد دارید از احراز هویت پیامکی در آنها استفاده کنید، فعال کنید. Firebase از یک سیاست مسدودسازی کامل منطقه پیامکی استفاده میکند که به طور پیشفرض به ایجاد پروژههای شما در حالت امنتر کمک میکند.
مطمئن شوید که برنامه شما ایمیلهای کاربر را تأیید میکند. احراز هویت چندعاملی (MFA) نیاز به تأیید ایمیل دارد. این امر مانع از آن میشود که افراد مخرب با ایمیلی که متعلق به آنها نیست، در یک سرویس ثبتنام کنند و سپس با اضافه کردن یک عامل دوم، مالک واقعی را مسدود کنند.
استفاده از چند مستاجری
اگر احراز هویت چند عاملی را برای استفاده در یک محیط چند مستاجری فعال میکنید، حتماً مراحل زیر را (علاوه بر بقیه دستورالعملهای موجود در این سند) انجام دهید:
در کنسول گوگل کلود، مستأجری را که میخواهید با او کار کنید، انتخاب کنید.
در کد خود، فیلد
tenantIdرا در نمونهAuthبرابر با شناسه مستاجر خود تنظیم کنید. برای مثال:Web
import { getAuth } from "firebase/auth"; const auth = getAuth(app); auth.tenantId = "myTenantId1";Web
firebase.auth().tenantId = 'myTenantId1';
فعال کردن احراز هویت چند عاملی
صفحه Authentication > Sign-in method را در کنسول Firebase باز کنید.
در بخش پیشرفته ، تأیید هویت چند عاملی پیامکی را فعال کنید.
همچنین باید شماره تلفنهایی را که قرار است برنامه خود را با آنها آزمایش کنید، وارد کنید. اگرچه اختیاری است، اما ثبت شماره تلفنهای آزمایشی اکیداً توصیه میشود تا از ایجاد مشکل در طول توسعه جلوگیری شود.
اگر هنوز دامنه برنامه خود را مجاز نکردهاید، آن را به لیست مجاز در صفحه Authentication > Settings کنسول Firebase اضافه کنید.
انتخاب الگوی ثبت نام
شما میتوانید انتخاب کنید که آیا برنامه شما به احراز هویت چند عاملی نیاز دارد یا خیر، و چگونه و چه زمانی کاربران خود را ثبت نام کنید. برخی از الگوهای رایج عبارتند از:
فاکتور دوم کاربر را به عنوان بخشی از ثبت نام ثبت کنید. اگر برنامه شما نیاز به احراز هویت چند عاملی برای همه کاربران دارد، از این روش استفاده کنید.
یک گزینه قابل رد کردن برای ثبت فاکتور دوم در طول ثبت نام ارائه دهید. برنامههایی که میخواهند احراز هویت چند عاملی را تشویق کنند، اما الزامی به آن نداشته باشند، ممکن است این رویکرد را ترجیح دهند.
امکان اضافه کردن عامل دوم از صفحه مدیریت حساب یا پروفایل کاربر، به جای صفحه ثبت نام، را فراهم کنید. این کار باعث میشود که در طول فرآیند ثبت نام، اصطکاک به حداقل برسد، در حالی که همچنان احراز هویت چند عاملی برای کاربران حساس به امنیت در دسترس است.
وقتی کاربر میخواهد به ویژگیهایی با الزامات امنیتی بالاتر دسترسی پیدا کند، به تدریج یک عامل دوم اضافه کنید.
راهاندازی تأییدکننده reCAPTCHA
قبل از اینکه بتوانید کدهای پیامکی ارسال کنید، باید یک تأییدکننده reCAPTCHA را پیکربندی کنید. Firebase از reCAPTCHA برای جلوگیری از سوءاستفاده استفاده میکند و تضمین میکند که درخواستهای تأیید شماره تلفن از یکی از دامنههای مجاز برنامه شما ارسال میشوند.
نیازی نیست که کلاینت reCAPTCHA را به صورت دستی تنظیم کنید؛ شیء RecaptchaVerifier در SDK کلاینت، به طور خودکار هرگونه کلید و رمز کلاینت لازم را ایجاد و مقداردهی اولیه میکند.
استفاده از reCAPTCHA نامرئی
شیء RecaptchaVerifier از reCAPTCHA نامرئی پشتیبانی میکند که اغلب میتواند کاربر را بدون نیاز به هیچ تعاملی تأیید کند. برای استفاده از reCAPTCHA نامرئی، یک RecaptchaVerifier با پارامتر size تنظیم شده روی invisible ایجاد کنید و شناسه عنصر رابط کاربری که ثبتنام چند عاملی را شروع میکند، مشخص کنید:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(), "sign-in-button", {
"size": "invisible",
"callback": function(response) {
// reCAPTCHA solved, you can proceed with
// phoneAuthProvider.verifyPhoneNumber(...).
onSolvedRecaptcha();
}
});
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
// reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
onSolvedRecaptcha();
}
});
استفاده از ویجت reCAPTCHA
برای استفاده از یک ویجت reCAPTCHA قابل مشاهده، یک عنصر HTML ایجاد کنید که ویجت را در خود جای دهد، سپس یک شیء RecaptchaVerifier با شناسهی کانتینر رابط کاربری ایجاد کنید. همچنین میتوانید به صورت اختیاری callbackهایی را تنظیم کنید که هنگام حل شدن یا منقضی شدن reCAPTCHA فراخوانی شوند:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(
getAuth(),
"recaptcha-container",
// Optional reCAPTCHA parameters.
{
"size": "normal",
"callback": function(response) {
// reCAPTCHA solved, you can proceed with
// phoneAuthProvider.verifyPhoneNumber(...).
onSolvedRecaptcha();
},
"expired-callback": function() {
// Response expired. Ask user to solve reCAPTCHA again.
// ...
}
}
);
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
'recaptcha-container',
// Optional reCAPTCHA parameters.
{
'size': 'normal',
'callback': function(response) {
// reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
// ...
onSolvedRecaptcha();
},
'expired-callback': function() {
// Response expired. Ask user to solve reCAPTCHA again.
// ...
}
});
پیشپردازش reCAPTCHA
به صورت اختیاری، میتوانید قبل از شروع ثبتنام دو مرحلهای، reCAPTCHA را پیشرندر کنید:
Web
recaptchaVerifier.render()
.then(function (widgetId) {
window.recaptchaWidgetId = widgetId;
});
Web
recaptchaVerifier.render()
.then(function(widgetId) {
window.recaptchaWidgetId = widgetId;
});
پس از اینکه render() کار خود را انجام داد، شناسه ویجت reCAPTCHA را دریافت میکنید که میتوانید از آن برای فراخوانی API مربوط به reCAPTCHA استفاده کنید:
var recaptchaResponse = grecaptcha.getResponse(window.recaptchaWidgetId);
RecaptchaVerifier این منطق را با متد verify حذف میکند، بنابراین نیازی نیست که مستقیماً متغیر grecaptcha مدیریت کنید.
ثبت عامل دوم
برای ثبت یک عامل ثانویه جدید برای یک کاربر:
کاربر را دوباره احراز هویت کنید.
از کاربر بخواهید شماره تلفن خود را وارد کند.
همانطور که در بخش قبل نشان داده شده است، تأییدکننده reCAPTCHA را مقداردهی اولیه کنید. اگر نمونه RecaptchaVerifier از قبل پیکربندی شده است، از این مرحله صرف نظر کنید:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth"; const recaptchaVerifier = new RecaptchaVerifier( getAuth(),'recaptcha-container-id', undefined);Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');یک جلسه چند عاملی برای کاربر دریافت کنید:
Web
import { multiFactor } from "firebase/auth"; multiFactor(user).getSession().then(function (multiFactorSession) { // ... });Web
user.multiFactor.getSession().then(function(multiFactorSession) { // ... })یک شیء
PhoneInfoOptionsرا با شماره تلفن کاربر و جلسه چند عاملی مقداردهی اولیه کنید:Web
// Specify the phone number and pass the MFA session. const phoneInfoOptions = { phoneNumber: phoneNumber, session: multiFactorSession };Web
// Specify the phone number and pass the MFA session. var phoneInfoOptions = { phoneNumber: phoneNumber, session: multiFactorSession };ارسال پیام تأیید به تلفن کاربر:
Web
import { PhoneAuthProvider } from "firebase/auth"; const phoneAuthProvider = new PhoneAuthProvider(auth); phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function (verificationId) { // verificationId will be needed to complete enrollment. });Web
var phoneAuthProvider = new firebase.auth.PhoneAuthProvider(); // Send SMS verification code. return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function(verificationId) { // verificationId will be needed for enrollment completion. })اگرچه الزامی نیست، اما بهتر است از قبل به کاربران اطلاع دهید که پیامک دریافت خواهند کرد و نرخهای استاندارد اعمال میشود.
اگر درخواست ناموفق بود، reCAPTCHA را مجدداً تنظیم کنید، سپس مرحله قبل را تکرار کنید تا کاربر بتواند دوباره امتحان کند. توجه داشته باشید که
verifyPhoneNumber()هنگام بروز خطا، reCAPTCHA را به طور خودکار تنظیم مجدد میکند، زیرا توکنهای reCAPTCHA فقط یک بار قابل استفاده هستند.Web
recaptchaVerifier.clear();Web
recaptchaVerifier.clear();پس از ارسال کد پیامکی، از کاربر بخواهید کد را تأیید کند:
Web
// Ask user for the verification code. Then: const cred = PhoneAuthProvider.credential(verificationId, verificationCode);Web
// Ask user for the verification code. Then: var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);یک شیء
MultiFactorAssertionرا باPhoneAuthCredentialمقداردهی اولیه کنید:Web
import { PhoneMultiFactorGenerator } from "firebase/auth"; const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);Web
var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);ثبت نام را تکمیل کنید. به صورت اختیاری، میتوانید یک نام نمایشی برای عامل دوم تعیین کنید. این برای کاربرانی که چندین عامل دوم دارند مفید است، زیرا شماره تلفن در طول فرآیند احراز هویت پنهان میشود (برای مثال، +1******1234).
Web
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. multiFactor(user).enroll(multiFactorAssertion, "My personal phone number");Web
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(multiFactorAssertion, 'My personal phone number');
کد زیر مثال کاملی از ثبت یک عامل دوم را نشان میدهد:
Web
import {
multiFactor, PhoneAuthProvider, PhoneMultiFactorGenerator,
RecaptchaVerifier, getAuth
} from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(),
'recaptcha-container-id', undefined);
multiFactor(user).getSession()
.then(function (multiFactorSession) {
// Specify the phone number and pass the MFA session.
const phoneInfoOptions = {
phoneNumber: phoneNumber,
session: multiFactorSession
};
const phoneAuthProvider = new PhoneAuthProvider(auth);
// Send SMS verification code.
return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier);
}).then(function (verificationId) {
// Ask user for the verification code. Then:
const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
// Complete enrollment.
return multiFactor(user).enroll(multiFactorAssertion, mfaDisplayName);
});
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
user.multiFactor.getSession().then(function(multiFactorSession) {
// Specify the phone number and pass the MFA session.
var phoneInfoOptions = {
phoneNumber: phoneNumber,
session: multiFactorSession
};
var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
// Send SMS verification code.
return phoneAuthProvider.verifyPhoneNumber(
phoneInfoOptions, recaptchaVerifier);
})
.then(function(verificationId) {
// Ask user for the verification code.
var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
// Complete enrollment.
return user.multiFactor.enroll(multiFactorAssertion, mfaDisplayName);
});
تبریک! شما با موفقیت یک عامل احراز هویت دوم برای یک کاربر ثبت کردید.
ورود کاربران با استفاده از فاکتور دوم
برای ورود کاربر با تأیید دو مرحلهای پیامکی:
کاربر را با اولین فاکتور خود وارد سیستم کنید، سپس خطای
auth/multi-factor-auth-requiredرا دریافت کنید. این خطا شامل یک resolver، نکاتی در مورد فاکتورهای دوم ثبت شده و یک جلسه اساسی است که تأیید میکند کاربر با اولین فاکتور با موفقیت احراز هویت شده است.برای مثال، اگر اولین فاکتور کاربر ایمیل و رمز عبور باشد:
Web
import { getAuth, signInWithEmailAndPassword, getMultiFactorResolver} from "firebase/auth"; const auth = getAuth(); signInWithEmailAndPassword(auth, email, password) .then(function (userCredential) { // User successfully signed in and is not enrolled with a second factor. }) .catch(function (error) { if (error.code == 'auth/multi-factor-auth-required') { // The user is a multi-factor user. Second factor challenge is required. resolver = getMultiFactorResolver(auth, error); // ... } else if (error.code == 'auth/wrong-password') { // Handle other errors such as wrong password. } });Web
firebase.auth().signInWithEmailAndPassword(email, password) .then(function(userCredential) { // User successfully signed in and is not enrolled with a second factor. }) .catch(function(error) { if (error.code == 'auth/multi-factor-auth-required') { // The user is a multi-factor user. Second factor challenge is required. resolver = error.resolver; // ... } else if (error.code == 'auth/wrong-password') { // Handle other errors such as wrong password. } ... });اگر اولین فاکتور کاربر یک ارائهدهندهی فدرال مانند OAuth، SAML یا OIDC باشد، پس از فراخوانی
signInWithPopup()یاsignInWithRedirect()خطا را دریافت کنید.اگر کاربر چندین عامل ثانویه ثبت کرده است، از او بپرسید که از کدام یک استفاده کند:
Web
// Ask user which second factor to use. // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber // You can get the display name via resolver.hints[selectedIndex].displayName if (resolver.hints[selectedIndex].factorId === PhoneMultiFactorGenerator.FACTOR_ID) { // User selected a phone second factor. // ... } else if (resolver.hints[selectedIndex].factorId === TotpMultiFactorGenerator.FACTOR_ID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }Web
// Ask user which second factor to use. // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber // You can get the display name via resolver.hints[selectedIndex].displayName if (resolver.hints[selectedIndex].factorId === firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) { // User selected a phone second factor. // ... } else if (resolver.hints[selectedIndex].factorId === firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }همانطور که در بخش قبل نشان داده شده است، تأییدکننده reCAPTCHA را مقداردهی اولیه کنید. اگر نمونه RecaptchaVerifier از قبل پیکربندی شده است، از این مرحله صرف نظر کنید:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth"; recaptchaVerifier = new RecaptchaVerifier(getAuth(), 'recaptcha-container-id', undefined);Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');یک شیء
PhoneInfoOptionsرا با شماره تلفن کاربر و جلسه چند عاملی مقداردهی اولیه کنید. این مقادیر در شیءresolverارسال شده به خطایauth/multi-factor-auth-requiredقرار دارند:Web
const phoneInfoOptions = { multiFactorHint: resolver.hints[selectedIndex], session: resolver.session };Web
var phoneInfoOptions = { multiFactorHint: resolver.hints[selectedIndex], session: resolver.session };ارسال پیام تأیید به تلفن کاربر:
Web
// Send SMS verification code. const phoneAuthProvider = new PhoneAuthProvider(auth); phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function (verificationId) { // verificationId will be needed for sign-in completion. });Web
var phoneAuthProvider = new firebase.auth.PhoneAuthProvider(); // Send SMS verification code. return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function(verificationId) { // verificationId will be needed for sign-in completion. })اگر درخواست ناموفق بود، reCAPTCHA را مجدداً تنظیم کنید، سپس مرحله قبل را تکرار کنید تا کاربر بتواند دوباره امتحان کند:
Web
recaptchaVerifier.clear();Web
recaptchaVerifier.clear();پس از ارسال کد پیامکی، از کاربر بخواهید کد را تأیید کند:
Web
const cred = PhoneAuthProvider.credential(verificationId, verificationCode);Web
// Ask user for the verification code. Then: var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);یک شیء
MultiFactorAssertionرا باPhoneAuthCredentialمقداردهی اولیه کنید:Web
const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);Web
var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);برای تکمیل احراز هویت ثانویه، تابع
resolver.resolveSignIn()را فراخوانی کنید. سپس میتوانید به نتیجه اصلی ورود به سیستم دسترسی پیدا کنید که شامل دادههای استاندارد مختص ارائهدهنده و اعتبارنامههای احراز هویت است:Web
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(multiFactorAssertion) .then(function (userCredential) { // userCredential will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // userCredential.additionalUserInfo will contain data related to Google // provider that the user signed in with. // - user.credential contains the Google OAuth credential. // - user.credential.accessToken contains the Google OAuth access token. // - user.credential.idToken contains the Google OAuth ID token. });Web
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(multiFactorAssertion) .then(function(userCredential) { // userCredential will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // userCredential.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. });
کد زیر یک مثال کامل از ورود به سیستم چند عاملی کاربر را نشان میدهد:
Web
import {
getAuth,
getMultiFactorResolver,
PhoneAuthProvider,
PhoneMultiFactorGenerator,
RecaptchaVerifier,
signInWithEmailAndPassword
} from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(),
'recaptcha-container-id', undefined);
const auth = getAuth();
signInWithEmailAndPassword(auth, email, password)
.then(function (userCredential) {
// User is not enrolled with a second factor and is successfully
// signed in.
// ...
})
.catch(function (error) {
if (error.code == 'auth/multi-factor-auth-required') {
const resolver = getMultiFactorResolver(auth, error);
// Ask user which second factor to use.
if (resolver.hints[selectedIndex].factorId ===
PhoneMultiFactorGenerator.FACTOR_ID) {
const phoneInfoOptions = {
multiFactorHint: resolver.hints[selectedIndex],
session: resolver.session
};
const phoneAuthProvider = new PhoneAuthProvider(auth);
// Send SMS verification code
return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
.then(function (verificationId) {
// Ask user for the SMS verification code. Then:
const cred = PhoneAuthProvider.credential(
verificationId, verificationCode);
const multiFactorAssertion =
PhoneMultiFactorGenerator.assertion(cred);
// Complete sign-in.
return resolver.resolveSignIn(multiFactorAssertion)
})
.then(function (userCredential) {
// User successfully signed in with the second factor phone number.
});
} else if (resolver.hints[selectedIndex].factorId ===
TotpMultiFactorGenerator.FACTOR_ID) {
// Handle TOTP MFA.
// ...
} else {
// Unsupported second factor.
}
} else if (error.code == 'auth/wrong-password') {
// Handle other errors such as wrong password.
}
});
Web
var resolver;
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function(userCredential) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
})
.catch(function(error) {
if (error.code == 'auth/multi-factor-auth-required') {
resolver = error.resolver;
// Ask user which second factor to use.
if (resolver.hints[selectedIndex].factorId ===
firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
var phoneInfoOptions = {
multiFactorHint: resolver.hints[selectedIndex],
session: resolver.session
};
var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
// Send SMS verification code
return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
.then(function(verificationId) {
// Ask user for the SMS verification code.
var cred = firebase.auth.PhoneAuthProvider.credential(
verificationId, verificationCode);
var multiFactorAssertion =
firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
// Complete sign-in.
return resolver.resolveSignIn(multiFactorAssertion)
})
.then(function(userCredential) {
// User successfully signed in with the second factor phone number.
});
} else if (resolver.hints[selectedIndex].factorId ===
firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) {
// Handle TOTP MFA.
// ...
} else {
// Unsupported second factor.
}
} else if (error.code == 'auth/wrong-password') {
// Handle other errors such as wrong password.
} ...
});
تبریک! شما با موفقیت با استفاده از احراز هویت چند عاملی وارد سیستم شدید.
قدم بعدی چیست؟
- کاربران چند عاملی را به صورت برنامهنویسی شده با Admin SDK مدیریت کنید.