I'm trying to verify an email on Google Firebase without adding credentials to the database.
For example, I want it to acknowledge if an email is typed in the database will say the email cannot be used because it is already in use or is incorrect format. Also, I want it to verify that the password is valid for firebases '6' character passwords. I do not want to add any credentials to the database, only verify that the needs are being met
signUp.addEventListener('click', (e) => {
//check if email and password valid first
//then display verification message
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
// redirect to another page HERE!
const user = userCredential.user;
alert('Credentials are eligible! Complete your account!')
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
alert(errorMessage)
});
here is a sample GUI design, if I clicked verify the email and password would be accepted because these credentials are not into the database using the current code I have. However, I do not want them to be added to the database. I want the verify button to check if the email is already in use and the password meets the parameters then display an alert saying so
If you want to verify email if it already exists without saving data into database, you can use fetchSignInMethodsForEmail method. To display custom error messages you can use Try and catch block as suggested in this documentation.
For Example:
.catch((error) => {
if (error.code == "Firebase: auth error") {
alert("The email address is already in use");
}
To display detailed useful error messages use functions.https.HttpsError.
For more information have a look at these thread1 &thread2.
Related
I am using the Capacitor-Firebase/authentication plugin in my application.
My goal
I am trying to turn an Anonymous user into a user with either credentials (email/password).
Also, I want to have his e-mail verified.
My approach
My approach was to use the EmailLink functionality and then trying to convert it to a user with email and password like the following:
I have successfully signed in a user using the following code from the docs:
const signInWithEmailLink = async () => {
const credential = EmailAuthProvider.credentialWithLink(email, emailLink);
const auth = getAuth();
const result = await signInWithCredential(auth, credential);
return result.user;
};
Later, I want to convert this to a user with email and password.
I am trying to do this with FirebaseAuthentication.updatePassword({ newPassword: password.value }).
My Problem
This does not work because IMO after using signInWithCredential the state of the user is different in the native layer than in the web layer. In the native layer the user is still an Anonymous user so FirebaseAuthentication.updatePassword() won't work.
I also tried the following to try to associate a username/password:
const credential = EmailAuthProvider.credential(email.value, password.value)
const auth = getAuth()
// https://firebase.google.com/docs/auth/web/account-linking
linkWithCredential(auth.currentUser, credential)
This fails with the following error: auth/provider-already-linked.
I finally found the solution myself:
An EmailLink account is just a flavor account of an Email/Password-Account which does not have a password.
So, if I am in Capacitor, I have to do the following to add the password:
const auth = getAuth()
updatePassword(auth.currentUser!, password)
On the web, the following command works:
FirebaseAuthentication.updatePassword({ newPassword: password })
I am currently working on a project where the parking lot owners should use website login and other users should use mobile app login.
But currently any user can login into both of the website and mobile app.
here is my firebase realtime database
my realtime database
So as you can see I defined type in user. when signing up a user gets a type depending on the device he/she registering
and my web sign in function is like this:
signInWithEmailAndPassword(auth, email, password).then((userCredential) => {
const user = userCredential.user;
alert('User Logged in!');
window.location = 'user.html';
}).catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert(errorMessage);
});
How can I provide login for the users which have 'type = web' ?
Firebase Authentication only cares about credentials: if the email/password you enter matches the data in the system, you can sign in - no matter what platform you're on. There is no way to change this in Firebase Authentication, so any additional logic will have to come from your application code.
For example, you could store a list of the UIDs of the parking lot owners, and check against that after signing in to allow then to use the web app or not.
signInWithEmailAndPassword(auth, email, password).then((userCredential) => {
const user = userCredential.user;
if (user) {
const uid = user.uid; // determine the UID of the user
const ownersRef = firebase.database().ref("parkinglotOwners");
const userSnapshot = await ownersRef.child(uid).get(); // try to load this users data from parkinglotOwners
if (userSnapshot.exists()) { // if this data exists
window.location = 'user.html'; // send them to the web app
} else {
alert("You're not allowed to use this app"; // tell them to go away
}
}
...
}).catch((error) => {
Firebase Auth is about authentication (are you the person you said you are).
Your need is more about Access Control. There is a feature in Firebase that may help with that. It's called "custom claims" and allow you to perform Claim-Based Access control.
see this video: https://www.youtube.com/watch?v=3hj_r_N0qMs
$("#btn1").on('click', function(e) {
e.preventDefault(); // <== disable form submit
const email = signupForm['signup-email'].value;
const password = signupForm['signup-password'].value;
// sign up the user & add firestore data
const auth = firebase.auth();
const promise = auth.createUserWithEmailAndPassword(email, password);
promise.then(user => {
user = firebase.auth().currentUser;
user.sendEmailVerification();
}).catch(error => console.log);
});
$("#btn2").on('click', function(e) {
e.preventDefault(); // <== disable form submit
var user = firebase.auth().currentUser;
if (user.emailVerified) {
// email is verified.
console.log("email is verified")
} else {
// email is not verified.
console.log("email is not verified")
}
});
I want that my Website sends an email to the user after the user enters his email and password.
In my Code, user.sendEmailVerification(); works fine and the user gets an email.
If the user verifies his email and clicks the btn2, the console should print "email is verified", but this doesn't happen. The console always prints "email is not verified". I tried also the firebase.auth().onAuthStateChanged method, but it's the same.
var user = firebase.auth().currentUser;
firebase.auth().onAuthStateChanged(user => {
if(user.emailVerified){
console.log('email is verified')
}else{
console.log('email not verified')
}
})
Verifying the email address happens out-of-band, typically in another tab of the same browser or in another application altogether. This means that your application code isn't immediately made aware of the update to the user's profile, but only once one of these things happens:
Their ID token is auto-refreshed, which happens every hour.
When the user logs out and logs in again.
When you force to refresh the ID token in your application code by calling reload on their user profile.
Once any of these happens, the user profile will contain the latest information from the server, including the user's email verification state.
Also see:
Angular firebase email verification false after verify
Android Firebase AuthStateListener Email Verified
Can I get updated emailVerified without logging out?
user.emailVerified doesn't change after clicking email verification link firebase
On the process of authentication, you are redirected to the auth server, and gets back to the page. The onAuthStageChange it's a observer to that redirection, you don't need to trigger an event, since when it's a realtime event.
I'm trying to implement an SMS password reset where the user is sent an OTP which they use as verification code to reset their password. After resetting and saving the user's new password, I am still unable to login with that new password, and only the old passwords work.
I have used the setPassword method, I have tried using user.set('password', value) which also does not work, and saving the user object with user.save(null, { useMasterKey: true }). Has anyone been able to implement their own password reset flow? Or you're supposed to strictly use the inbuilt email password reset flow?
This is the specific code I used for resetting the password
const user = await Parse.Query
.or(
User.query.equalTo('resetToken', request.body.resetToken),
User.query.equalTo('resetCode', request.body.resetToken)
)
.first();
if (!user){
throw new Error('User does not exist');
}
user.setPassword(request.body.password);
// deleting resetToken && resetCode
user.unset('resetCode');
user.unset('resetToken');
await user.save(null, {useMasterKey: true});
As a user signs up to our app, I want them to know whether the email they are trying to sign up with already exists, without having to submit the form (A.K.A on blur of the email field). As it stands, the user has to enter their details and click signup before it let's them know whether the email is taken or not.
The required behaviour can be observed with spotify signup where you enter the email, and as soon as you click away you see the following:
So far, I have written a cloud function (http) that is triggered on blur that calls the getUserByEmail function from firestore admin auth. The function is as follows:
export const checkUserEmail = https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const email = req.body.email;
await admin.auth().getUserByEmail(email);
res.send({status: 200});
return;
} catch(e) {
return Helpers._handleError(res, 400, e.message);
}
})
});
This does work as I can now check at this moment whether or not an email exists, however the problem is it takes anywhere between 3-10 seconds to validate (long enough for the user to get deeper into the signup process).
Is there a way to either:
Speed up the cloud function or
Validate whether a user has already authenticated with the email provided directly on the client side with firestore?
Thanks in advance
You can use a users collection, which you may be doing already. This can store user information and often proves to be really handle since the auth user can't be updated with fields it doesn't how out of the box.
You can store users' emails here and check the collection for the user's input compared to the email field of the users collection here.