Esta guía es un complemento de Cómo configurar la autenticación de Firebase con una aplicación web React . En la introducción de esa guía, señalé que Firebase ofrece otros esquemas de autenticación más allá de la autenticación básica de correo electrónico/contraseña. Una de esas alternativas es la Autenticación sin contraseña .
La autenticación sin contraseña es una opción atractiva a la hora de crear aplicaciones. Simplifica la experiencia del usuario, ya que sus usuarios no necesitan recordar sus contraseñas y, por lo tanto, tampoco tienen que preocuparse por perderlas. También facilita la experiencia de desarrollo ya que no es necesario diseñar ninguna lógica de gestión o captura de contraseñas.
En esta guía, creará un flujo de trabajo simple de inicio de sesión/confirmación/perfil/cierre de sesión que implemente la autenticación sin contraseña de Firebase.
Google establece varios límites de autenticación de Firebase. Si está utilizando el plan Spark gratuito, tenga en cuenta que estará limitado a 5 correos electrónicos con enlaces de inicio de sesión por día. Si bien el plan Spark puede ser suficiente para fines de prueba, deberá actualizar al plan Blaze de pago por uso para superar este límite.
A lo largo de esta guía, me referiré a la guía Cómo configurar la autenticación de Firebase con una aplicación web React como guía de requisitos previos y al proyecto asociado como proyecto de requisitos previos .
Para completar esta guía, necesitará tener:
En la guía de requisitos previos, creó un nuevo proyecto de Firebase para la autenticación básica de correo electrónico/contraseña. Ahora, habilitará ese mismo proyecto para la autenticación sin contraseña. Inicie sesión en su cuenta de Firebase y haga clic en Ir a la consola .
Haga clic en su proyecto de autenticación que aparece en el panel de proyectos de Firebase. Esta guía utiliza el nombre del proyecto my-auth-test
.
Haga clic en autenticación en el menú del panel izquierdo.
Haga clic en la pestaña Método de inicio de sesión en la ventana principal.
Según su trabajo en la guía de requisitos previos, la tabla Proveedores de inicio de sesión ya debería mostrar Correo electrónico/Contraseña en la columna Proveedores con el estado Habilitado . Haga clic en el icono de lápiz para abrir el panel de configuración del proveedor de correo electrónico/contraseña .
Haga clic en el interruptor para habilitar el enlace de correo electrónico (inicio de sesión sin contraseña) .
Haga clic en Guardar .
Su proyecto de Firebase ahora está configurado para admitir la autenticación sin contraseña.
Cree un nuevo proyecto de React usando el nombre de la aplicación que desee. Esta guía utiliza passwordless-auth
.
npx create-react-app passwordless-auth
Esta guía requiere la instalación de 3 paquetes de Node.js:
Instale cada uno de los tres paquetes anteriores a través de npm
:
npm install firebase
npm install react-router-dom
npm install bootstrap
firebase.js
del proyecto de requisitos previos En el proyecto de requisitos previos, creó un archivo firebase.js
que utiliza los datos de configuración de su proyecto Firebase para crear una instancia del servicio Firebase Authentication. Su archivo firebase.js
debe tener la siguiente estructura con los valores de configuración de su proyecto Firebase:
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; const firebaseConfig = { apiKey: "AIzaSyDiUlY68W9Li_0EIkmdGdzD7nvqCT9kHnY", authDomain: "my-auth-test-fbd48.firebaseapp.com", projectId: "my-auth-test-fbd48", storageBucket: "my-auth-test-fbd48.appspot.com", messagingSenderId: "1078604952662", appId: "1:1078604952662:web:5d0b908439cfb5684ab7f7" } const app = initializeApp(firebaseConfig); const auth = getAuth(app); export { auth }
Copie firebase.js
a su nueva carpeta de proyecto de React.
Si necesita revisar la configuración de su proyecto de Firebase, haga clic en el ícono de ajustes junto a Descripción general del proyecto en el menú del panel izquierdo. La pestaña General ya debería estar seleccionada. Desplácese hacia abajo hasta la sección Sus aplicaciones que contiene el panel de aplicaciones web . La opción npm dentro del panel de aplicaciones web ya debería estar seleccionada. Los valores de configuración de su proyecto aparecerán en el bloque de código mostrado.
La aplicación React constará de 5 componentes: App
, Layout
, Login
, Confirm
y Profile
.
App
App
define la estructura general de la aplicación, incluido el enrutamiento. Layout
Layout
especifica el marcado de la aplicación que permanece consistente en todas las rutas. Login
Confirm
Confirm
cuando hace clic en un enlace de inicio de sesión. Profile
Profile
después de confirmar su dirección de correo electrónico.Profile
para cerrar sesión en su cuenta. El directorio src
final contendrá los siguientes archivos:
src |__ index.js |__ firebase.js // Copied from prerequisite project in Step 3. |__ App.js |__ Layout.jsx |__ Login.jsx |__ Confirm.jsx |__ Profile.jsx
reportWebVitals.js
setupTests.js
logo.svg
index.css
App.css
App.test.js
Copie index.js
del proyecto de requisitos previos a la carpeta de su nuevo proyecto. Esta guía utiliza el mismo archivo. Si necesita reconstruir index.js
, consulte el Paso 5b.2 de la guía de requisitos previos o copie el bloque de código a continuación.
Copie Layout.jsx
del proyecto de requisitos previos a la carpeta de su nuevo proyecto. Esta guía utiliza el mismo archivo. Si necesita reconstruir Layout.jsx
, consulte el Paso 5d de la guía de requisitos previos o copie el bloque de código a continuación. Opcionalmente, puede actualizar el texto del proyecto en la etiqueta <p>
de Layout.jsx
para React With Firebase Passwordless Authentication
o cualquier título que prefiera.
Sus archivos index.js
y Layout.jsx
deben ser los siguientes:
// index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import "bootstrap/dist/css/bootstrap.min.css"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );
// Layout.jsx import { Outlet } from "react-router-dom"; const Layout = () => { return( <div className = "container-fluid"> <div className = "row justify-content-center mt-3"> <div className = "col-md-4 text-center"> <p className = "lead">React With Firebase Passwordless Authentication</p> </div> <Outlet /> </div> </div> ) } export default Layout
App.js
El archivo App.js
es prácticamente el mismo que el del proyecto de requisitos previos, con cambios en solo dos líneas. Para facilitar la creación del archivo, copie App.js
del proyecto de requisitos previos a su nueva carpeta de proyecto.
Elimine la siguiente línea import
del archivo y reemplácela como se muestra a continuación:
// Delete this line: import Signup from "./Signup";
// Replace it with: import Confirm from "./Confirm";
Elimine la siguiente <Route>
del archivo y reemplácela como se muestra a continuación:
// Delete this line: <Route path = "/signup" element = { <Signup></Signup> } ></Route>
// Replace it with: <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route>
Guarde App.js
El archivo completo ahora debería ser el siguiente:
import Layout from "./Layout"; import Login from "./Login"; import Confirm from "./Confirm"; import Profile from "./Profile"; import { BrowserRouter, Routes, Route } from "react-router-dom"; const App = () => { return ( <BrowserRouter> <Routes> <Route path = "/" element = { <Layout></Layout> }> <Route index element = { <Login></Login> }></Route> <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route> <Route path = "/profile" element = { <Profile></Profile> } ></Route> </Route> </Routes> </BrowserRouter> ) } export default App
Tenga en cuenta que el componente Login
vuelve a ser la ruta de inicio de la aplicación, como lo era con el proyecto de requisitos previos.
Login.jsx
En el caso de la autenticación sin contraseña, obviamente no es necesario incluir un campo de contraseña ni administrar el estado para ingresar la contraseña. Por lo tanto, el formulario de inicio de sesión solo necesita capturar la dirección de correo electrónico del usuario.
Cree un nuevo archivo Login.jsx
en el directorio src
.
Agregue el siguiente código:
import { useState } from "react"; import { auth } from "./firebase"; import { sendSignInLinkToEmail } from "firebase/auth"; const Login = () => { const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const actionCodeSettings = { url: "http://localhost:3000/confirm", handleCodeInApp: true } const callSendSignInLinkToEmail = (e) => { e.preventDefault(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { setNotice("An email was sent to your email address. Click the link in the email to login."); }) .catch((error) => { setNotice("An error occurred when sending a login link to your email address: ", error.name); }) } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleInputEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleInputEmail" className = "form-label">Email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSendSignInLinkToEmail(e)}>Submit</button> </div> </form> </div> </div> ) }
Login.jsx
.
Al capturar la dirección de correo electrónico del usuario, el formulario Login.jsx
envía un correo electrónico con un enlace de inicio de sesión a su dirección a través del método sendSignInLinkToEmail
de Firebase. Si tiene éxito, se notifica al usuario que se ha enviado el correo electrónico. Tenga en cuenta que el objeto actionCodeSettings
se pasa como parámetro al método sendSignInLinkToEmail
e incluye la URL a la que se dirigirá al usuario cuando haga clic en el enlace de inicio de sesión enviado por correo electrónico. En este caso, la URL se asigna a la ruta /confirm
especificada en App.js
Confirm.jsx
El método signInWithEmailLink
de Firebase se utiliza para iniciar sesión en un usuario que ha hecho clic en un enlace de inicio de sesión. Como verá en un momento, el método toma un parámetro email
y el valor del email
debe coincidir con la dirección de correo electrónico que el usuario utilizó al iniciar sesión a través del formulario de inicio de sesión. Confirm.jsx
presenta al usuario un formulario para confirmar su dirección de correo electrónico y posteriormente intenta iniciar sesión.
Cree un nuevo archivo Confirm.jsx
en el directorio src
.
Agregue el siguiente código:
import { useState } from "react"; import { auth } from "./firebase"; import { isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Confirm = () => { const navigate = useNavigate(); const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const callSignInWithEmailLink = (e) => { e.preventDefault(); if (isSignInWithEmailLink(auth, window.location.href)) { signInWithEmailLink(auth, email, window.location.href) .then(() => { navigate("/profile"); }) .catch((error) => { setNotice("An occurred during sign in: ", error.name); }) } } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleConfirmEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleConfirmEmail" className = "form-label">Please confirm your email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSignInWithEmailLink(e)}>Confirm</button> </div> </form> </div> </div> ) } export default Confirm
Confirm.jsx
.
El método isSignInWithEmailLink
primero comprueba si el enlace de inicio de sesión que utiliza el usuario es válido. Si es así, se llama al método signInWithEmailLink
para iniciar sesión como usuario. Para reiterar, el valor email
pasado al método signInWithEmailLink
debe coincidir con la dirección de correo electrónico que el usuario utilizó con el formulario de inicio de sesión. Tenga en cuenta que si el usuario es un usuario nuevo (es decir, es la primera vez que inicia sesión), Firebase creará automáticamente el usuario en el almacén de autenticación de Firebase. Este es otro ejemplo de la experiencia simplificada que ofrece la autenticación sin contraseña: la creación de cuentas para nuevos usuarios se gestiona automáticamente.
Profile.jsx
El componente final que creará es Profile.jsx
. Los usuarios son dirigidos a este componente cuando inician sesión correctamente a través de Confirm.jsx
. La ruta da la bienvenida al usuario con su dirección de correo electrónico y proporciona un botón para cerrar sesión. Al cerrar sesión, el usuario regresa al componente Login
.
Cree un nuevo archivo Profile.jsx
en el directorio src
.
Agregue el siguiente código:
import { auth } from "./firebase"; import { signOut } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Profile = () => { const navigate = useNavigate(); const logoutUser = async (e) => { e.preventDefault(); await signOut(auth); navigate("/"); } return( <div className = "container"> <div className = "row justify-content-center"> <div className = "col-md-4 text-center"> <p>Welcome <em className = "text-decoration-underline">{ auth.currentUser.email }</em>. You are logged in!</p> <div className = "d-grid gap-2"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => logoutUser(e)}>Logout</button> </div> </div> </div> </div> ) } export default Profile
Profile.jsx
.Inicie la aplicación React:
npm start
locahost:3000
en su navegador si su navegador no se inicia automáticamente. Deberías ver el formulario Login
.
Ingrese el correo electrónico que desea utilizar para iniciar sesión y haga clic en Enviar . Si el envío se realiza correctamente, se mostrará una notificación indicando que se envió un correo electrónico con un enlace de inicio de sesión a su dirección de correo electrónico.
Sign in to project-1078604952662
, donde la secuencia numérica de 13 dígitos representa el messagingSenderId
de su proyecto de Firebase (consulte el Paso 3 de esta guía). En la sección Opcional a continuación, explicaré cómo puede modificar el nombre de su proyecto de Firebase para mostrar un nombre "fácil de usar" en los correos electrónicos con enlaces de inicio de sesión. Por ahora, abra el correo electrónico con el enlace de inicio de sesión y haga clic en el enlace de inicio de sesión. Serás dirigido al formulario Confirm
.
Ingrese la dirección de correo electrónico que utilizó al iniciar sesión en el formulario Confirm
. Haga clic en Confirmar . Si la confirmación es exitosa, será dirigido a la página Profile
.
Haga clic en el botón Cerrar sesión en la página Profile
para cerrar sesión. Si el cierre de sesión se realiza correctamente, se le redirigirá de nuevo al formulario Login
.
Los pasos anteriores capturan el flujo de trabajo de la aplicación.
Puedes cambiar el nombre de tu proyecto para que los correos electrónicos con enlaces de inicio de sesión enviados por Firebase muestren un nombre "fácil de usar" en lugar de, por ejemplo, project-1078604952662
. Inicie sesión en su cuenta de Firebase y haga clic en Ir a la consola .
La autenticación sin contraseña parece ser una opción cada vez más popular entre los desarrolladores de aplicaciones, y es comprensible. Más allá de la ventaja obvia de eliminar la necesidad de administrar contraseñas, tampoco hay necesidad de verificación por correo electrónico, ya que el proceso de envío del enlace de inicio de sesión es una verificación en sí mismo.
Al igual que con el proyecto de requisitos previos, la implementación aquí es básica. Podría considerar mejoras simples como:
Bloquear/poner en lista negra dominios de direcciones de correo electrónico concretos (es decir, dominios de correo electrónico no deseado comunes).
Almacenar localmente la dirección de correo electrónico ingresada por el usuario en la página Login
y verificar la existencia de la dirección de correo electrónico en la página Confirm
. Con este enfoque, si el usuario hace clic en un enlace de inicio de sesión en el mismo dispositivo donde accedió a la página Login
, no necesitará ingresar su dirección de correo electrónico nuevamente en la página Confirm
, ya que se recuperará. del almacenamiento local. Esto proporciona una experiencia de usuario aún más fluida.
Puede obtener más información sobre la autenticación sin contraseña de Firebase a través de la documentación oficial .