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

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

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

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

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

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

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

  2. Использование Firebase Android Банка Москвы , объявить зависимость для библиотеки Firebase аутентификации Android в вашем модуле (приложение уровня) Gradle файл (обычно app/build.gradle ).

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

    Джава

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare 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 declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

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

    (Альтернативный) Объявляет Firebase библиотеки зависимостей без использования спецификации

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

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

    dependencies {
        // Declare 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:21.0.1'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

    Котлин + KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare 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-ktx'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

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

    (Альтернативный) Объявляет Firebase библиотеки зависимостей без использования спецификации

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

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

    dependencies {
        // Declare 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-ktx:21.0.1'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

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

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

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

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

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

    Джава

    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();

    Котлин + KTX

    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 */)
    }

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

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

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

    Джава

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

    Котлин + KTX

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

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

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

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

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

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

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

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

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

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

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

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

      example.page.link

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

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

    1. Чтобы обрабатывать эти ссылки из вашего приложения Android, необходимо указать имя пакета Android в настройках проекта консоли Firebase. Кроме того, необходимо предоставить SHA-1 и SHA-256 сертификата приложения.
    2. Теперь, когда вы добавили домен динамической ссылки и убедились, что ваше приложение Android настроено правильно, динамическая ссылка будет перенаправлять на ваше приложение, начиная с активности средства запуска.
    3. Если вы хотите ссылку динамического перенаправления на конкретную деятельность, вам нужно будет настроить фильтр намерений в файле AndroidManifest.xml. Это можно сделать, указав домен динамической ссылки или обработчик действий электронной почты в фильтре намерений. По умолчанию обработчик электронной почты действий размещен на домене , как в следующем примере:
      PROJECT_ID.firebaseapp.com/
    4. Предостережения:
      1. Не указывайте URL-адрес, который вы установили для actionCodeSettings в своем фильтре намерений.
      2. При создании домена динамической ссылки вы также могли создать короткую ссылку URL. Этот короткий URL-адрес не будет передан; не настроить фильтр намерений , чтобы поймать его с android:pathPrefix атрибута. Это означает, что вы не сможете перехватывать разные динамические ссылки в разных частях вашего приложения. Тем не менее, вы можете проверить mode параметра запроса в ссылке , чтобы увидеть , что операция пытается быть выполнена, или методы использования SDK , такие как isSignInWithEmailLink , чтобы увидеть , если ссылка , что ваше приложение получило делает то , что вы хотите.
    5. Более подробную информацию о получении динамических ссылок, см Получая инструкции Android динамические ссылки .

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

Джава

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

Котлин + KTX

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

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

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

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

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

Джава

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

Котлин + KTX

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

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

Джава

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

Котлин + KTX

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

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

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

Джава

auth.fetchSignInMethodsForEmail(email)
        .addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
            @Override
            public void onComplete(@NonNull Task<SignInMethodQueryResult> task) {
                if (task.isSuccessful()) {
                    SignInMethodQueryResult result = task.getResult();
                    List<String> signInMethods = result.getSignInMethods();
                    if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                        // User can sign in with email/password
                    } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                        // User can sign in with email/link
                    }
                } else {
                    Log.e(TAG, "Error getting sign in methods for user", task.getException());
                }
            }
        });

Котлин + KTX

Firebase.auth.fetchSignInMethodsForEmail(email)
        .addOnSuccessListener { result ->
            val signInMethods = result.signInMethods!!
            if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                // User can sign in with email/password
            } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                // User can sign in with email/link
            }
        }
        .addOnFailureListener { exception ->
            Log.e(TAG, "Error getting sign in methods for user", exception)
        }

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

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

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

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

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

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

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

Джава

FirebaseAuth.getInstance().signOut();

Котлин + KTX

Firebase.auth.signOut()