Вы можете использовать Firebase Authentication для входа пользователя, отправив SMS-сообщение на его телефон. Пользователь авторизуется, используя одноразовый код, содержащийся в SMS-сообщении.
Самый простой способ добавить вход по номеру телефона в приложение — использовать FirebaseUI , который включает в себя встроенный виджет входа, реализующий различные способы входа по номеру телефона, а также вход по паролю и федеративный вход. В этом документе описывается, как реализовать процесс входа по номеру телефона с помощью Firebase SDK.
Прежде чем начать
Если вы еще этого не сделали, скопируйте фрагмент инициализации из консоли Firebase в свой проект, как описано в разделе Добавление Firebase в ваш проект JavaScript .Проблемы безопасности
Аутентификация только по номеру телефона, хоть и удобна, менее безопасна, чем другие доступные методы, поскольку владение номером телефона может легко передаваться от одного пользователя другому. Кроме того, на устройствах с несколькими профилями любой пользователь, принимающий SMS, может войти в учётную запись, используя номер телефона устройства.
Если вы используете в своем приложении вход по номеру телефона, вам следует предложить его наряду с более безопасными методами входа и проинформировать пользователей о недостатках безопасности при использовании входа по номеру телефона.
Включите вход по номеру телефона для вашего проекта Firebase
Чтобы авторизовать пользователей с помощью SMS, необходимо сначала включить метод входа по номеру телефона для вашего проекта Firebase:
- В консоли Firebase откройте раздел «Аутентификация» .
- На странице «Способ входа» включите способ входа по номеру телефона .
- Необязательно : на странице настроек задайте политику регионов, в которых вы хотите разрешить или запретить отправку SMS-сообщений. Настройка политики региона для SMS поможет защитить ваши приложения от злоупотреблений SMS.
- На той же странице, если домен, на котором будет размещено ваше приложение, не указан в разделе «Домены перенаправления OAuth» , добавьте свой домен. Обратите внимание, что localhost не допускается в качестве размещенного домена для телефонной аутентификации.
Настройте верификатор reCAPTCHA
Прежде чем вы сможете авторизовать пользователей по их номерам телефонов, необходимо настроить верификатор reCAPTCHA в Firebase. Firebase использует reCAPTCHA для предотвращения злоупотреблений, например, гарантируя, что запрос на проверку номера телефона поступает с одного из разрешённых доменов вашего приложения.
Вам не нужно вручную настраивать клиент reCAPTCHA; при использовании объекта RecaptchaVerifier
из Firebase SDK Firebase автоматически создает и обрабатывает все необходимые клиентские ключи и секреты.
Объект RecaptchaVerifier
поддерживает невидимую reCAPTCHA , которая часто может верифицировать пользователя, не требуя от него никаких действий, а также виджет reCAPTCHA, который всегда требует взаимодействия с пользователем для успешного завершения.
Базовую отрисовку reCAPTCHA можно локализовать в соответствии с предпочтениями пользователя, обновив код языка в экземпляре Auth перед её отрисовкой. Вышеуказанная локализация также будет применена к отправляемому пользователю SMS-сообщению с кодом подтверждения.
Web
import { getAuth } from "firebase/auth"; const auth = getAuth(); auth.languageCode = 'it'; // To apply the default browser preference instead of explicitly setting it. // auth.useDeviceLanguage();
Web
firebase.auth().languageCode = 'it'; // To apply the default browser preference instead of explicitly setting it. // firebase.auth().useDeviceLanguage();
Использовать невидимую reCAPTCHA
Чтобы использовать невидимую reCAPTCHA, создайте объект RecaptchaVerifier
с параметром size
равным invisible
, и укажите идентификатор кнопки, которая отправляет форму входа. Например:
Web
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', { 'size': 'invisible', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. onSignInSubmit(); } });
Web
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', { 'size': 'invisible', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. onSignInSubmit(); } });
Используйте виджет reCAPTCHA
Чтобы использовать видимый виджет reCAPTCHA, создайте на странице элемент, содержащий виджет, а затем создайте объект RecaptchaVerifier
, указав при этом идентификатор контейнера. Например:
Web
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});
Web
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
Необязательно: укажите параметры reCAPTCHA
При желании вы можете задать функции обратного вызова для объекта RecaptchaVerifier
, которые будут вызываться, когда пользователь решает reCAPTCHA или срок действия reCAPTCHA истекает до того, как пользователь отправит форму:
Web
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', { 'size': 'normal', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. // ... }, 'expired-callback': () => { // Response expired. Ask user to solve reCAPTCHA again. // ... } });
Web
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', { 'size': 'normal', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. // ... }, 'expired-callback': () => { // Response expired. Ask user to solve reCAPTCHA again. // ... } });
Необязательно: предварительно визуализируйте reCAPTCHA.
Если вы хотите предварительно отобразить reCAPTCHA перед отправкой запроса на вход, вызовите render
:
Web
recaptchaVerifier.render().then((widgetId) => { window.recaptchaWidgetId = widgetId; });
Web
recaptchaVerifier.render().then((widgetId) => { window.recaptchaWidgetId = widgetId; });
После завершения render
вы получите идентификатор виджета reCAPTCHA, который можно использовать для совершения вызовов API reCAPTCHA :
Web
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
Web
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
Отправить проверочный код на телефон пользователя
Чтобы инициировать вход по номеру телефона, предоставьте пользователю интерфейс, предлагающий ему указать свой номер телефона, а затем вызовите signInWithPhoneNumber
, чтобы запросить у Firebase отправку кода аутентификации на телефон пользователя по SMS:
Получите номер телефона пользователя.
Юридические требования различаются, но в качестве наилучшей практики и для того, чтобы сформировать у пользователей определенные ожидания, вам следует сообщить им, что при использовании входа с телефона им может быть отправлено SMS-сообщение для подтверждения, и будут применяться стандартные тарифы.
- Вызовите
signInWithPhoneNumber
, передав ему номер телефона пользователя иRecaptchaVerifier
который вы создали ранее.ЕслиWeb
import { getAuth, signInWithPhoneNumber } from "firebase/auth"; const phoneNumber = getPhoneNumberFromUserInput(); const appVerifier = window.recaptchaVerifier; const auth = getAuth(); signInWithPhoneNumber(auth, phoneNumber, appVerifier) .then((confirmationResult) => { // SMS sent. Prompt user to type the code from the message, then sign the // user in with confirmationResult.confirm(code). window.confirmationResult = confirmationResult; // ... }).catch((error) => { // Error; SMS not sent // ... });
Web
const phoneNumber = getPhoneNumberFromUserInput(); const appVerifier = window.recaptchaVerifier; firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier) .then((confirmationResult) => { // SMS sent. Prompt user to type the code from the message, then sign the // user in with confirmationResult.confirm(code). window.confirmationResult = confirmationResult; // ... }).catch((error) => { // Error; SMS not sent // ... });
signInWithPhoneNumber
приводит к ошибке, сбросьте reCAPTCHA, чтобы пользователь мог повторить попытку:grecaptcha.reset(window.recaptchaWidgetId); // Or, if you haven't stored the widget ID: window.recaptchaVerifier.render().then(function(widgetId) { grecaptcha.reset(widgetId); });
Метод signInWithPhoneNumber
отправляет пользователю запрос reCAPTCHA и, если пользователь проходит его, запрашивает у Firebase Authentication отправку SMS-сообщения с кодом подтверждения на телефон пользователя.
Авторизуйте пользователя с помощью проверочного кода.
После успешного вызова signInWithPhoneNumber
предложите пользователю ввести код подтверждения, полученный по SMS. Затем авторизуйте пользователя, передав код методу confirm
объекта ConfirmationResult
, который был передан обработчику выполнения signInWithPhoneNumber
(то есть его блоку then
). Например:
Web
const code = getCodeFromUserInput(); confirmationResult.confirm(code).then((result) => { // User signed in successfully. const user = result.user; // ... }).catch((error) => { // User couldn't sign in (bad verification code?) // ... });
Web
const code = getCodeFromUserInput(); confirmationResult.confirm(code).then((result) => { // User signed in successfully. const user = result.user; // ... }).catch((error) => { // User couldn't sign in (bad verification code?) // ... });
Если вызов для confirm
прошел успешно, пользователь успешно вошел в систему.
Получить промежуточный объект AuthCredential
Если вам нужно получить объект AuthCredential
для учетной записи пользователя, передайте код проверки из результата подтверждения и код проверки в PhoneAuthProvider.credential
вместо вызова confirm
:
var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);
Затем вы можете войти в систему, используя учетные данные пользователя:
firebase.auth().signInWithCredential(credential);
Тест с вымышленными номерами телефонов
Вы можете настроить вымышленные номера телефонов для разработки через консоль Firebase . Тестирование с вымышленными номерами телефонов даёт следующие преимущества:
- Протестируйте аутентификацию по номеру телефона, не исчерпывая квоту использования.
- Проверьте аутентификацию по номеру телефона без отправки реального SMS-сообщения.
- Проводите последовательные тесты с одним и тем же номером телефона, не подвергаясь ограничениям. Это минимизирует риск отклонения при проверке в App Store, если проверяющий случайно использует один и тот же номер телефона для тестирования.
- Легкое тестирование в средах разработки без дополнительных усилий, например, возможность разработки в симуляторе iOS или эмуляторе Android без Google Play Services.
- Пишите интеграционные тесты, не опасаясь проверок безопасности, которые обычно применяются к реальным телефонным номерам в производственной среде.
Вымышленные номера телефонов должны соответствовать следующим требованиям:
- Убедитесь, что вы используете действительно вымышленные номера телефонов, а не существующие. Firebase Authentication не позволяет использовать существующие номера телефонов реальных пользователей в качестве тестовых. Один из вариантов — использовать номера с префиксом 555 в качестве тестовых номеров в США, например: +1 650-555-3434.
- Номера телефонов должны быть правильно отформатированы с учётом длины и других ограничений. Они пройдут ту же проверку, что и реальные номера телефонов пользователей.
- Вы можете добавить до 10 номеров телефонов для разработки.
- Используйте тестовые номера телефонов/коды, которые трудно угадать, и регулярно меняйте их.
Создайте вымышленные номера телефонов и коды подтверждения
- В консоли Firebase откройте раздел «Аутентификация» .
- На вкладке «Способ входа» включите опцию «Поставщик телефонной связи», если вы этого еще не сделали.
- Откройте меню «Телефонные номера для тестирования аккордеона».
- Укажите номер телефона, который вы хотите проверить, например: +1 650-555-3434 .
- Укажите 6-значный проверочный код для этого конкретного номера, например: 654321 .
- Добавьте номер. При необходимости вы можете удалить номер телефона и его код, наведя курсор на соответствующую строку и нажав на значок корзины.
Ручное тестирование
Вы можете сразу начать использовать вымышленный номер телефона в своём приложении. Это позволит проводить ручное тестирование на этапах разработки, не сталкиваясь с проблемами квот или ограничениями. Вы также можете тестировать приложение непосредственно в симуляторе iOS или эмуляторе Android без установленных сервисов Google Play.
Когда вы указываете вымышленный номер телефона и отправляете код подтверждения, SMS-сообщение не отправляется. Вместо этого вам необходимо указать ранее настроенный код подтверждения для завершения входа.
После завершения входа в систему создаётся пользователь Firebase с этим номером телефона. Этот пользователь обладает теми же характеристиками и свойствами, что и пользователь с реальным номером телефона, и может получать доступ к Realtime Database / Cloud Firestore и другим сервисам таким же образом. Идентификационный токен, созданный в ходе этого процесса, имеет ту же подпись, что и пользователь с реальным номером телефона.
Другой вариант — установить тестовую роль с помощью пользовательских утверждений для этих пользователей, чтобы отличать их от поддельных пользователей, если вы хотите еще больше ограничить доступ.
Интеграционное тестирование
Помимо ручного тестирования, Firebase Authentication предоставляет API, помогающие писать интеграционные тесты для проверки аутентификации по телефону. Эти API отключают верификацию приложений, отключая требование reCAPTCHA в веб-версии и скрытых push-уведомлениях в iOS. Это делает возможным и упрощает автоматическое тестирование в этих процессах. Кроме того, они помогают тестировать процессы мгновенной верификации на Android.
В веб-версии установите для appVerificationDisabledForTesting
значение true
перед рендерингом firebase.auth.RecaptchaVerifier
. Это автоматически обработает reCAPTCHA, позволяя вам передавать номер телефона без необходимости вручную её решать. Обратите внимание, что даже если reCAPTCHA отключена, использование невымышленного номера телефона всё равно не приведёт к завершению входа. С этим API можно использовать только вымышленные номера телефонов.
// Turn off phone auth app verification. firebase.auth().settings.appVerificationDisabledForTesting = true; var phoneNumber = "+16505554567"; var testVerificationCode = "123456"; // This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true. // This will resolve after rendering without app verification. var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container'); // signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake // reCAPTCHA response. firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier) .then(function (confirmationResult) { // confirmationResult can resolve with the fictional testVerificationCode above. return confirmationResult.confirm(testVerificationCode) }).catch(function (error) { // Error; SMS not sent // ... });
Видимые и невидимые фиктивные верификаторы приложений reCAPTCHA ведут себя по-разному, если отключена проверка приложений:
- Видимая reCAPTCHA : При рендеринге видимой reCAPTCHA через
appVerifier.render()
она автоматически разрешается с задержкой в доли секунды. Это эквивалентно нажатию пользователем кнопки reCAPTCHA сразу после рендеринга. Ответ reCAPTCHA истечёт через некоторое время, а затем автоматически разрешится снова. - Невидимая reCAPTCHA : Невидимая reCAPTCHA не разрешается автоматически при рендеринге, а вместо этого делает это при вызове
appVerifier.verify()
или при нажатии на якорь кнопки reCAPTCHA с задержкой в доли секунды. Аналогично, ответ истекает через некоторое время и автоматически разрешается только после вызоваappVerifier.verify()
или при повторном нажатии на якорь кнопки reCAPTCHA.
При каждом разрешении фиктивной reCAPTCHA соответствующая функция обратного вызова срабатывает, как и ожидалось, с поддельным ответом. Если также указана функция обратного вызова, определяющая срок действия, она сработает по истечении срока действия.
Следующие шаги
После первого входа пользователя в систему создаётся новая учётная запись, которая привязывается к учётным данным, использованным при входе (имя пользователя и пароль, номер телефона или информация о поставщике аутентификации). Эта новая учётная запись хранится в вашем проекте Firebase и может использоваться для идентификации пользователя в каждом приложении проекта, независимо от способа входа.
В ваших приложениях рекомендуемый способ узнать статус аутентификации пользователя — установить наблюдателя для объекта
Auth
. После этого вы сможете получить основную информацию о профиле пользователя из объектаUser
. См. раздел Управление пользователями .В правилах безопасности Firebase Realtime Database и Cloud Storage вы можете получить уникальный идентификатор вошедшего в систему пользователя из переменной
auth
и использовать его для управления данными, к которым пользователь может получить доступ.
Вы можете разрешить пользователям входить в ваше приложение с использованием нескольких поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.
Чтобы выйти из системы пользователя, вызовите signOut
:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });