С помощью Firebase Authentication можно авторизовать пользователя, отправив ему электронное письмо со ссылкой, по которой он сможет войти в систему. При этом также проверяется адрес электронной почты пользователя.
Вход в систему по электронной почте имеет множество преимуществ:
- Простая регистрация и авторизация.
- Снижается риск повторного использования паролей в разных приложениях, что может подорвать безопасность даже тщательно подобранных паролей.
- Возможность аутентифицировать пользователя, одновременно проверяя, является ли он законным владельцем адреса электронной почты.
- Для входа в систему пользователю достаточно иметь доступный адрес электронной почты. Наличие номера телефона или аккаунта в социальных сетях не требуется.
- Пользователь может безопасно войти в систему без необходимости вводить (или запоминать) пароль, что может быть неудобно на мобильном устройстве.
- Существующий пользователь, ранее входивший в систему с помощью адреса электронной почты (пароля или федеративной аутентификации), может быть переведен на вход только с помощью адреса электронной почты. Например, пользователь, забывший свой пароль, может войти в систему без необходимости его сброса.
Прежде чем начать
Если вы еще этого не сделали, скопируйте фрагмент кода инициализации из консоли Firebase в свой проект, как описано в разделе «Добавление Firebase в ваш проект JavaScript» .
Включите вход по ссылке из электронной почты для вашего проекта Firebase.
Для авторизации пользователей по ссылке из электронной почты необходимо сначала включить в вашем проекте Firebase поставщика услуг электронной почты и метод авторизации по ссылке из электронной почты:
В консоли Firebase перейдите в раздел Безопасность > Аутентификация .
На вкладке «Способ входа» включите способ входа по электронной почте/паролю . Обратите внимание, что для использования входа по ссылке из электронного письма необходимо включить вход по электронной почте/паролю.
В этом же разделе включите поставщик услуг авторизации по ссылке электронной почты (вход без пароля) .
Нажмите « Сохранить ».
Отправить ссылку для аутентификации на электронный адрес пользователя.
Для запуска процесса аутентификации предоставьте пользователю интерфейс, в котором ему будет предложено указать свой адрес электронной почты, а затем вызовите функцию sendSignInLinkToEmail , чтобы запросить у Firebase отправку ссылки для аутентификации на электронную почту пользователя.
Создайте объект
ActionCodeSettings, который предоставит Firebase инструкции по созданию ссылки в электронном письме. Установите следующие поля:url: Прямая ссылка для встраивания и любые дополнительные данные, которые необходимо передать. Если вы еще этого не сделали, добавьте свой домен в список разрешенных доменов:В консоли Firebase перейдите в раздел Безопасность > Аутентификация > Вкладка Настройки .
В разделе «Авторизованные домены» нажмите «Добавить домен» и добавьте свой домен.
-
androidиios: Помогает Firebase Authentication определить, следует ли создавать веб-ссылку или мобильную ссылку, открываемую на устройстве Android или Apple. -
handleCodeInApp: Установите значение true. Операция входа в систему всегда должна выполняться в приложении, в отличие от других действий, выполняемых вне приложения (сброс пароля и подтверждение электронной почты). Это связано с тем, что по завершении процесса ожидается, что пользователь войдет в систему, и его состояние аутентификации сохранится в приложении. -
linkDomain: Если для проекта определены пользовательские домены ссылок Hosting , укажите, какой из них следует использовать при открытии ссылки указанным мобильным приложением. В противном случае автоматически выбирается домен по умолчанию (например,PROJECT_ID .firebaseapp.com). dynamicLinkDomain: Устарело. Не указывайте этот параметр.Web
const actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, // The domain must be configured in Firebase Hosting and owned by the project. linkDomain: 'custom-domain.com' };
Web
var actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, dynamicLinkDomain: 'example.page.link' };
Чтобы узнать больше о
ActionCodeSettings, обратитесь к разделу «Передача состояния в действиях с электронной почтой» .Запросите у пользователя его адрес электронной почты.
Отправьте ссылку для аутентификации на электронную почту пользователя и сохраните адрес электронной почты на случай, если пользователь завершит вход через электронную почту на том же устройстве.
Web
import { getAuth, sendSignInLinkToEmail } from "firebase/auth"; const auth = getAuth(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; // ... });
Web
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { var errorCode = error.code; var errorMessage = error.message; // ... });
Завершите вход, используя ссылку из электронного письма.
Вопросы безопасности
Чтобы предотвратить использование ссылки для входа в систему для непреднамеренного пользователя или на непреднамеренном устройстве, Firebase Auth требует указания адреса электронной почты пользователя при завершении процесса входа в систему. Для успешного входа в систему этот адрес электронной почты должен совпадать с адресом, на который изначально была отправлена ссылка для входа.
Вы можете оптимизировать этот процесс для пользователей, которые открывают ссылку для входа на том же устройстве, на котором запрашивают ссылку, сохранив их адрес электронной почты локально — например, с помощью localStorage или cookie — при отправке электронного письма с подтверждением входа. Затем используйте этот адрес для завершения процесса. Не передавайте адрес электронной почты пользователя в параметры URL-адреса перенаправления и не используйте его повторно, так как это может привести к внедрению сессий.
После завершения авторизации все предыдущие неподтвержденные способы входа будут удалены, а все существующие сессии будут аннулированы. Например, если кто-то ранее создал неподтвержденную учетную запись с тем же адресом электронной почты и паролем, пароль пользователя будет удален, чтобы предотвратить повторный вход в систему злоумышленника, который заявил о своем праве собственности и создал эту неподтвержденную учетную запись, используя тот же адрес электронной почты и пароль.
Также убедитесь, что в рабочей среде используется URL-адрес с протоколом HTTPS, чтобы избежать потенциального перехвата вашей ссылки промежуточными серверами.
Завершение авторизации на веб-странице
Формат ссылки в электронном письме совпадает с форматом, используемым для действий с электронной почтой вне системы (подтверждение электронной почты, сброс пароля и аннулирование изменения адреса электронной почты). Firebase Auth упрощает эту проверку, предоставляя API isSignInWithEmailLink для проверки того, является ли ссылка ссылкой для входа в систему по электронной почте.
Для завершения авторизации на целевой странице вызовите signInWithEmailLink , указав адрес электронной почты пользователя и ссылку на электронное письмо с одноразовым кодом.
Web
import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; // Confirm the link is a sign-in with email link. const auth = getAuth(); if (isSignInWithEmailLink(auth, window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. let email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. signInWithEmailLink(auth, email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user by importing getAdditionalUserInfo // and calling it with result: // getAdditionalUserInfo(result) // You can access the user's profile via: // getAdditionalUserInfo(result)?.profile // You can check if the user is new or existing: // getAdditionalUserInfo(result)?.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Web
// Confirm the link is a sign-in with email link. if (firebase.auth().isSignInWithEmailLink(window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. var email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. firebase.auth().signInWithEmailLink(email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user via result.user // Additional user info profile not available via: // result.additionalUserInfo.profile == null // You can check if the user is new or existing: // result.additionalUserInfo.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Завершение входа в мобильное приложение
Firebase Authentication использует Firebase Hosting для отправки ссылки из электронного письма на мобильное устройство. Для завершения авторизации через мобильное приложение необходимо настроить его таким образом, чтобы оно обнаруживало входящую ссылку, анализировало лежащую в её основе прямую ссылку, а затем завершало авторизацию так же, как это делается через веб-интерфейс.
Чтобы узнать больше о том, как обрабатывать вход в систему с помощью ссылки из электронной почты в приложении Android, обратитесь к руководству по Android .
Чтобы узнать больше о том, как обрабатывать вход в систему с помощью ссылки из электронной почты в приложении Apple, обратитесь к руководству по платформам Apple .
Связывание/повторная аутентификация с помощью ссылки на электронную почту.
Вы также можете связать этот метод аутентификации с существующим пользователем. Например, пользователь, ранее прошедший аутентификацию у другого поставщика, например, по номеру телефона, может добавить этот метод входа в систему к своей существующей учетной записи.
Разница будет заключаться во второй половине операции:
Web
import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. firebase.auth().currentUser.linkWithCredential(credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Это также можно использовать для повторной аутентификации пользователя, получившего ссылку в электронном письме, перед выполнением конфиденциальной операции.
Web
import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. const auth = getAuth(); reauthenticateWithCredential(auth.currentUser, credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. firebase.auth().currentUser.reauthenticateWithCredential(credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
Однако, поскольку процесс может завершиться на другом устройстве, где исходный пользователь не авторизован, он может не завершиться. В этом случае пользователю может быть показано сообщение об ошибке, чтобы заставить его открыть ссылку на том же устройстве. В ссылку можно передать информацию о типе операции и идентификаторе пользователя (uid).
Устарело: Различение пароля электронной почты и ссылки в электронном письме.
Если вы создали свой проект 15 сентября 2023 года или позже, защита от перечисления адресов электронной почты включена по умолчанию. Эта функция повышает безопасность учетных записей пользователей вашего проекта, но отключает метод fetchSignInMethodsForEmail() , который мы ранее рекомендовали для реализации потоков, основанных на идентификаторах.
Хотя вы можете отключить защиту от перечисления адресов электронной почты для своего проекта, мы не рекомендуем этого делать.
Для получения более подробной информации см. документацию по защите от перечисления адресов электронной почты .
Шаблон электронного письма по умолчанию для входа по ссылке
В шаблоне электронного письма по умолчанию в тему и текст письма включается метка времени, чтобы последующие письма не сворачивались в одну цепочку, а ссылка не скрывалась .
Этот шаблон применим к следующим языкам:
| Код | Язык |
|---|---|
| ар | арабский |
| zh-CN | Китайский (упрощенный) |
| zh-TW | Китайский (традиционный) |
| нл | Голландский |
| эн | Английский |
| эн-ГБ | Английский (Великобритания) |
| фр | Французский |
| де | немецкий |
| идентификатор | индонезийский |
| это | итальянского |
| джа | японский |
| ко | корейский |
| пл | польский |
| пт-БР | Португальский (Бразилия) |
| пт-ПТ | Португальский (Португалия) |
| ру | Русский |
| эс | испанский |
| es-419 | Испанский (Латинская Америка) |
| т | Тайский |
Следующие шаги
После первого входа пользователя в систему создается новая учетная запись, которая связывается с учетными данными — то есть именем пользователя и паролем, номером телефона или информацией о поставщике аутентификации, — которые пользователь использовал для входа. Эта новая учетная запись хранится как часть вашего проекта 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. });