Autentica con Firebase mediante un vínculo de correo electrónico en Android

Puedes usar Firebase Authentication para que los usuarios accedan mediante el envío de un correo electrónico con un vínculo en el que se pueda hacer clic. Además, en el proceso se verifica la dirección de correo electrónico del usuario.

Existen numerosos beneficios asociados al acceso por correo electrónico:

  • Es sencillo registrarse y acceder.
  • Hay un menor riesgo de reutilización de contraseñas entre aplicaciones, lo que puede comprometer incluso la seguridad de contraseñas bien seleccionadas.
  • Se puede autenticar un usuario y, al mismo tiempo, verificar que sea el dueño legítimo de la dirección de correo electrónico.
  • El usuario solo necesita una cuenta de correo electrónico con acceso para ingresar. No es necesario poseer un número de teléfono ni una cuenta en redes sociales.
  • El usuario puede acceder sin necesidad de proporcionar (o recordar) una contraseña, lo que resulta especialmente práctico si se utiliza un dispositivo móvil.
  • Un usuario existente que antes accedió con un identificador de correo electrónico (contraseña o federado) puede actualizar la configuración para acceder solamente con el correo electrónico. Por ejemplo, un usuario que olvidó su contraseña puede acceder de igual modo sin necesidad de restablecerla.

Antes de comenzar

Configura tu proyecto de Android

  1. Si aún no lo has hecho, agrega Firebase a tu proyecto de Android.

  2. En el archivo Gradle del módulo (nivel de la app) (generalmente <project>/<app-module>/build.gradle.kts o <project>/<app-module>/build.gradle), agrega la dependencia de la biblioteca de Firebase Authentication para Android. Te recomendamos usar Firebase Android BoM para controlar las versiones de las bibliotecas.

    Además, como parte de la configuración de Firebase Authentication, debes agregar el SDK de Servicios de Google Play a la app.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.9.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")
    }

    Cuando usas Firebase Android BoM, tu app siempre usará versiones compatibles de las bibliotecas de Firebase para Android.

    (Alternativa)  Agrega dependencias de la biblioteca de Firebase sin usar la BoM

    Si eliges no usar la Firebase BoM, debes especificar cada versión de la biblioteca de Firebase en su línea de dependencia.

    Ten en cuenta que, si usas múltiples bibliotecas de Firebase en tu app, es muy recomendable que uses la BoM para administrar las versiones de las bibliotecas para garantizar que todas las versiones sean compatibles.

    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.0")
    // 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")
    }
    ¿Buscas un módulo de biblioteca específico de Kotlin? A partir de octubre de 2023 (Firebase BoM 32.5.0), tanto los desarrolladores de Kotlin como los de Java pueden depender del módulo de la biblioteca principal (para obtener más información, consulta las Preguntas frecuentes sobre esta iniciativa).

Habilita el acceso mediante un vínculo de correo electrónico para tu proyecto de Firebase

Para que los usuarios accedan a través de un vínculo de correo electrónico, primero debes habilitar el método de acceso con proveedor de correo electrónico y con vínculo de correo electrónico para el proyecto de Firebase:

  1. En Firebase console, abre la sección Authentication.
  2. En la pestaña Método de acceso, habilita el proveedor de Correo electrónico/Contraseña. Ten en cuenta que se debe habilitar el acceso mediante correo electrónico/contraseña para utilizar el acceso con un vínculo de correo electrónico.
  3. En la misma sección, habilita el método de acceso con Vínculo del correo electrónico (acceso sin contraseña).
  4. Haz clic en Guardar.

Para iniciar el flujo de autenticación, muéstrale al usuario una interfaz que le pida ingresar su dirección de correo electrónico y, luego, llama a sendSignInLinkToEmail para solicitar a Firebase que envíe el vínculo de autenticación al correo electrónico del usuario.

  1. Construye el objeto ActionCodeSettings, que proporciona a Firebase las instrucciones para crear el vínculo de correo electrónico. Configura los siguientes campos:

    • url: Es el vínculo directo que se debe incorporar y cualquier estado adicional que se deba pasar. El dominio del vínculo debe estar en la lista de dominios autorizados de Firebase console, que se encuentra en la pestaña Método de acceso (Authentication > Método de acceso). El vínculo redireccionará al usuario a esta URL si la app no está instalada en el dispositivo y no se pudo instalar.
    • androidPackageName y iOSBundleId: Ayudan a Firebase Authentication a determinar si debe crear un vínculo solo web o móvil que se abre en un dispositivo Android o Apple.
    • handleCodeInApp: Se debe configurar como verdadero. A diferencia de otras acciones de correo electrónico fuera de banda (restablecimiento de contraseñas y verificaciones de correos electrónicos), la operación de acceso siempre debe completarse en la app. Esto se debe a que, al final del flujo, se espera que el usuario acceda y que su estado de autenticación permanezca en la app.
    • linkDomain: Cuando se definen dominios de vínculos Hosting personalizados para un proyecto, especifica cuál usar cuando una app para dispositivos móviles determinada abra el vínculo. De lo contrario, se selecciona automáticamente el dominio predeterminado (por ejemplo, PROJECT_ID.firebaseapp.com).
    • dynamicLinkDomain: Obsoleto. No especifiques este parámetro.

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

    Para obtener más información sobre ActionCodeSettings, consulta la sección Pasa estados en acciones de correo electrónico.

  2. Pídele el correo electrónico al usuario.

  3. Envía el vínculo de autenticación al correo electrónico del usuario y guarda su correo en caso de que este complete el acceso con correo electrónico en el mismo dispositivo.

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

Preocupaciones de seguridad

Para evitar que un vínculo de acceso se use para acceder como un usuario no deseado o en un dispositivo no deseado, Firebase Authentication requiere que se proporcione la dirección de correo electrónico del usuario cuando se complete el proceso de acceso. Para que el acceso sea exitoso, esta dirección de correo electrónico debe coincidir con la dirección a la que se envió originalmente el vínculo de acceso.

Con el objetivo de simplificar este proceso para los usuarios que abren el vínculo de acceso en el mismo dispositivo en el que lo solicitan, puedes almacenar su dirección de correo electrónico de manera local (por ejemplo, utilizando SharedPreferences) cuando envías el correo electrónico de acceso. Luego, usa esta dirección para completar el proceso. No pases el correo electrónico del usuario en los parámetros de la URL de redireccionamiento ni vuelvas a utilizarlo, ya que esto puede provocar que se inserte la sesión.

Una vez finalizado el acceso, se eliminará del usuario cualquier mecanismo de acceso previo sin verificar y se invalidarán las sesiones existentes. Por ejemplo, si alguien creó una cuenta no verificada con el mismo correo electrónico y contraseña, se quitará la contraseña del usuario para evitar que el ladrón de identidad que reclamó la propiedad y creó esa cuenta no verificada vuelva a acceder con el correo electrónico y la contraseña no verificados.

Además, asegúrate de utilizar una URL HTTPS en producción para evitar que los servidores intermediarios intercepten el vínculo.

Completa el acceso en una app para Android

Firebase Authentication usa Firebase Hosting para enviar el vínculo de correo electrónico a un dispositivo móvil. Para completar el acceso a través de la aplicación para dispositivos móviles, la app debe configurarse para detectar el vínculo entrante, analizar el vínculo directo subyacente y luego completar el acceso. Para obtener más información, consulta la documentación de Android App Links.

Configurar Firebase Hosting

Firebase Authentication usa dominios de Firebase Hosting cuando crea y envía un vínculo que debe abrirse en una aplicación para dispositivos móviles. Ya se configuró un dominio de Firebase Hosting predeterminado para ti.

  1. Configura los dominios de Firebase Hosting:

    En Firebase console, abre la sección Hosting.

    • Si deseas usar el dominio predeterminado para el vínculo de correo electrónico que se abre en las aplicaciones para dispositivos móviles, ve a tu sitio predeterminado y toma nota de tu dominio de Hosting predeterminado. Un dominio de Hosting predeterminado suele ser como el siguiente: PROJECT_ID.firebaseapp.com.

      Necesitarás este valor cuando configures la app para interceptar el vínculo entrante.

    • Si deseas usar un dominio personalizado para el vínculo de correo electrónico, puedes registrar uno con Firebase Hosting y usarlo para el dominio del vínculo.

  2. Configuración de aplicaciones para Android:

    Para manejar estos vínculos desde la aplicación para Android, es necesario especificar el nombre del paquete de la app en la configuración del proyecto de Firebase console. Además, es necesario proporcionar el SHA-1 y el SHA-256 del certificado de aplicación.

    Si deseas que estos vínculos redireccionen a una actividad específica, deberás configurar un filtro de intents en el archivo AndroidManifest.xml. El filtro de intents debe capturar vínculos de correo electrónico del dominio. En 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>
    

    Cuando los usuarios abren un vínculo de hosting con la ruta de acceso /__/auth/links y el esquema y el host que especificaste, tu app iniciará la actividad con este filtro de intents para controlar el vínculo.

Una vez que recibas el vínculo mencionado anteriormente, verifica que sea apto para la autenticación mediante vínculo de correo electrónico y completa el acceso.

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

Para obtener más información sobre cómo realizar el acceso mediante un vínculo de correo electrónico en una aplicación de Apple, consulta la Guía de plataformas de Apple.

Para saber cómo realizar el acceso mediante un vínculo de correo electrónico en una aplicación web, consulta la Guía para aplicaciones web.

También puedes vincular este método de autenticación a un usuario existente. Por ejemplo, un usuario ya autenticado con otro proveedor, como un número de teléfono, puede agregar este método de acceso a la cuenta existente.

Lo que cambia sería la segunda mitad de la operación:

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

Esto también se puede usar para volver a autenticar a un usuario de un vínculo de correo electrónico antes de ejecutar una operación sensible.

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

Sin embargo, como el flujo podría terminar en un dispositivo diferente, desde donde el usuario original no accedió, dicho flujo podría no completarse. En ese caso, se puede mostrar un error al usuario para forzarlo a abrir el vínculo en el mismo dispositivo. Se puede pasar algún estado en el vínculo para proporcionar información sobre el tipo de operación y el uid del usuario.

La autenticación mediante vínculos de correo electrónico antes dependía de Firebase Dynamic Links, que dejará de estar disponible el 25 de agosto de 2025.

Publicamos una solución alternativa en la versión 23.2.0 y versiones posteriores del SDK de Android de Firebase Authentication, y en la versión 33.9.0 y versiones posteriores de Firebase BoM.

Si tu app usa vínculos del estilo anterior, debes migrarla al nuevo sistema basado en Firebase Hosting.

Si creaste tu proyecto a partir del 15 de septiembre de 2023, la protección contra la enumeración de correos electrónicos está habilitada de forma predeterminada. Esta función mejora la seguridad de las cuentas de usuario de tu proyecto, pero inhabilita el método fetchSignInMethodsForEmail(), que antes recomendábamos para implementar flujos que priorizan el identificador.

Aunque puedes inhabilitar la protección contra la enumeración de correo electrónico para tu proyecto, te recomendamos que no lo hagas.

Consulta la documentación sobre la protección contra la enumeración de correo electrónico. para obtener más información.

Próximos pasos

Cuando un usuario accede por primera vez, se crea una cuenta de usuario nueva y se la vincula con las credenciales (el nombre de usuario y la contraseña, el número de teléfono o la información del proveedor de autenticación) que el usuario utilizó para acceder. Esta cuenta nueva se almacena como parte de tu proyecto de Firebase y se puede usar para identificar a un usuario en todas las apps del proyecto, sin importar cómo acceda.

  • En tus apps, puedes obtener la información básica del perfil del usuario a partir del objeto FirebaseUser. Consulta Administra usuarios.

  • En tus Reglas de seguridad de Firebase Realtime Database y Cloud Storage, puedes obtener el ID del usuario único que accedió a partir de la variable auth y usarlo para controlar a qué datos podrá acceder.

Para permitir que los usuarios accedan a tu app mediante varios proveedores de autenticación, puedes vincular las credenciales de estos proveedores con una cuenta de usuario existente.

Para salir de la sesión de un usuario, llama a signOut de la siguiente manera:

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();