Recently, I've been working on an exciting e-commerce platform that combines features from StockX and eBay. As this is my first major project, I was particularly motivated to build everything from scratch. However, my journey with implementing user authentication taught me some valuable lessons about choosing between manual authentication and Firebase Auth.
The Manual Authentication Approach
Initially, I attempted to implement authentication manually while still planning to use Firebase for data storage. My original implementation looked something like this:
Create a signup process that would:
Collect user data from a form
Generate a JWT token
Store user data in Firebase
Implement a login process that would:
Verify user credentials against the database
Authenticate with the JWT token
Redirect to the home page upon success
Here's what the initial implementation looked like:
const submitFormData = async (path, data) => {
// Store JWT token
localStorage.setItem("token", responseData.data.token);
console.log("Redirecting to home page");
location.replace("/");
};
subBtn.addEventListener("click", () => {
// Form validation
if (!tac.checked) {
showAlert("you must agree to our terms and conditions");
} else {
loader.style.display = "block";
submitFormData("/signup", {
name: name.value,
email: email.value,
password: password.value,
number: number.value,
tac: tac.checked,
notification: notification.checked,
seller: false
});
}
});
The Challenge
While this code worked initially, I hit a significant roadblock when trying to fetch user data from Firebase. The user object consistently returned null, indicating that the user wasn't found. After an hour of troubleshooting and research, I discovered that Firebase Auth offered a more streamlined solution.
The Firebase Auth Solution
Switching to Firebase Auth simplified the process considerably. Here's how the improved implementation works:
Signup Process
const auth = getAuth();
createUserWithEmailAndPassword(auth, email.value, password.value)
.then((userCredential) => {
const user = userCredential.user;
loader.style.display = "block";
return submitFormData("/signup", {
name: name.value,
email: email.value,
password: password.value,
number: number.value,
tac: tac.checked,
notification: notification.checked,
seller: false
});
})
.catch((error) => {
showAlert(error.message);
});
Login Process
signInWithEmailAndPassword(auth, email.value, password.value)
.then((userCredential) => {
const user = userCredential.user;
loader.style.display = "block";
return submitFormData("/login", {
email: email.value,
password: password.value
});
})
.catch((error) => {
showAlert(error.message);
});
Key Components Explained
Authentication Setup: The getAuth()
method initializes Firebase Authentication, handling the complex security mechanisms behind the scenes.
User Creation: createUserWithEmailAndPassword()
manages the entire signup process, including:
Email validation
Password security
User creation in Firebase Auth
Automatic session management
User Sign-in: signInWithEmailAndPassword()
provides:
Secure credential verification
Session management
Error handling for invalid credentials
Lessons Learned
While building authentication from scratch can be educational, Firebase Auth provides a robust, tested solution that handles many edge cases and security concerns automatically.
Firebase Auth integrates seamlessly with Firestore, making it easier to manage user data and authentication state in sync.
The built-in error handling and security features of Firebase Auth save significant development time and reduce potential security risks.
Remember, when building a production application, it's often better to use battle-tested authentication solutions like Firebase Auth rather than implementing everything from scratch. This allows you to focus on building your application's unique features while ensuring security best practices are followed.
Top comments (0)