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

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

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

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

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

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

  1. В Xcode откройте проект приложения и перейдите в Файл > Добавить пакеты .
  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 читайте в разделе «Универсальные ссылки и связанные домены» (Universal Links and Associated Domains)

Настроить 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 11.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;
}

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