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

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

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

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

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

Настройте свой Android-проект

  1. Если вы еще этого не сделали, добавьте Firebase в свой проект Android .

  2. В файле Gradle вашего модуля (уровня приложения) (обычно <project>/<app-module>/build.gradle.kts или <project>/<app-module>/build.gradle ) добавьте зависимость для библиотеки Firebase Authentication для Android. Мы рекомендуем использовать Firebase Android BoM для управления версиями библиотеки.

    Кроме того, в рамках настройки Firebase Authentication вам необходимо добавить в свое приложение SDK сервисов Google Play.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.14.0"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0")
    }

    Благодаря использованию Firebase Android BoM ваше приложение всегда будет использовать совместимые версии библиотек Firebase Android.

    (Альтернатива) Добавьте зависимости библиотеки Firebase без использования BoM

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

    Обратите внимание: если вы используете в своем приложении несколько библиотек Firebase, мы настоятельно рекомендуем использовать BoM для управления версиями библиотек, что гарантирует совместимость всех версий.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:23.2.1")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0")
    }
    Ищете модуль библиотеки, специфичный для Kotlin? Начиная с октября 2023 года ( Firebase BoM 32.5.0) разработчики Kotlin и Java смогут полагаться на основной модуль библиотеки (подробности см. в разделе часто задаваемых вопросов об этой инициативе ).

Включите вход по ссылке электронной почты для вашего проекта Firebase

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

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

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

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

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

    Kotlin

    val actionCodeSettings = actionCodeSettings {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url = "https://www.example.com/finishSignUp?cartId=1234"
        // This must be true
        handleCodeInApp = true
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
            "com.example.android",
            true, // installIfNotAvailable
            "12", // minimumVersion
        )
    }

    Java

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

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

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

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

    Kotlin

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Email sent.")
            }
        }

    Java

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

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

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

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

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

Также убедитесь, что вы используете HTTPS-URL в рабочей среде, чтобы избежать потенциального перехвата вашей ссылки промежуточными серверами.

Завершение входа в приложение Android

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

Настройте Firebase Hosting

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

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

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

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

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

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

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

    Для обработки этих ссылок из вашего приложения Android необходимо указать имя пакета вашего приложения в настройках проекта консоли Firebase . Кроме того, необходимо предоставить SHA-1 и SHA-256 сертификата приложения.

    Если вы хотите, чтобы эти ссылки перенаправляли на определенную активность, вам нужно будет настроить фильтр намерений в вашем файле AndroidManifest.xml . Фильтр намерений должен перехватывать ссылки электронной почты вашего домена. В AndroidManifest.xml :

    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.BROWSABLE" />
      <category android:name="android.intent.category.DEFAULT" />
      <data
        android:scheme="https"
        android:host="<PROJECT_ID>.firebaseapp.com or your custom domain"
        android:pathPrefix="/__/auth/links" />
    </intent-filter>
    

    Когда пользователи открывают ссылку хостинга с путем /__/auth/links и указанной вами схемой и хостом, ваше приложение начнет действие с этим фильтром намерений для обработки ссылки .

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

Kotlin

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully signed in with email link!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error signing in with email link", task.exception)
            }
        }
}

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

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

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

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

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

Kotlin

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "Successfully linked emailLink credential!")
            val result = task.result
            // You can access the new user via result.getUser()
            // Additional user info profile *not* available via:
            // result.getAdditionalUserInfo().getProfile() == null
            // You can check if the user is new or existing:
            // result.getAdditionalUserInfo().isNewUser()
        } else {
            Log.e(TAG, "Error linking emailLink credential", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

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

Kotlin

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            // User is now successfully reauthenticated
        } else {
            Log.e(TAG, "Error reauthenticating", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

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

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

Мы опубликовали альтернативное решение в Firebase Authentication Android SDK v23.2.0+ и Firebase BoM v33.9.0+.

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

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

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

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

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

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

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

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

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

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

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();