Cómo instalar Firebase Auth a tu aplicación Flutter


Avatar de Pedro Cortez

Una herramienta importante de la suite Firebase que es esencial dominar es Firebase Auth. Esta herramienta permitirá a tus usuarios crear una cuenta y luego acceder a su perfil. En esta guía, intentaré mostrarte paso a paso cómo crear un sistema de inicio de sesión sencillo.


flutter firebase auth

¿Para qué sirve Firebase Auth?

Firebase Auth es una herramienta poderosa de la suite Firebase, diseñada para gestionar de manera segura las credenciales de tus usuarios. Esto es lo que puedes lograr con Firebase Auth:

  • Recuperar las credenciales de los usuarios: Recopila de manera segura los correos electrónicos y contraseñas de tus usuarios;
  • Almacenar la información de forma segura: Los datos de autenticación están cifrados y protegidos contra accesos no autorizados;
  • Asignar un identificador único a cada usuario: Cada usuario recibe un identificador único, lo que facilita la gestión y el seguimiento;
  • Permitir a los usuarios iniciar sesión: Ofrece a tus usuarios la posibilidad de iniciar sesión fácilmente en tu aplicación con sus credenciales.

Otra ventaja de Firebase Auth es que soporta diferentes métodos de autenticación, incluyendo autenticación por correo electrónico y contraseña, así como mediante proveedores terceros como Google, Facebook y Twitter, además de la autenticación anónima. Esto te permite elegir el método que mejor se adapte a las necesidades de tu aplicación y usuarios.

¿Cómo instalar Firebase Auth en mi aplicación Flutter?

Antes de instalar Firebase Auth, asegúrate de haber integrado Firebase en tu aplicación Flutter. Si aún no lo has hecho, consulta mi guía detallada sobre cómo instalar Firebase con Flutter. Una vez que hayas completado ese paso, solo tendrás que importar el paquete firebase_auth en su última versión (5.3.3). Para ello, puedes hacer lo siguiente:

  • Ejecuta el comando $ flutter pub add firebase_auth en tu terminal;
  • Copia y pega firebase_auth: ^5.4.1 en tus dependencias, en tu archivo pubspec.yaml.

Agrega la siguiente línea de importación en los archivos donde desees utilizar Firebase Auth:

import 'package:firebase_auth/firebase_auth.dart';

Crear un usuario

Aquí están los pasos para crear un usuario en tu base de datos Firebase, recuperando sus datos desde tu aplicación Flutter:

1. Agregar permisos en Firebase

El primer paso para instalar Firebase en tu aplicación Flutter es configurar los permisos en tu proyecto:

  • Ve a la consola de Firebase, luego dirígete a la sección de Autenticación. Haz clic en «Todos los productos» en el menú de la izquierda, selecciona «Autenticación» y haz clic en «Comenzar».
  • Elige «Correo electrónico/Contraseña» como método de inicio de sesión. Este método es fácil de implementar y es ideal para comenzar.
  • Una vez que habilites este método, podrás almacenar la información de los usuarios, como su correo electrónico y contraseña, asociados a un identificador único.

2. Crear campos de inscripción en tu aplicación

Para recopilar la información de registro (correo electrónico, contraseña, nombre, apellido, confirmación de contraseña), debes agregar campos de texto en tu interfaz de usuario. Así es como hacerlo:

  • Crea dos variables de tipo TextEditingController() para gestionar los campos de texto.
  • Agrega los campos de texto en tu UI para que el usuario pueda ingresar sus datos. Aquí tienes un ejemplo de código para comenzar, que puedes adaptar a tu diseño y necesidades:

Te proporciono un ejemplo que puedes usar y modificar según tus necesidades:

class InputSection extends StatefulWidget {
  InputSection({super.key});

  @override
  State<InputSection> createState() => _InputSectionState();
}

class _InputSectionState extends State<InputSection> {
  final TextEditingController emailField = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 360,
      margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
      child: Column(children: [
        //REPETIR ESTE BLOQUE PARA CADA CAMPO QUE NECESITES. AQUÍ HE PUESTO EL CORREO, PERO SÓLO TIENES QUE REEMPLAZAR EL TEXTEDITINGCONTROLLER Y EL HINT TEXT
        Container(
            height: MediaQuery.of(context).size.height * 0.11,
            child: Column(
              children: [
                Container(
                  margin: const EdgeInsets.only(bottom: 5),
                  alignment: Alignment.centerLeft,
                  child: Text(
                    "Correo electrónico*",
                    textAlign: TextAlign.start,
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                Container(
                    height: MediaQuery.of(context).size.height * 0.06,
                    margin: EdgeInsets.symmetric(
                      horizontal: MediaQuery.of(context).size.width * 0.01,
                    ),
                    decoration: BoxDecoration(
                        color: Colors.white,
                        border: Border.all(color: Colors.black, width: 1),
                        borderRadius: BorderRadius.circular(30),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.black.withOpacity(0.2),
                            spreadRadius: 2,
                            blurRadius: 5,
                            offset: const Offset(0, 5),
                          ),
                        ]),
                    child: Row(
                      children: [
                        Expanded(
                            child: Container(
                          margin: const EdgeInsets.only(left: 20),
                          child: TextField(
                            controller: emailField,
                            style: const TextStyle(
                              fontSize: 15,
                              color: Colors.black,
                              fontWeight: FontWeight.bold,
                            ),
                            obscureText: false,
                            decoration: InputDecoration(
                              hintText: "Introduce correo",
                              hintStyle: TextStyle(
                                  color: Colors.black,
                                  fontWeight: FontWeight.w500),
                              border: InputBorder.none,
                            ),
                          ),
                        )),
                        Container(
                          height: 50,
                          width: 50,
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(30),
                          ),
                          child: const Icon(Icons.mail_outline_rounded,
                              size: 30, color: Colors.black),
                        ),
                      ],
                    )),
              ],
            )),
      ]));
  }
}

3. Enviar la información recuperada desde Flutter a Firebase Auth

Después de recuperar la información del usuario, almacénala en Firebase Auth. Para ello, crea:

  • Un botón de envío;
  • Una función para crear al usuario;
  • Una función para crear un documento en Firebase que represente a tu usuario y almacene su información (esto no es obligatorio, pero se recomienda encarecidamente).

Aquí tienes un ejemplo de código para el botón y la función de registro:

Container(
    width: double.infinity,
    height: MediaQuery.of(context).size.height * 0.06,
    margin: EdgeInsets.symmetric(
      horizontal: MediaQuery.of(context).size.width * 0.01,
    ),
    child: ElevatedButton(
        style: ElevatedButton.styleFrom(
            backgroundColor: const Color.fromARGB(250, 250, 185, 45),
            shape: const RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(30)),
            )),
        onPressed: () {
          SignUp();
        },
        child: Text("Registrarse",
            style: TextStyle(
              fontSize: 18,
              color: Colors.black,
              fontWeight: FontWeight.bold,
            ))),
)

Luego, te aconsejo crear una función SignUp() que creará a tu usuario, lo conectará y añadirá sus datos a Firebase en un solo paso:

Future SignUp() async {
    await auth.instance.createUserWithEmailAndPassword(
        email: emailField.text.trim(), password: passwordField.text.trim());
    var userID = auth.currentUser!.uid;
    addUser(userID, userName.text, emailField.text);
}

El método createUserWithEmailAndPassword() en una instancia de FirebaseAuth se utiliza para crear un nuevo usuario con su correo electrónico y contraseña.

¿Cómo recuperar la información contenida en mis campos de texto?

El texto ingresado en tus campos de texto se almacena en variables de tipo TextEditingController(). Para recuperar los valores de estos campos, solo necesitas acceder a la propiedad .text de cada variable y usar .trim() para eliminar los espacios innecesarios al principio y al final de la cadena.

String email = emailController.text.trim();
String password = passwordController.text.trim();

El uso de .trim() no es obligatorio, pero se recomienda para evitar errores debido a espacios accidentales.

¿Por qué crear una instancia?

Para usar las funciones de Firebase Auth, es necesario crear una instancia de FirebaseAuth. Esta instancia puede almacenarse en una variable para ser reutilizada en diferentes partes de tu código. Gracias a esta instancia, podrás llamar a diversos métodos necesarios para la gestión de usuarios, como la creación y el inicio de sesión de usuarios.

final FirebaseAuth _auth = FirebaseAuth.instance;

¿Cómo recuperar el ID del usuario que acabo de crear?

El ID único de un usuario se puede obtener utilizando el método FirebaseAuth.instance.currentUser!.uid. Una vez que este ID se almacene en una variable de tipo String, es recomendable usarlo como identificador para el documento del usuario en tu base de datos Firebase. Esto facilita la búsqueda de la información del usuario, como su foto de perfil, usando simplemente el nombre de la colección y el ID del usuario.

String userId = FirebaseAuth.instance.currentUser!.uid;

Al usar este ID como identificador para el documento del usuario en Firestore, podrás acceder rápidamente a la información almacenada asociando el ID único a cada documento de usuario.

4. Gestionar los errores

Durante el registro, tus usuarios pueden encontrar problemas como una contraseña débil o una dirección de correo electrónico incorrecta. Para manejar estas situaciones, es importante crear una función que verifique la información ingresada y devuelva un mensaje de error apropiado en caso de problema.

Para ello, utiliza un bloque try/catch para probar una acción (try) y ejecutar otra acción si esta falla (catch). Coloca las funciones de agregar usuarios a Firebase en el bloque try y los mensajes de error en el bloque catch. Aquí tienes un ejemplo de código que puedes utilizar:

try {
     await auth.createUserWithEmailAndPassword(
         email: emailField.text.trim(), password: passwordField.text.trim());
     var userID = auth.currentUser!.uid;
     addUser(userID, userName.text, emailField.text);
} on FirebaseAuthException catch (e) {
     //CONTRASEÑA DEMASIADO DÉBIL
     if (e.code.contains("weak-password")) {
       Fluttertoast.showToast(
           msg: "Tu contraseña debe tener al menos 6 caracteres.");
     }

     //CORREO EN MAL FORMATO
     if (e.code.contains("invalid-email")) {
       Fluttertoast.showToast(msg: "Tu correo electrónico no tiene un formato válido.");
     }

     //CORREO YA EN USO
     if (e.code.contains("email-already-in-use")) {
       Fluttertoast.showToast(msg: "Este correo electrónico ya está en uso.");
     }

     //MENSAJE POR DEFECTO
     else {
       Fluttertoast.showToast(
           msg:
               "Parece que tu correo electrónico y tu contraseña no están en el formato correcto.");
     }
     ;
     print(e);
}

En este ejemplo, la función try intenta:

  • Crear un usuario con su correo electrónico y contraseña;
  • Recuperar su identificador único;
  • Añadir la información del usuario en un documento de Firebase.

Si alguna de estas acciones falla, el error es capturado por catch(e), donde e representa el error.

e es una sintaxis comúnmente utilizada que significa «error», pero puedes usar cualquier otro nombre. Solo asegúrate de que es el nombre que contendrá el error de tu bloque catch.

Dependiendo del tipo de error, puedes mostrar un mensaje específico para informar al usuario sobre lo que debe corregir:

  • weak-password: Contraseña demasiado débil (menos de 6 caracteres).
  • invalid-email: Formato de correo electrónico inválido.
  • email-already-in-use: El correo electrónico ya está registrado en tu base de datos de Firebase Auth.

Aquí, utilizo el paquete FlutterToast para mostrar un breve mensaje de error. Cada mensaje es personalizado según el tipo de error devuelto por mi método catch(e) {}.

Conectar un usuario

Después de registrar a tus usuarios, debes configurar un sistema de inicio de sesión. Este sistema funciona como un valor booleano, determinando si el usuario está conectado o desconectado. Veamos cómo implementar esta funcionalidad y luego cómo adaptar tu aplicación según el estado del usuario.

Adaptar la función main()

Para conectar a los usuarios, el primer paso es modificar tu función main(). Esta función ahora debe verificar el estado del usuario antes de construir la aplicación. Así es como se vería tu función main() después de la modificación:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  runApp(const MyApp());
}

Crear un sistema de inicio de sesión

Al igual que para el registro, el primer paso para conectar a un usuario es recuperar su correo electrónico y contraseña. Debes crear al menos dos campos de texto y dos variables de tipo TextEditingController() para almacenar esta información. Luego, crea un botón de inicio de sesión que activará la función de inicio de sesión. Puedes reutilizar y adaptar el código proporcionado previamente.

Luego, crea una función loginToFirebase() y colócala en la parte onPressed de tu botón de inicio de sesión. Aquí tienes un ejemplo de código que puedes usar:

FirebaseAuth auth = FirebaseAuth.instance; //No es necesario agregar esta línea si ya la tienes

Future loginToFirebase() async {
   print(emailField.text.trim());
   print(passwordField.text.trim());
   try {
     await auth.signInWithEmailAndPassword(
         email: emailField.text.trim(), password: passwordField.text.trim());
   } on FirebaseAuthException catch (e) {
     Fluttertoast.showToast(
         msg:
             "Tu dirección de correo electrónico o tu contraseña parecen ser incorrectos.");
     print(e.toString());
   }
}

Aquí, recupero la dirección contenida en emailField y la contraseña en passwordField. Las utilizo en mi método auth.signInWithEmailAndPassword() para cambiar el estado de mi usuario y pasarlo de desconectado a conectado.

Probar que mi función funciona

Para verificar que tu función de inicio de sesión funciona correctamente, muestra el ID único del usuario en la terminal de comandos utilizando un print(). Por ejemplo:

print(FirebaseAuth.instance.currentUser!.uid);

Si el ID se muestra correctamente, significa que el usuario está correctamente conectado.

Mostrar contenido diferente según el estado del usuario

Una vez que tu usuario esté conectado, solo te quedará cambiar de tu página de inicio de sesión a la página que quieras mostrar. Para ello, existen dos métodos que personalmente he podido utilizar:

  • runApp(): Que lanzará una página diferente, según el estado del usuario;
  • MaterialPageRoute(): Que redirigirá al usuario a una nueva página.

Usar runApp()

El método runApp() es el más fácil de usar. Debes crear dos páginas: una para la conexión y otra como la página principal. Utiliza StatefulWidget para construir el diseño de cada página.

Ambos StatefulWidget deben devolver un MaterialApp para que este método funcione correctamente. No te limites a usar un Scaffold o un Container.

Luego, modifica tu función main de la siguiente manera:

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp();
 auth.authStateChanges().listen((User? user) {
   if (user == null) {
     print('Usuario no conectado');
     runApp(const PageConnexion());
   } else {
     print('Usuario conectado: ' + user.email!);
     runApp(const HomePage());
   }
 });
}

En este ejemplo, la función main muestra PageConnexion() si el usuario es null (no conectado). De lo contrario, muestra HomePage().

Usar MaterialPageRoute()

A veces, no es posible utilizar el método anterior para mostrar la página correcta al usuario. En ese caso, utiliza Navigator.pushReplacement() para redirigir al usuario a otra página.

Aquí tienes un ejemplo de código para implementar este método en el botón de inicio de sesión:

onPressed() {
   Navigator.pushReplacement(
     context,
     MaterialPageRoute(
         builder: (_) => const MaterialApp(
         debugShowCheckedModeBanner: false,
         home: DefaultTabController(
           length: 4,
           child: HomeScreen(),
     ))))
}

class HomeScreen extends StatefulWidget {
 const HomeScreen({super.key});

 @override
 State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
       extendBody: true,
       backgroundColor: Colors.white,
       body: //(Cuerpo de tu página)
 }
}

Otras métodos de inicio de sesión

Existen muchos otros métodos de inicio de sesión para los cuales redactaré guías conforme se vayan necesitando:

Estos métodos permiten una mayor flexibilidad y se adaptan a diversas necesidades de autenticación.

Conclusión

Ahora tus usuarios pueden crear un perfil para acceder a tu aplicación. Pero, ¿cómo saber si les gusta usar tu aplicación y si aprecian su diseño? ¿Cómo medir sus diferentes interacciones y analizarlas? Te lo explicaré todo en la próxima guía.

Avatar de Pedro Cortez