Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Аутентификация с Firebase с помощью ссылки электронной почты в JavaScript

Вы можете использовать Firebase Authentication для входа пользователя в систему, отправив ему электронное письмо, содержащее ссылку, которую они могут щелкнуть для входа. В процессе также проверяется адрес электронной почты пользователя.

Вход по электронной почте дает множество преимуществ:

  • Низкое трение при регистрации и входе в систему.
  • Снижение риска повторного использования паролей в приложениях, что может подорвать безопасность даже хорошо подобранных паролей.
  • Возможность аутентифицировать пользователя, одновременно подтверждая, что пользователь является законным владельцем адреса электронной почты.
  • Пользователю требуется только доступная учетная запись электронной почты для входа в систему. Не требуется владение номером телефона или учетной записью в социальной сети.
  • Пользователь может безопасно войти в систему без необходимости вводить (или запоминать) пароль, что может быть громоздким на мобильном устройстве.
  • Существующего пользователя, который ранее входил в систему с идентификатором электронной почты (паролем или федеративным), можно обновить, чтобы войти в систему только с помощью электронной почты. Например, пользователь, забывший свой пароль, может войти в систему, не сбрасывая пароль.

Прежде чем вы начнете

Если вы еще не сделали, скопируйте инициализации фрагмент из Firebase консоли для вашего проекта , как описано в Add Firebase к вашему проекту JavaScript .

Чтобы войти в систему с помощью ссылки электронной почты, вы должны сначала включить метод входа в систему с помощью поставщика электронной почты и ссылки электронной почты для своего проекта Firebase:

  1. В Firebase консоли откройте раздел Auth.
  2. На вкладке Вход в метод, позволяют поставщику Email / пароль. Обратите внимание, что вход по электронной почте / паролю должен быть включен, чтобы использовать ссылку для входа по электронной почте.
  3. В том же разделе включить ссылку по электронной почте ( без пароля входа в) регистрации в методе.
  4. Нажмите кнопку Сохранить.

Для того, чтобы инициировать процесс аутентификации, предоставить пользователю интерфейс , который предлагает пользователю предоставить свой адрес электронной почты , а затем вызвать sendSignInLinkToEmail на запрос , что Firebase отправить ссылку аутентификации электронной почты пользователя.

  1. Построить ActionCodeSettings объект, который обеспечивает Firebase с инструкциями о том, как построить ссылку по электронной почте. Задайте следующие поля:

    • url : Глубинная ссылка врезать и любое дополнительное состояние, которые передаются вместе. Домен ссылки должен быть добавлен в список авторизованных доменов консоли Firebase, который можно найти, перейдя на вкладку Метод входа (Аутентификация -> Метод входа).
    • android и ios : Приложения для использования при регистрации в ссылке открывается на устройстве Android или IOS. Узнайте больше о том , как настроить Firebase Dynamic Links для открытых ссылок по электронной почте действия с помощью мобильных приложений.
    • handleCodeInApp : Установите верно. Операция входа всегда должна выполняться в приложении, в отличие от других внешних действий с электронной почтой (сброс пароля и проверка электронной почты). Это связано с тем, что в конце потока ожидается, что пользователь войдет в систему, а его состояние аутентификации сохраняется в приложении.
    • dynamicLinkDomain : Если несколько доменов пользовательских динамически подключаемых определены для проекта, указать , какой из них использовать , когда канал будет открыт с помощью указанного мобильного приложения (например, example.page.link ). В противном случае автоматически выбирается первый домен.

      Веб-версия 9

      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'
        },
        dynamicLinkDomain: 'example.page.link'
      };

      Веб-версия 8

      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, обратитесь к Passing государства в электронной Actions разделе.

  2. Спросите у пользователя их адрес электронной почты.

  3. Отправьте ссылку для аутентификации на электронную почту пользователя и сохраните электронную почту пользователя на случай, если пользователь завершит вход по электронной почте на том же устройстве.

    Веб-версия 9

    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;
        // ...
      });

    Веб-версия 8

    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 упрощает эту проверку, предоставляя isSignInWithEmailLink API , чтобы проверить ссылку , является ли вход с помощью электронной связи.

Для завершения регистрации в целевой странице, вызовите signInWithEmailLink с электронной почтой пользователя и фактической ссылкой электронной почты , содержащей одноразовый кодом.

Веб-версия 9

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 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.
    });
}

Веб-версия 8

// 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 использует динамические ссылки Firebase для отправки ссылки электронной почты на мобильное устройство. Для завершения входа через мобильное приложение приложение должно быть настроено для обнаружения входящей ссылки приложения, анализа базовой глубинной ссылки и затем завершения входа в систему, как это делается через веб-поток.

Чтобы узнать больше о том , как обрабатывать вход с помощью электронной почты ссылки в Android приложении, обратитесь к руководству Android .

Чтобы узнать , как более о том , как обрабатывать вход с помощью электронной связи в приложении IOS, обратитесь к руководству IOS .

Вы также можете связать этот метод аутентификации с существующим пользователем. Например, пользователь, ранее прошедший аутентификацию у другого поставщика, например по номеру телефона, может добавить этот метод входа в свою существующую учетную запись.

Разница будет во второй половине операции:

Веб-версия 9

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.
  });

Веб-версия 8

// 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.
  });

Это также можно использовать для повторной аутентификации пользователя электронной почты перед запуском конфиденциальной операции.

Веб-версия 9

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.
  });

Веб-версия 8

// 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.

В случае , если вы поддерживаете как пароль и ссылку на основе вход с помощью электронной почты, чтобы дифференцировать метод входа в для пользователя пароль / ссылки, используйте fetchSignInMethodsForEmail . Это полезно для потоков с первым идентификатором, когда пользователя сначала просят указать свой адрес электронной почты, а затем ему предоставляется метод входа:

Веб-версия 9

import { getAuth, fetchSignInMethodsForEmail, EmailAuthProvider} from "firebase/auth";

// After asking the user for their email.
const email = window.prompt('Please provide your email');

const auth = getAuth();
fetchSignInMethodsForEmail(auth, email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Веб-версия 8

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Как описано выше , по электронной почте / пароль и адрес электронной / ссылки считаются одинаковыми firebase.auth.EmailAuthProvider (такой же PROVIDER_ID ) с различными методами входа.

Следующие шаги

После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, связанная с учетными данными, то есть с именем пользователя и паролем, номером телефона или информацией о провайдере аутентификации, с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении в вашем проекте, независимо от того, как пользователь входит в систему.

  • В приложениях, рекомендуемый способ узнать статус аутентификации вашего пользователя, чтобы установить наблюдатель на Auth объекте. Вы можете получить основную информацию о профиле пользователя от User объекта. См Управление пользователей .

  • В вашей базе данных в реальном времени и Firebase Cloud Storage правил безопасности , вы можете получить подписанный в уникальном пользователя идентификатор пользователя из auth переменной и использовать его , чтобы контролировать , какие данные пользователь заходит может.

Вы можете позволить пользователям входить в ваше приложение с помощью нескольких поставщиков проверки подлинности с помощью ссылки AUTH учетных данных поставщика к существующему учетной записи пользователя.

Чтобы выйти пользователь, вызовите signOut :

Веб-версия 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Веб-версия 8

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});