Firebase Authentication in React: A Simple Step-by-Step Guide
Firebase Authentication in React: A Simple Step-by-Step Guide Authentication is a fundamental requirement for most web applications. In this tutorial, I'll walk you through implementing Firebase Authentication in a React application without using the Context API. We'll create sign-up and sign-in pages and set up navigation to a home page after successful authentication. What We'll Build A React application with Firebase Authentication Sign-up page for new users Sign-in page for existing users Protected home page that requires authentication Simple navigation between these pages Prerequisites Basic knowledge of React Node.js and npm installed on your computer A Google account to set up Firebase Step 1: Set Up a New React Project Let's start by creating a new React application: npx create-react-app firebase-auth-app cd firebase-auth-app Step 2: Install Required Dependencies We'll need to install Firebase and React Router: npm install firebase react-router-dom Step 3: Create a Firebase Project Go to the Firebase Console Click "Add project" and follow the setup instructions Once your project is created, click on the web icon () to add a web app to your project Register your app with a nickname (e.g., "firebase-auth-app") Copy the Firebase configuration object that looks like this: const firebaseConfig = { apiKey: "your-api-key", authDomain: "your-project-id.firebaseapp.com", projectId: "your-project-id", storageBucket: "your-project-id.appspot.com", messagingSenderId: "your-messaging-sender-id", appId: "your-app-id" }; Step 4: Enable Authentication Methods in Firebase In the Firebase Console, navigate to "Authentication" in the left sidebar Click on "Get started" Enable "Email/Password" authentication by clicking on it and toggling the switch to "Enable" Click "Save" Step 5: Set Up Firebase in Your React App Create a new file src/firebase.js to initialize Firebase: // src/firebase.js import { initializeApp } from 'firebase/app'; import { getAuth } from 'firebase/auth'; const firebaseConfig = { // Replace with your Firebase config object apiKey: "your-api-key", authDomain: "your-project-id.firebaseapp.com", projectId: "your-project-id", storageBucket: "your-project-id.appspot.com", messagingSenderId: "your-messaging-sender-id", appId: "your-app-id" }; // Initialize Firebase const app = initializeApp(firebaseConfig); export const auth = getAuth(app); export default app; Step 6: Create the Sign-Up Component // src/components/Signup.js import React, { useState } from 'react'; import { createUserWithEmailAndPassword } from 'firebase/auth'; import { auth } from '../firebase'; import { Link, useNavigate } from 'react-router-dom'; function Signup() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const navigate = useNavigate(); async function handleSubmit(e) { e.preventDefault(); if (password !== confirmPassword) { return setError('Passwords do not match'); } try { setError(''); setLoading(true); await createUserWithEmailAndPassword(auth, email, password); navigate('/'); } catch (error) { setError('Failed to create an account: ' + error.message); } setLoading(false); } return ( Sign Up {error && {error}} Email setEmail(e.target.value)} required /> Password setPassword(e.target.value)} required /> Confirm Password setConfirmPassword(e.target.value)} required /> Sign Up Already have an account? Log In ); } export default Signup; Step 7: Create the Login Component // src/components/Login.js import React, { useState } from 'react'; import { signInWithEmailAndPassword } from 'firebase/auth'; import { auth } from '../firebase'; import { Link, useNavigate } from 'react-router-dom'; function Login() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const navigate = useNavigate(); async function handleSubmit(e) { e.preventDefault(); try { setError(''); setLoading(true); await signInWithEmailAndPassword(auth, email, password); navigate('/'); } catch (error) { setError('Failed to log in: ' + error.message); } setLoading(false); } return (

Firebase Authentication in React: A Simple Step-by-Step Guide
Authentication is a fundamental requirement for most web applications. In this tutorial, I'll walk you through implementing Firebase Authentication in a React application without using the Context API. We'll create sign-up and sign-in pages and set up navigation to a home page after successful authentication.
What We'll Build
- A React application with Firebase Authentication
- Sign-up page for new users
- Sign-in page for existing users
- Protected home page that requires authentication
- Simple navigation between these pages
Prerequisites
- Basic knowledge of React
- Node.js and npm installed on your computer
- A Google account to set up Firebase
Step 1: Set Up a New React Project
Let's start by creating a new React application:
npx create-react-app firebase-auth-app
cd firebase-auth-app
Step 2: Install Required Dependencies
We'll need to install Firebase and React Router:
npm install firebase react-router-dom
Step 3: Create a Firebase Project
- Go to the Firebase Console
- Click "Add project" and follow the setup instructions
- Once your project is created, click on the web icon (>) to add a web app to your project
- Register your app with a nickname (e.g., "firebase-auth-app")
- Copy the Firebase configuration object that looks like this:
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-project-id.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project-id.appspot.com",
messagingSenderId: "your-messaging-sender-id",
appId: "your-app-id"
};
Step 4: Enable Authentication Methods in Firebase
- In the Firebase Console, navigate to "Authentication" in the left sidebar
- Click on "Get started"
- Enable "Email/Password" authentication by clicking on it and toggling the switch to "Enable"
- Click "Save"
Step 5: Set Up Firebase in Your React App
Create a new file src/firebase.js
to initialize Firebase:
// src/firebase.js
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
// Replace with your Firebase config object
apiKey: "your-api-key",
authDomain: "your-project-id.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project-id.appspot.com",
messagingSenderId: "your-messaging-sender-id",
appId: "your-app-id"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export default app;
Step 6: Create the Sign-Up Component
// src/components/Signup.js
import React, { useState } from 'react';
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../firebase';
import { Link, useNavigate } from 'react-router-dom';
function Signup() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
async function handleSubmit(e) {
e.preventDefault();
if (password !== confirmPassword) {
return setError('Passwords do not match');
}
try {
setError('');
setLoading(true);
await createUserWithEmailAndPassword(auth, email, password);
navigate('/');
} catch (error) {
setError('Failed to create an account: ' + error.message);
}
setLoading(false);
}
return (
<div className="signup-container">
<div className="signup-form">
<h2>Sign Up</h2>
{error && <div className="error-message">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Email</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<div className="form-group">
<label>Confirm Password</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
/>
</div>
<button disabled={loading} type="submit" className="submit-button">
Sign Up
</button>
</form>
<div className="login-link">
Already have an account? <Link to="/login">Log In</Link>
</div>
</div>
</div>
);
}
export default Signup;
Step 7: Create the Login Component
// src/components/Login.js
import React, { useState } from 'react';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../firebase';
import { Link, useNavigate } from 'react-router-dom';
function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
async function handleSubmit(e) {
e.preventDefault();
try {
setError('');
setLoading(true);
await signInWithEmailAndPassword(auth, email, password);
navigate('/');
} catch (error) {
setError('Failed to log in: ' + error.message);
}
setLoading(false);
}
return (
<div className="login-container">
<div className="login-form">
<h2>Log In</h2>
{error && <div className="error-message">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Email</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<button disabled={loading} type="submit" className="submit-button">
Log In
</button>
</form>
<div className="signup-link">
Need an account? <Link to="/signup">Sign Up</Link>
</div>
</div>
</div>
);
}
export default Login;
Step 8: Create the Home Component
// src/components/Home.js
import React, { useState, useEffect } from 'react';
import { onAuthStateChanged, signOut } from 'firebase/auth';
import { auth } from '../firebase';
import { useNavigate } from 'react-router-dom';
function Home() {
const [currentUser, setCurrentUser] = useState(null);
const navigate = useNavigate();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
setCurrentUser(user);
} else {
navigate('/login');
}
});
return () => unsubscribe();
}, [navigate]);
async function handleLogout() {
try {
await signOut(auth);
navigate('/login');
} catch (error) {
console.error('Failed to log out:', error);
}
}
if (!currentUser) return <div>Loading...</div>;
return (
<div className="home-container">
<h2>Welcome to Your Dashboard!</h2>
<p>You are logged in as: {currentUser.email}</p>
<button onClick={handleLogout} className="logout-button">
Log Out
</button>
</div>
);
}
export default Home;
Step 9: Create a Simple Auth Check Component
Instead of using the Context API, we'll create a simple component to check if a user is authenticated:
// src/components/AuthCheck.js
import React, { useState, useEffect } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../firebase';
import { Navigate } from 'react-router-dom';
function AuthCheck({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setIsAuthenticated(!!user);
setIsLoading(false);
});
return () => unsubscribe();
}, []);
if (isLoading) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return children;
}
export default AuthCheck;
Step 10: Set Up App Routing
Now, let's update the main App component to include all our routes:
// src/App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import AuthCheck from './components/AuthCheck';
import Signup from './components/Signup';
import Login from './components/Login';
import Home from './components/Home';
import './App.css';
function App() {
return (
<Router>
<div className="app-container">
<Routes>
<Route path="/" element={
<AuthCheck>
<Home />
</AuthCheck>
} />
<Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login />} />
</Routes>
</div>
</Router>
);
}
export default App;
Step 11: Add Basic CSS Styling
Let's add some minimal CSS to make our app look decent:
/* src/App.css */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
}
.app-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.signup-container,
.login-container,
.home-container {
background-color: white;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 20px;
width: 100%;
max-width: 400px;
}
h2 {
text-align: center;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.submit-button,
.logout-button {
width: 100%;
padding: 10px;
background-color: #4285f4;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
margin-top: 10px;
}
.submit-button:hover,
.logout-button:hover {
background-color: #357ae8;
}
.submit-button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.error-message {
background-color: #ffebee;
color: #c62828;
padding: 10px;
border-radius: 4px;
margin-bottom: 15px;
text-align: center;
}
.login-link,
.signup-link {
text-align: center;
margin-top: 15px;
}
.home-container p {
margin-bottom: 20px;
}
Step 12: Run and Test Your Application
Now let's run the application and test our authentication flow:
npm start
Your React application should open in your default browser at http://localhost:3000
.
Testing the Flow
Let's test our authentication flow to make sure everything works as expected:
-
Sign-up flow:
- Navigate to
/signup
- Create a new account with email and password
- After successful registration, you should be redirected to the home page
- Navigate to
-
Login flow:
- Log out from the home page
- You should be redirected to the login page
- Enter your credentials
- After successful login, you should be redirected to the home page
-
Authentication protection:
- Try accessing the home page (
/
) directly when not logged in - You should be redirected to the login page
- Try accessing the home page (
Understanding How It Works
Authentication Flow
Firebase Setup: We initialize Firebase and its authentication service in
firebase.js
.-
Sign Up:
- When a user submits the sign-up form, we call Firebase's
createUserWithEmailAndPassword
function - If successful, we navigate to the home page
- If there's an error, we display it to the user
- When a user submits the sign-up form, we call Firebase's
-
Login:
- When a user submits the login form, we call Firebase's
signInWithEmailAndPassword
function - If successful, we navigate to the home page
- If there's an error, we display it to the user
- When a user submits the login form, we call Firebase's
-
Authentication Check:
- We use Firebase's
onAuthStateChanged
to listen for authentication state changes - In the
AuthCheck
component, we redirect unauthenticated users to the login page - In the
Home
component, we use this to get the current user's information
- We use Firebase's
-
Logout:
- When a user clicks the logout button, we call Firebase's
signOut
function - After logging out, we redirect the user to the login page
- When a user clicks the logout button, we call Firebase's
Common Issues and Troubleshooting
Firebase Initialization Errors
If you see an error like "Firebase App named '[DEFAULT]' already exists", make sure you're only initializing Firebase once in your application.
Authentication Errors
- Check that you've enabled Email/Password authentication in the Firebase Console
- Make sure password meets Firebase's minimum requirements (at least 6 characters)
- Verify that you're using the correct Firebase configuration
Routing Issues
- Ensure all routes are properly defined in
App.js
- Verify that
AuthCheck
is correctly protecting your routes
Next Steps
Now that you have a basic authentication system in place, you might want to:
- Add password reset functionality
- Implement social media login options (Google, Facebook, etc.)
- Create a user profile page with more information
- Add email verification
- Implement more robust error handling
Conclusion
You've successfully built a React application with Firebase Authentication! You now have functional sign-up and sign-in pages that redirect users to a protected home page after successful authentication.
This implementation uses a straightforward approach without the Context API, making it easier to understand and maintain. You can build upon this foundation to create more complex applications with user authentication.
Happy coding!