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

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

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

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

Прежде чем начать

Используйте Swift Package Manager для установки и управления зависимостями Firebase.

  1. В Xcode, открыв проект приложения, перейдите в меню File > Add Packages .
  2. При появлении запроса добавьте репозиторий Firebase Apple Platforms SDK:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Выберите библиотеку Firebase Authentication .
  5. Добавьте флаг -ObjC в раздел «Другие флаги компоновщика» в настройках сборки вашей целевой системы.
  6. После завершения Xcode автоматически начнет разрешение и загрузку ваших зависимостей в фоновом режиме.

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

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

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

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

    • url : Прямая ссылка для встраивания и любые дополнительные данные, которые необходимо передать. Домен ссылки должен быть внесен в белый список разрешенных доменов в консоли Firebase, который можно найти на вкладке «Метод входа» (Аутентификация -> Метод входа).
    • iOSBundleID и androidPackageName : помогают Firebase Authentication определить, следует ли создавать веб-ссылку или мобильную ссылку, открываемую на устройстве Android или Apple.
    • handleCodeInApp : Установите значение true. Операция входа в систему всегда должна выполняться в приложении, в отличие от других действий, выполняемых вне приложения (сброс пароля и подтверждение электронной почты). Это связано с тем, что по завершении процесса ожидается, что пользователь войдет в систему, и его состояние аутентификации сохранится в приложении.
    • linkDomain : Если для проекта определены пользовательские домены ссылок Hosting , укажите, какой из них следует использовать при открытии ссылки указанным мобильным приложением. В противном случае автоматически выбирается домен по умолчанию (например, PROJECT_ID .firebaseapp.com ).
    • dynamicLinkDomain : Устарело. Не указывайте этот параметр.

    Быстрый

    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")

    Objective-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 , обратитесь к разделу «Передача состояния в действиях с электронной почтой» .

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

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

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

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

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

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

Настройка Firebase Hosting

При создании и отправке ссылки, предназначенной для открытия в мобильном приложении, Firebase Authentication использует домены Firebase Hosting . Для вас уже настроен домен Firebase Hosting по умолчанию.

  1. Настройка доменов Firebase Hosting :

    В консоли Firebase откройте раздел «Хостинг» .

    • Если вы хотите использовать домен по умолчанию для ссылки в электронном письме, открывающейся в мобильных приложениях, перейдите на свой основной сайт и запишите домен Hosting по умолчанию. Домен Hosting по умолчанию обычно выглядит так: PROJECT_ID .firebaseapp.com .

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

    • Если вы хотите использовать собственный домен для ссылки в электронном письме, вы можете зарегистрировать его в Firebase Hosting и использовать его в качестве домена для ссылки.

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

    Вам потребуется настроить выбранный домен как ассоциированный домен для ссылок приложения. Чтобы настроить права доступа в вашем приложении, откройте вкладку «Подписание и возможности» целевого приложения в Xcode и добавьте домены Firebase Hosting из предыдущего шага в раздел «Ассоциированные домены». Если используется домен Firebase Hosting по умолчанию, это будет... applinks: PROJECT_ID .firebaseapp.com .

    Дополнительную информацию см. в разделе «Поддержка связанных доменов» на сайте документации Apple.

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

Быстрый

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

Objective-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.
  }

Objective-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.
  }

Objective-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).

До версии Firebase Authentication iOS SDK v11.8.0 функция входа по ссылке из электронного письма использовала Firebase Dynamic Links для открытия ссылок входа в нужном приложении. Эти ссылки для подтверждения устарели, поскольку Firebase Dynamic Links будет отключен 25 августа 2025 года .

Если ваше приложение использует ссылки старого образца, вам следует перевести его на новую систему на основе Firebase Hosting .

Если вы создали свой проект 15 сентября 2023 года или позже, защита от перечисления адресов электронной почты включена по умолчанию. Эта функция повышает безопасность учетных записей пользователей вашего проекта, но отключает метод fetchSignInMethodsForEmail() , который мы ранее рекомендовали для реализации потоков, основанных на идентификаторах.

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

Для получения более подробной информации см. раздел «Включение или отключение защиты от перечисления адресов электронной почты» .

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

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

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

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

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

Для выхода из системы пользователя вызовите signOut: .

Быстрый

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

Objective-C

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

Также может потребоваться добавить код обработки ошибок для всего спектра ошибок аутентификации. См. раздел «Обработка ошибок» .