Firebase Web (Sign In for Email) not working - javascript

I've been struggling to get Firebase Auth to work for my website. I'm using a local server to run the HTML code.
Firebase is signing up users successfully (they show up in my Firebase console), but it's not signing them in.
I am using this code to check if user is signed in. It always shows "User is not signed in."
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user);
console.log('User is signed in');
} else {
console.log(user);
console.log('User is not signed in');
}
});
I've gone through the documentation and watched the Firecast videos as well as some other tutorials.
My HTML code:
<div class="login w3-display-middle">
<form class="login-container">
<p><input type="text" placeholder="Email" id="email"></p>
<p><input type="password" placeholder="Password" id="password"></p>
<p><button class="w3-blue" id="signin" style="width:100%">LOG IN </button></p>
<p><button class="w3-blue" id="signup" style="width:100%">SIGN UP </button></p>
<p><button class="w3-red" id="signout" style="width:100%">SIGN OUT </button></p>
</form>
</div>
Javascript (included right below the HTML code, before the body tag is closed:
<script src="https://www.gstatic.com/firebasejs/4.5.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: <I have included my apiKey>,
authDomain: <I have included my authDomain>,
databaseURL: <Included my database URL>,
projectId: <Used my project ID>,
storageBucket: <Used this as well>,
messagingSenderId: <And this too>
};
firebase.initializeApp(config);
</script>
<script>
const txtEmail = document.getElementById("email");
const txtPassword = document.getElementById("password");
signin.addEventListener('click', e => {
//Get email and password
const email = txtEmail.value;
const pass = txtPassword.value;
console.log(txtEmail.value);//Shows correct value
console.log(txtPassword.value);//Shows correct value
const promise = firebase.auth().signInWithEmailAndPassword(email, pass);
promise.catch(e => console.log(e.message));
});
signup.addEventListener('click', e => {
//Get email and password
const email = txtEmail.value;
const pass = txtPassword.value;
const auth = firebase.auth();
auth.createUserWithEmailAndPassword(email,pass)
.catch(function(error){
console.log(error.code);
console.log(error.message);
});
});
signout.addEventListener('click',e=> {
firebase.auth().signOut().then(function() {
// Sign-out successful.
})
.catch(function(error) {
console.log(error.code);
console.log(error.message);
});
});
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user);
console.log('User is signed in');
} else {
console.log(user);
console.log('User is not signed in');
}
});
</script>
Really need help figuring this one out. I've spent like 4 hours on it now. Also, when I initially signup the user, it also signs them in (shows up in the Firebase console!). It's just so weird.

Related

Firebase auth password reset

I'm working on a firebase app that contains an authentication system that allows users to sign up/login and create a profile. The app stores and calls profile info about the users. The system worked just fine until I realized there's no way for a user to reset their password. So I added sendPasswordResetEmail function and it's been downhill since then. I'm a newbie to firebase and to StackOverflow so forgive the mess you're about to see. Am I missing something in that function?
const resetpassword = async () => {
const email = document.getElementById('email').value;
try {
const { user } = auth.sendPasswordResetEmail(email);
alert('Password Reset Email Sent!');
}
catch(error) {
console.log("error ===>", error);
if (error.message === "Firebase: Error (auth/user-not-found).") {
alert("There is no user corresponding to this email address.")}
else (errorCode == 'auth/invalid-email') {
alert(errorMessage)}
}
}
If you are using firebase version 9 then use code snippet below to reset user password
import { getAuth, sendPasswordResetEmail } from "firebase/auth";
const auth = getAuth();
sendPasswordResetEmail(auth, email)
.then(() => {
// Password reset email sent!
// ..
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});

Firebase onAuthStateChanged() triggering before retrieving name from signup form?

I'm creating a dashboard using vanilla HTML, CSS and JS, with Firebase as my backend. In my signup.html page, I have a form that allows users to input their name along with their email address and password. Upon signup, users are redirected to dashboard.html with their personalized content. Inside the dashboard, it has a spot where it displays their name.
The problem is it is not always getting the name from the form, and if it doesn't get the user's name from the signup form then it just doesn't have their name as I don't have a "add name" function in the dashboard. I suspect this is because of the way I use the onAuthStateChanged() inside signup.html.
The following is my signup page JS code:
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
window.location.replace('dashboard.html')
} else {
return
}
});
document.querySelector('#signup_btn').addEventListener("click", (e) => {
e.preventDefault();
var user_email = document.getElementById('user_email').value;
var user_pass = document.getElementById('user_pass').value;
var user_name = document.getElementById('user_name').value;
// Sign Up
firebase.auth().createUserWithEmailAndPassword(user_email, user_pass)
// Success
.then((userCredentials) => {
userCredentials.user.updateProfile({
displayName: user_name
})
})
// Errors
.catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode == 'auth/weak-password') {
alert('The password is too weak.');
} else {
alert(errorMessage);
}
console.log(error);
});
})
If it helps, here is the form from my signup.html page:
<form>
<h1>Sign Up</h1>
<!-- <h2>Log into your account using your email address</h2> -->
<label for="user_name">Name</label>
<input type="text" name="name" id="user_name">
<label for="user_email">Email Address</label>
<input type="text" name="email" id="user_email">
<label for="user_pass">Password</label>
<input type="password" name="Password" id="user_pass">
<button type="submit" id="signup_btn">Sign Up</button>
<p>Already have an account? Log In</p>
</form>
It seems like your onAuthStateChanged listener is being triggered before the write to the database has completed. This is the expected behavior for the API, but not what you want here.
Since you do want to use the onAuthStateChanged listener to navigate on page reload, the best I can think off is to turn off the listener when the user clicks the sign up button:
// 👇 store the unsubscribe function in a variable
var unsubscribe = firebase.auth().onAuthStateChanged(function (user) {
if (user) {
window.location.replace('dashboard.html')
} else {
return
}
});
document.querySelector('#signup_btn').addEventListener("click", (e) => {
e.preventDefault();
unsubscribe(); // 👈 turn off auth state listener
var user_email = document.getElementById('user_email').value;
var user_pass = document.getElementById('user_pass').value;
var user_name = document.getElementById('user_name').value;
// Sign Up
firebase.auth().createUserWithEmailAndPassword(user_email, user_pass)
// Success
.then((userCredentials) => {
return userCredentials.user.updateProfile({ // 👈 add a return
displayName: user_name
})
})
.then(() => {
window.location.replace('dashboard.html') // 👈 explicitly navigate here
})
As mentioned in the documentation,
onAuthStateChanged adds an observer for changes to the user's sign-in state.
When the user is logged in, it redirects your user to /dashboard before the updateProfile is resolved resulting in termination of that request.
I don't think you'll need an auth state listener on login page so try refactoring the code like this:
window.onload = function () {
if (firebase.auth().currentUser) window.location.replace("dashboard.html")
// Else stay on this page
// button click events here
}

Firebase authentication and store user in MySQL

I want to know how I can register a user using Firebase authentication, and then proceed to store the user in a MySQL database as well for later use.
I am currently authenticating the user using Firebase, but am not sure how to go about calling a Nodejs API to query the MySQL database.
All the examples I have seen to store users in MySQL are calling the API from the form action itself. However, I want to first authenticate the user with Firebase.
If someone has experience with this I would appreciate the help.
const signupForm = document.querySelector('#sign-up-form');
signupForm.addEventListener('submit', (e) => {
e.preventDefault();
//get user info
const username = signupForm['signup-username'].value;
const email = signupForm['signup-email'].value;
const password = signupForm['signup-password'].value;
//signup the user
auth.createUserWithEmailAndPassword(email, password).then(cred => {
//createUser function returns the user credentials
user = auth.currentUser;
}).then(function () {
user.updateProfile({
displayName: username
})
}).catch((error) => {
//Handle errors
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == 'auth/weak-password') {
alert('The password is too weak.');
} else {
alert(errorMessage);
}
});
})
You need to have some sort of backend to send the user and then use Express or some other server make the query and save to MySQL. You can't do it from the client because it's insecure.
eg:
auth.createUserWithEmailAndPassword(email, password).then(async (user) {
user.updateProfile({
displayName: username
})
const result = await axios.post('/api/saveUser/', user, config)
})

Retrieve document in Firestore and validate against user's entry

I am able to successfully retrieve a document in Firebase Firestore in JavaScript. But would like to validate that document against a user's entry in order to auth that individual into the page.
Using console log I see that I have retrieved the record but it is not matching it against the text inputted by the end user.
How is this accomplished?
I am using Vuejs. And want to password protect one page.
In jsfiddle: https://jsfiddle.net/oL4bondy/4/
HTML
<div v-if="!isLoggedIn">
<h2>Please log in first.</h2>
<div class="form-group">
<form #submit.prevent="validatePin">
<div class="form-group">
<input v-model="password" type="text" class="form-control" placeholder="Enter password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary text-center">Submit</button>
</div>
</form>
</div>
</div>
JS
export default {
name: "add-post",
data() {
return {
password: "",
isLoggedIn: ""
};
},
methods: {
validatePin() {
const docRef = db.collection("passwords").doc("user");
docRef
.get()
.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});
let password = this.doc.data;
if (this.userInput === password) {
this.isLoggedIn = true;
}
}
}
};
Use Firebase.auth() for this. In particular, the .onAuthStateChanged method/listener will fire after page load. That's where you want to process user/UI access.
There are a few problems, but mostly it's related to the fact that the document is loaded from Firestore asynchronously. The solution is to move all the code that needs the document into the then() that is called once the document is loaded. So:
validatePin() {
const docRef = db.collection("passwords").doc("user");
docRef
.get()
.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
let password = this.doc.data;
if (this.userInput === password) {
this.isLoggedIn = true;
// TODO: do whatever needs to happen once the user is logged in
}
} else {
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});
}

Firebase Auth - User not logged in after Firebase sign up and redirect

I am creating an account for a user with firebase. After the account is created, I redirect to the home page, which checks if I am logged in. Oddly enough, I am not logged in.
On Create Account Page:
createAccount() {
firebaseAuth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((user) => {
// write some data to database
firebase.database().ref().child('users').child(user.uid).child('someKey').set(this.state.email).then(function() {
// send email verification
user.sendEmailVerification().then(function() {
console.log("sent email verification");
// Go to home page
this.props.history.push('/home');
}.bind(this)).catch(function(error) {
console.log("Error: account created but no verification email sent.");
}.bind(this));
}.bind(this)).catch((error) => {
console.log('Error: while writing to database');
});
// catch any error while creating user
}).catch((error) => {
console.log('Error: while creating account');
});
}
On Home Page:
componentDidMount() {
firebase.auth().onAuthStateChanged(function (user) {
if (!user) {
console.log("no user logged in");
this.props.history.replace('/login'); // ISSUE: Always redirected to login, even after signup and login
return
} else {
console.log("Woo! User is logged in!");
}
}.bind(this))
}
Alternative attempts:
I have tried explicitly logging the user in after signup, but the same result occurs
replaced this.createAccount with () => this.createAccount for onClick handler (same result)
used firebase.auth() instead of firebaseAuth() (same result)
Does anyone understand why I am not logged in?
** EDIT: **
Below is how I am initializing my app:
<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/4.0.0/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "XXXXXXXXX",
authDomain: "myproject.firebaseapp.com",
databaseURL: "https://myproject.firebaseio.com",
projectId: "XXXXXXXXX",
storageBucket: "XXXXXXXXX.appspot.com",
messagingSenderId: "XXXXXXXXX"
};
firebase.initializeApp(config);
</script>
It may be worth noting: If I sign in with an account that was not just created (or if I wait a while and then sign in to the account I created), there doesn't seem to be an issue with retaining the authorization when redirected. It seems to be that it's only when I create a new user and then redirect that it loses the logged in user.
I have the same setup and it works fine.
I have my auth state change listener at the top of my router...
state = { user: null };
componentDidMount() {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.setState({ user });
} else {
this.props.history.push('/login');
}
});
}
In Login.js I have a form that connects to a login function similar to yours...
login() {
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(res => {
this.props.history.push('/');
})
.catch(err => console.error(error));
}
The only thing that I can think of you gave history.replace, try changing to history.push.
If that doesn't work is there any chance you can set up a https://codesandbox.io/ with a mcve and I'd be happy to debug it https://stackoverflow.com/help/mcve

Categories

Resources