Compartir en Twitter
Go to Homepage

AUTENTICACIÓN EN REACT CON FIREBASE V9

November 10, 2025

Introducción a la autenticación con React y Firebase

La autenticación es un componente esencial en aplicaciones web modernas, ya que garantiza que solo los usuarios autorizados accedan a ciertas funcionalidades. Este tutorial explica cómo implementar autenticación en React con Firebase V9, utilizando herramientas como React Router V6 para la navegación, Material UI para formularios y React Toastify para notificaciones de errores. Se cubrirá la creación de formularios de inicio de sesión y registro, la configuración de Firebase, la implementación de rutas privadas basadas en sesiones y el manejo de errores. Este contenido está diseñado para desarrolladores que deseen integrar autenticación robusta en sus aplicaciones React.

Configuración inicial del proyecto

Para comenzar, se necesita un entorno con Node.js instalado. Descargue e instale Node.js desde su sitio oficial si no lo tiene. Luego, cree un proyecto React ejecutando el siguiente comando en la terminal:

npx create-react-app react-firebase-v9

Navegue al directorio del proyecto y ejecute el servidor de desarrollo:

cd react-firebase-v9
npm start

Esto iniciará la aplicación, mostrando la página predeterminada de React. Limpie el contenido de src/App.js para preparar el espacio para los formularios de autenticación.

La estructura inicial del proyecto será:

react-firebase-v9/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── index.js
│   └── Components/
│       └── Common/

Instalación de dependencias necesarias

Instale las dependencias requeridas para el proyecto: Firebase V9, React Router V6, Material UI y React Toastify. Ejecute los siguientes comandos:

npm install firebase react-router-dom @mui/material @emotion/react @emotion/styled react-toastify

Material UI se utiliza para crear formularios estilizados, React Router para manejar la navegación, Firebase para la autenticación y React Toastify para mostrar mensajes de error.

Creación de formularios de login y registro

Cree una carpeta Components/Common dentro de src para almacenar componentes reutilizables. Dentro de esta carpeta, cree un archivo Form.js para el formulario de autenticación:

import * as React from "react";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";

export default function Form({ title }) {
    return (
        <div>
            <div className="heading-container">
                <h3>{title} Form</h3>
            </div>
            <Box
                component="form"
                sx={{ "& > :not(style)": { m: 1, width: "25ch" } }}
                noValidate
                autoComplete="off"
            >
                <TextField
                    id="email"
                    label="Enter the Email"
                    variant="outlined"
                />
                <TextField
                    id="password"
                    label="Enter the Password"
                    variant="outlined"
                />
            </Box>
        </div>
    );
}

Cree también un componente Button.js en la misma carpeta para un botón reutilizable:

import * as React from "react";
import Button from "@mui/material/Button";

export default function BasicButton({ title }) {
    return <Button variant="contained">{title}</Button>;
}

Actualice Form.js para incluir el botón:

import * as React from "react";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import Button from "./Button";

export default function Form({ title }) {
    return (
        <div>
            <div className="heading-container">
                <h3>{title} Form</h3>
            </div>
            <Box
                component="form"
                sx={{ "& > :not(style)": { m: 1, width: "25ch" } }}
                noValidate
                autoComplete="off"
            >
                <TextField
                    id="email"
                    label="Enter the Email"
                    variant="outlined"
                />
                <TextField
                    id="password"
                    label="Enter the Password"
                    variant="outlined"
                />
            </Box>
            <Button title={title} />
        </div>
    );
}

Importe el formulario en App.js:

import "./App.css";
import Form from "./Components/Common/Form";

function App() {
    return (
        <div className="App">
            <Form title="Login" />
        </div>
    );
}

export default App;

Configuración de Firebase

Cree un proyecto en la consola de Firebase. Haga clic en “Agregar proyecto”, asigne un nombre y siga los pasos para registrar una aplicación web. Firebase proporcionará un objeto de configuración que debe guardarse en un archivo firebase-config.js:

import { initializeApp } from "firebase/app";

const firebaseConfig = {
    apiKey: "SU_API_KEY",
    authDomain: "SU_AUTH_DOMAIN",
    projectId: "SU_PROJECT_ID",
    storageBucket: "SU_STORAGE_BUCKET",
    messagingSenderId: "SU_MESSAGING_SENDER_ID",
    appId: "SU_APP_ID",
    measurementId: "SU_MEASUREMENT_ID",
};

export const app = initializeApp(firebaseConfig);

Reemplace los valores con los proporcionados por Firebase. En la consola de Firebase, habilite el método de autenticación por correo electrónico y contraseña en la sección “Authentication”.

Configuración de rutas con React Router

Configure las rutas para las páginas de login, registro y una página principal protegida. En index.js, envuelva la aplicación con BrowserRouter:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <React.StrictMode>
        <Router>
            <App />
        </Router>
    </React.StrictMode>
);

En App.js, configure las rutas para login y registro, pasando props al componente Form:

import { useState } from "react";
import "./App.css";
import Form from "./Components/Common/Form";
import { Routes, Route } from "react-router-dom";

function App() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");

    return (
        <div className="App">
            <Routes>
                <Route
                    path="/login"
                    element={
                        <Form
                            title="Login"
                            setEmail={setEmail}
                            setPassword={setPassword}
                        />
                    }
                />
                <Route
                    path="/register"
                    element={
                        <Form
                            title="Register"
                            setEmail={setEmail}
                            setPassword={setPassword}
                        />
                    }
                />
            </Routes>
        </div>
    );
}

export default App;

Manejo de datos en formularios

Actualice Form.js para manejar los datos de entrada usando los estados pasados como props:

import * as React from "react";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import Button from "./Button";

export default function Form({ title, setEmail, setPassword, handleAction }) {
    return (
        <div>
            <div className="heading-container">
                <h3>{title} Form</h3>
            </div>
            <Box
                component="form"
                sx={{ "& > :not(style)": { m: 1, width: "25ch" } }}
                noValidate
                autoComplete="off"
            >
                <TextField
                    id="email"
                    label="Enter the Email"
                    variant="outlined"
                    onChange={(e) => setEmail(e.target.value)}
                />
                <TextField
                    id="password"
                    label="Enter the Password"
                    variant="outlined"
                    onChange={(e) => setPassword(e.target.value)}
                />
            </Box>
            <Button title={title} handleAction={handleAction} />
        </div>
    );
}

Actualice Button.js para manejar el evento onClick:

import * as React from "react";
import Button from "@mui/material/Button";

export default function BasicButton({ title, handleAction }) {
    return (
        <Button variant="contained" onClick={handleAction}>
            {title}
        </Button>
    );
}

En App.js, cree una función handleAction para distinguir entre login y registro:

import { useState } from "react";
import "./App.css";
import Form from "./Components/Common/Form";
import { Routes, Route } from "react-router-dom";

function App() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");

    const handleAction = (id) => {
        console.log(id);
    };

    return (
        <div className="App">
            <Routes>
                <Route
                    path="/login"
                    element={
                        <Form
                            title="Login"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(1)}
                        />
                    }
                />
                <Route
                    path="/register"
                    element={
                        <Form
                            title="Register"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(2)}
                        />
                    }
                />
            </Routes>
        </div>
    );
}

export default App;

Implementación de funciones de Firebase

Importe las funciones de autenticación de Firebase en App.js:

import {
    getAuth,
    signInWithEmailAndPassword,
    createUserWithEmailAndPassword,
} from "firebase/auth";
import { app } from "./firebase-config";

Actualice handleAction para manejar el registro:

const handleAction = (id) => {
    const authentication = getAuth();
    if (id === 2) {
        createUserWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                console.log(response);
            })
            .catch((error) => {
                console.log(error);
            });
    }
};

Almacenamiento del token en session storage

Para implementar rutas privadas, almacene el token de autenticación en sessionStorage:

const handleAction = (id) => {
    const authentication = getAuth();
    if (id === 2) {
        createUserWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                sessionStorage.setItem(
                    "Auth Token",
                    response._tokenResponse.refreshToken
                );
            })
            .catch((error) => {
                console.log(error);
            });
    }
};

Cree un componente Home.js para la página protegida:

import React from "react";

export default function Home() {
    return <div>Home Page</div>;
}

Agregue una ruta para /home en App.js y use useNavigate para redirigir tras el registro:

import { useState } from "react";
import "./App.css";
import Form from "./Components/Common/Form";
import Home from "./Components/Home";
import { Routes, Route, useNavigate } from "react-router-dom";
import {
    getAuth,
    signInWithEmailAndPassword,
    createUserWithEmailAndPassword,
} from "firebase/auth";
import { app } from "./firebase-config";

function App() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const navigate = useNavigate();

    const handleAction = (id) => {
        const authentication = getAuth();
        if (id === 2) {
            createUserWithEmailAndPassword(authentication, email, password)
                .then((response) => {
                    sessionStorage.setItem(
                        "Auth Token",
                        response._tokenResponse.refreshToken
                    );
                    navigate("/home");
                })
                .catch((error) => {
                    console.log(error);
                });
        }
    };

    return (
        <div className="App">
            <Routes>
                <Route
                    path="/login"
                    element={
                        <Form
                            title="Login"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(1)}
                        />
                    }
                />
                <Route
                    path="/register"
                    element={
                        <Form
                            title="Register"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(2)}
                        />
                    }
                />
                <Route path="/home" element={<Home />} />
            </Routes>
        </div>
    );
}

export default App;

Creación de rutas privadas

En Home.js, use useEffect para verificar la existencia del token:

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";

export default function Home() {
    const navigate = useNavigate();

    useEffect(() => {
        const authToken = sessionStorage.getItem("Auth Token");
        if (!authToken) {
            navigate("/login");
        }
    }, [navigate]);

    return <div>Home Page</div>;
}

En App.js, agregue una verificación similar para redirigir a /home si el usuario está autenticado:

import { useState, useEffect } from "react";
import "./App.css";
import Form from "./Components/Common/Form";
import Home from "./Components/Home";
import { Routes, Route, useNavigate } from "react-router-dom";
import {
    getAuth,
    signInWithEmailAndPassword,
    createUserWithEmailAndPassword,
} from "firebase/auth";
import { app } from "./firebase-config";

function App() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const navigate = useNavigate();

    useEffect(() => {
        const authToken = sessionStorage.getItem("Auth Token");
        if (authToken) {
            navigate("/home");
        }
    }, [navigate]);

    const handleAction = (id) => {
        const authentication = getAuth();
        if (id === 2) {
            createUserWithEmailAndPassword(authentication, email, password)
                .then((response) => {
                    sessionStorage.setItem(
                        "Auth Token",
                        response._tokenResponse.refreshToken
                    );
                    navigate("/home");
                })
                .catch((error) => {
                    console.log(error);
                });
        }
    };

    return (
        <div className="App">
            <Routes>
                <Route
                    path="/login"
                    element={
                        <Form
                            title="Login"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(1)}
                        />
                    }
                />
                <Route
                    path="/register"
                    element={
                        <Form
                            title="Register"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(2)}
                        />
                    }
                />
                <Route path="/home" element={<Home />} />
            </Routes>
        </div>
    );
}

export default App;

Implementación del inicio de sesión

Agregue la funcionalidad de inicio de sesión en handleAction:

const handleAction = (id) => {
    const authentication = getAuth();
    if (id === 1) {
        signInWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                sessionStorage.setItem(
                    "Auth Token",
                    response._tokenResponse.refreshToken
                );
                navigate("/home");
            })
            .catch((error) => {
                console.log(error);
            });
    } else if (id === 2) {
        createUserWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                sessionStorage.setItem(
                    "Auth Token",
                    response._tokenResponse.refreshToken
                );
                navigate("/home");
            })
            .catch((error) => {
                console.log(error);
            });
    }
};

Manejo de errores con React Toastify

Configure React Toastify para mostrar mensajes de error. En App.js, importe los componentes necesarios y agregue el contenedor de notificaciones:

import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

function App() {
    // ... resto del código ...
    return (
        <div className="App">
            <Routes>
                <Route
                    path="/login"
                    element={
                        <Form
                            title="Login"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(1)}
                        />
                    }
                />
                <Route
                    path="/register"
                    element={
                        <Form
                            title="Register"
                            setEmail={setEmail}
                            setPassword={setPassword}
                            handleAction={() => handleAction(2)}
                        />
                    }
                />
                <Route path="/home" element={<Home />} />
            </Routes>
            <ToastContainer />
        </div>
    );
}

Actualice handleAction para manejar errores específicos:

const handleAction = (id) => {
    const authentication = getAuth();
    if (id === 1) {
        signInWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                sessionStorage.setItem(
                    "Auth Token",
                    response._tokenResponse.refreshToken
                );
                navigate("/home");
            })
            .catch((error) => {
                if (error.code === "auth/wrong-password") {
                    toast.error("Please check the Password");
                }
                if (error.code === "auth/user-not-found") {
                    toast.error("Please check the Email");
                }
            });
    } else if (id === 2) {
        createUserWithEmailAndPassword(authentication, email, password)
            .then((response) => {
                sessionStorage.setItem(
                    "Auth Token",
                    response._tokenResponse.refreshToken
                );
                navigate("/home");
            })
            .catch((error) => {
                if (error.code === "auth/email-already-in-use") {
                    toast.error("Email Already in Use");
                }
            });
    }
};

Implementación del cierre de sesión

En Home.js, agregue un botón para cerrar sesión:

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";

export default function Home() {
    const navigate = useNavigate();

    const handleLogout = () => {
        sessionStorage.removeItem("Auth Token");
        navigate("/login");
    };

    useEffect(() => {
        const authToken = sessionStorage.getItem("Auth Token");
        if (!authToken) {
            navigate("/login");
        }
    }, [navigate]);

    return (
        <div>
            Home Page
            <button onClick={handleLogout}>Log out</button>
        </div>
    );
}

Conclusiones

Este tutorial ha cubierto la implementación de un sistema de autenticación completo en una aplicación React utilizando Firebase V9. Se han creado formularios de login y registro con Material UI, configurado rutas con React Router V6, gestionado sesiones con sessionStorage y manejado errores con React Toastify. Este enfoque proporciona una base sólida para aplicaciones web seguras y escalables. Los desarrolladores pueden extender esta funcionalidad agregando características como recuperación de contraseñas o autenticación con proveedores externos.