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 с помощью ссылки электронной почты в iOS

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

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

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

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

  1. Добавить Firebase в свой проект IOS .

  2. Включите следующие стручки в вашем Podfile :

    pod 'Firebase/Auth'
    

  3. Если вы еще не подключили приложение к вашему проекту Firebase, сделать это из консоли Firebase .

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

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

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

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

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

    Быстрый

    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.url = URL(string: "https://www.example.com")
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
    actionCodeSettings.setAndroidPackageName("com.example.android",
                                             installIfNotAvailable: false, minimumVersion: "12")
    

    Цель-C

    FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
    [actionCodeSettings setURL:[NSURL URLWithString:@"https://www.example.com"]];
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = YES;
    [actionCodeSettings setIOSBundleID:[[NSBundle mainBundle] bundleIdentifier]];
    [actionCodeSettings setAndroidPackageName:@"com.example.android"
                        installIfNotAvailable:NO
                               minimumVersion:@"12"];
    

    Чтобы узнать больше о ActionCodeSettings, обратитесь к Passing государства в электронной Actions разделе.

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

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

    Быстрый

    Auth.auth().sendSignInLink(toEmail: email,
                               actionCodeSettings: actionCodeSettings) { error in
      // ...
        if let error = error {
          self.showMessagePrompt(error.localizedDescription)
          return
        }
        // 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.
        UserDefaults.standard.set(email, forKey: "Email")
        self.showMessagePrompt("Check your email for link")
        // ...
    }
    

    Цель-C

    [[FIRAuth auth] sendSignInLinkToEmail:email
                       actionCodeSettings:actionCodeSettings
                               completion:^(NSError *_Nullable error) {
      // ...
        if (error) {
          [self showMessagePrompt:error.localizedDescription];
           return;
        }
        // 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.
        [NSUserDefaults.standardUserDefaults setObject:email forKey:@"Email"];
        [self showMessagePrompt:@"Check your email for link"];
        // ...
    }];
    

Проблемы безопасности

Чтобы предотвратить использование ссылки для входа в систему в качестве непреднамеренного пользователя или на непредусмотренном устройстве, Firebase Auth требует, чтобы адрес электронной почты пользователя был предоставлен при завершении процесса входа. Для успешного входа этот адрес электронной почты должен совпадать с адресом, на который изначально была отправлена ​​ссылка для входа.

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

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

Завершение входа в мобильное приложение iOS

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

Firebase Auth использует Firebase Dynamic Links при отправке ссылки , которая предназначается , чтобы открыть в мобильном приложении. Чтобы использовать эту функцию, необходимо настроить динамические ссылки в консоли Firebase.

  1. Включить динамические ссылки Firebase:

    1. В Firebase консоли откройте раздел Динамические ссылки.
    2. Если вы еще не приняли условия использования динамических ссылок и не создали домен динамических ссылок, сделайте это сейчас.

      Если вы уже создали домен с динамическими ссылками, обратите на это внимание. Домен динамических ссылок обычно выглядит как в следующем примере:

      example.page.link

      Это значение понадобится вам при настройке приложения iOS или Android для перехвата входящей ссылки.

  2. Настройка приложений iOS:

    1. Если вы планируете обрабатывать эти ссылки из своего приложения iOS, идентификатор пакета iOS необходимо указать в настройках проекта консоли Firebase. Кроме того, необходимо указать идентификатор App Store ID и идентификатор группы разработчиков Apple.
    2. Вам также необходимо настроить свой домен обработчика действий электронной почты как связанный домен в возможностях вашего приложения. По умолчанию обработчик электронной почты действий размещен на домене , как в следующем примере:
      APP_ID.firebaseapp.com
    3. Если вы планируете распространять свое приложение на iOS версии 8 и ниже, вам нужно будет установить идентификатор пакета iOS в качестве настраиваемой схемы для входящих URL-адресов.
    4. Более подробно об этом см Получая инструкции IOS динамические ссылки .

Получив ссылку, как описано выше, убедитесь, что она предназначена для аутентификации по электронной почте, и выполните вход.

Быстрый

if Auth.auth().isSignIn(withEmailLink: link) {
        Auth.auth().signIn(withEmail: email, link: self.link) { user, error in
          // ...
        }
}

Цель-C

if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
    [[FIRAuth auth] signInWithEmail:email
                               link:link
                         completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      // ...
    }];
}

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

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

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

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

Быстрый

  let credential = EmailAuthCredential.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.link(with: credential) { authData, error in
    if (error) {
      // And error occurred during linking.
      return
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }

Цель-C

  FIRAuthCredential *credential =
      [FIREmailAuthProvider credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      linkWithCredential:credential
              completion:^(FIRAuthDataResult *_Nullable result,
                           NSError *_Nullable error) {
    if (error) {
      // And error occurred during linking.
      return;
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }];

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

Быстрый

  let credential = EmailAuthProvider.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.reauthenticate(with: credential) { authData, error in
    if (error) {
      // And error occurred during re-authentication.
      return
    }
    // The user was successfully re-authenticated.
  }

Цель-C

  FIRAuthCredential *credential =
      [FIREmailAuthCredential credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      reauthenticateWithCredential:credential
                        completion:^(FIRAuthDataResult *_Nullable result,
                                     NSError *_Nullable error) {
    if (error) {
      // And error occurred during re-authentication
      return;
    }
    // The user was successfully re-authenticated.
  }];

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

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

Быстрый

 // After asking the user for their email.
 Auth.auth().fetchSignInMethods(forEmail: email) { signInMethods, error in
   // This returns the same array as fetchProviders(forEmail:completion:) 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 (error) {
     // Handle error case.
   }
   if (!signInMethods.contains(EmailPasswordAuthSignInMethod)) {
     // User can sign in with email/password.
   }
   if (!signInMethods.contains(EmailLinkAuthSignInMethod)) {
     // User can sign in with email/link.
   }
 }

Цель-C

 // After asking the user for their email.
 [FIRAuth auth] fetchSignInMethodsForEmail:email
                                completion:^(NSArray *_Nullable signInMethods,
                                             NSError *_Nullable error) {
   // 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 (error) {
     // Handle error case.
   }
   if (![signInMethods containsObject:FIREmailPasswordAuthSignInMethod]) {
     // User can sign in with email/password.
   }
   if (![signInMethods containsObject:FIREmailLinkAuthSignInMethod]) {
     // User can sign in with email/link.
   }
 }];

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

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

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

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

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

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

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

Быстрый

    let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}
  

Цель-C

    NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

Вы также можете добавить код обработки ошибок для всего диапазона ошибок аутентификации. См ошибки Берите .