¿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 archivopubspec.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.
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.
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:
- Guía de instalación de Google Sign In con Flutter;
- Guía de instalación de Apple Sign In con Flutter;
- Twitter;
- Facebook;
- Microsoft, etc.
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.