I'm developing an authentication system for my React app with Firebase Auth. When the user signs up, firebase auth registers the user (createUserWithEmailAndPassword) and returns a promise with auth.uid and auth.emailVerified set to "false". This is fine.
I then use sendEmailVerification() method so the email address can be verified. I've tested the code and it works ok for a "valid" and "existing" email address. "catch" does give error for duplicate email address as expected. The problem is, it does not send the NON-EXISTING email (which I suppose is the correct bahaviour) but its should then give an error (so I can display to the user) which it does not.
Can someone explain why I'm not getting error for NON EXISTENT email address?
export const unpSignUp = (newUser) => {
console.log("newUser", newUser);
return (dispatch, getState, { getFirebase, getFirestore }) => {
const firebase = getFirebase();
const firestore = getFirestore();
firebase.auth().createUserWithEmailAndPassword(
newUser.unp_a05_email,
newUser.unp_a10_password
)
.then((response) => {
return firestore
.collection("unps")
.doc(response.user.uid)
.set({
unp_a02_surname: newUser.unp_a02_surname,
unp_a03_name: newUser.unp_a03_name,
unp_a06_verify_email_sent_datetime: null,
unp_a07_email_verified_on_datetime: null,
unp_a18_acc_created_on_datetime: moment().format("YYYY MM DD HH:mm:ss"),
});
})
.then((response) => {
console.log("SIGNUP SUCCESS ", response);
// user has been signed up, next step is to send verification email
dispatch({ type: SIGNUP_SUCCESS })
})
.then(() => {
// user has been signed up, next step is to send verification email
console.log('send email adr verification')
return firebase.auth().currentUser.sendEmailVerification()
})
.then( (response) => {
console.log("Verification email sent", response);
const user = firebase.auth().currentUser
console.log('current user', user)
const unp = firestore.collection("unps").doc(user.uid);
return unp.update({
unp_a06_verify_email_sent_datetime: moment().format("YYYY MM DD HH:mm:ss"),
})
})
.then( () => {
console.log(`unp_a06_verify_email_sent_datetime update to ${moment().format("YYYY MM DD HH:mm:ss")} `)
})
.catch((error) => {
console.log("SIGNUP ERROR", error);
console.log("SIGNUP ERROR CODE", error.code);
console.log("SIGNUP ERROR MESAGE", error.message);
dispatch({ type: SIGNUP_ERROR, error });
});
};
};
From firebase reference,
the return type of sendEmailVerification is Promise<void> - and it does not tell about any error codes that are sent in case of wrong email or failed/bounce mails. The error code it mentions is with respect to actionCodeSettings
If the actionCodeSettings is not specified, no URL is appended to the action URL. The state URL provided must belong to a domain that is whitelisted by the developer in the console. Otherwise an error will be thrown.
Thus it can not be checked if it is a valid email id. (This is expected behaviour as receiving mail servers may be down at times and hence there is a concept of retrying bounce mails)
Related
Passwordless sign in is not working in Firebase. Email was sent successfully. But after clicking on the link provided in the email that link redirects to the website with api key, mode etc. But not signing in or saving the email in firebase.
Please help me!!
const handleContinueWithEmail = async (event: any) => {
event.preventDefault();
setSignInLoading(true);
if (isSignInWithEmailLink(auth, window.location.href)) {
setEmail(window.localStorage.getItem("emailForSignIn"));
if (!email) {
setEmail(window.prompt("Please provide your email for confirmation"));
}
signInWithEmailLink(auth, email, window.location.href)
.then((result) => {
window.localStorage.removeItem("emailForSignIn");
// You can access the new user via result.user
// Additional user info profile not available via:
// result.additionalUserInfo.profile == null
// You can check if the user is new or existing:
// result.additionalUserInfo.isNewUser
console.log(result.user);
})
.catch((error) => {
// Some error occurred, you can inspect the code: error.code
// Common errors could be invalid email and invalid or expired OTPs.
console.log(error);
});
} else {
sendSignInLinkToEmail(auth, email, {
url: location.origin,
handleCodeInApp: true,
})
.then(() => {
window.localStorage.setItem("emailForSignIn", email);
setSignInLoading(false);
setShowSuccessToast(true);
setSuccessText(
"Sign in email has been sent! Check spam folder if not found."
);
setTimeout(function () {
setShowSuccessToast(false);
}, 6000);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
setSignInLoading(false);
console.error(errorCode, errorMessage);
});
}
};
Successfully redirected with API key, mode, and more. But not sign in or saving email on Firebase.
I'm trying to add passwordless sign in using fireabase on my website. But it's not sign in or saving email to firebase user list. So, I need help to solve this problem.
1.I'm working on an backend API but at some point I need to get user data from another API. I am trying to use Axios to make http request in order to do that. The request return the result in the browser as expected but the problem is that I can't display console log in the terminal. It doesn't show anything even though I asked the program to do so. Is there a problem probably with my code?
2.Error message =>>> POST http://localhost:8000/api/register 400 (Bad Request) Error: Request failed with status code 400`
const handleSubmit = async () => {
//e.preventDefault();
try
{
// console.log(name, email, password, secret);
const { data } = await axios.post("http://localhost:8000/api/register", {
name,
email,
password,
secret,
});
setOk(data.ok); //useState component
}
catch (error) {
**strong text**
console.log(error.response.data);
}
}
import User from '../models/user'
//import{ hashPassword, comparePassword } from '../helpers/auth'
export const register = async (req,res) => {
//console.log('Register endpoint =>', req.body)
//to make this work make express.json is applied in the above middleware
//console.log error to debug code
const {name, email, password, secret} = req.body;
//validation
if(!name) return res.status(400).send('Name is required')
if(!password || password.length < 6) return res.status(400).send('Password is
short
or password is not entered')
if(!secret) return res.status(400).send('Answer is required')
//The above code is for validation purpose to make sure data is correctly
entered
const exist = await User.findOne({email })
if(exist) return res.status(400).send('Email is taken')
}
.catch(error => {
console.log(error)
})
May be catching error on your axios is wrong try this
Hi I am using express for backend authentication and these are my sign in functions/controllers on the front end.
export const signInUser = async credentials => {
console.log('this is for the signInUser', credentials)
try {
const resp = await api.post('/sign-in', credentials)
localStorage.setItem('token', resp.data.token)
return resp.data
} catch (error) {
throw error
}
}
onSignIn = event => {
event.preventDefault()
const { history, setUser } = this.props
signInUser(this.state)
.then(res => setUser(res.user))
.then(() => history.push('/Home'))
.catch(error => {
console.error(error)
this.setState({
loginUsername: '',
loginPassword: '',
})
})
}
setUser = user => this.setState({ user })
and this is my sign in controller on the backend
const signIn = async (req, res) => {
try {
console.log('hello' ,req.body);
const { loginUsername, username, loginPassword } = req.body;
const user = await User.findOne({
where: {
username: loginUsername
}
});
console.log('this is the user', user)
if (await bcrypt.compare(loginPassword, user.dataValues.password_digest)) {
const payload = {
id: user.id,
username: user.username,
password: user.password
};
const token = jwt.sign(payload, TOKEN_KEY);
return res.status(201).json({ user, token });
} else {
res.status(401).send("Username or Password is invalid- try again.");
}
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
The issue is the state of the user doesn't persist on refresh but I still have the json webtoken in my local storage and this is an issue when I make post requests and even signing up since I am redirecting to the home page and losing the user state. Any help would be appreciated!
From your tags, I noticed that you are using React, so the solution is simple!
you can have an GlobalAuthManager context for your application that would wrap all the components at the most higher level! after <React.strictMode> like below:
<React.StrictMode>
<GlobalAuthManager.Provider value={{authData}}>
<App />
</GlobalAuthManager.Provider>
</React.StrictMode>
As you might guess, this would be a context! that would provide you your user data to all your components!
The Pattern:
1. Store token:
when your user logins to your app, you would receive a token ( in your response or in response header ), you need to store the token value in localstorage, or more better in cookie storage (there are a lot of articles about it why), one is here.
2. have a /getUserData endpoint in backend:
you need to have a /getUserData endpoint in backend to retrive your user data based on token
3. call /getUserData in app mount:
before every thing in your app, you need to call this endpoint if you find token in localstorage or cookie storage. so if you run this in your componnetDidMount or useEffect(() => { ... }, []), that would work!
4. store your user data and state in context:
after you've called the /getUserData and if you had a valid token(i mean not expired token or not interrupted and edited token) , you will get you user data and what you need to do is that you need to store this in your GlobalAuthManager and provide that in to your Global App component!
after that you have your user data available to you that you can decide to show login or sign up button in your Navbar or disable/enable comment section for example based on your user data!
Wrap up:
So the key is that you have to have a GlobalAuthManager for only one purpose, that before every thing it runs in the top level in your app and gets you your user data based on provided token from localstorage or cookie storage!
after that you can manage your app state based on that your user is logged in or not!
So I am attempting to use Firebase cloud messaging to send push notifications to my app. However, it seems to fail continuously for some odd reason. I am using the onCreate method to listen for the creation of a node under a certain path. It is getting the UID from that info gathered in the onCreate method but then when I try to get the user info from a different node to grab the fcmToken so I can send the notification. It always says undefined.
My index.js looks like this:
//listen for reply notification and then trigger a push notification
exports.observeNotification = functions.database.ref('/notifications/{uid}/{commentId}/')
.onCreate(event => {
// Grab the current value of what was written to the Realtime Database.
//const notification = event.data.val();
console.log('User ID is: ', event.params.uid);
console.log('Comment ID Is: ', event.params.commentId);
return admin.database().ref('/users/' + event.params.uid).once('value', snapshot => {
var userWeAreSendingTo = snapshot
console.log('User ID is: ', userWeAreSendingTo);
console.log('FCM Token of that user is: ', userWeAreSendingTo.fcmToken);
var payload = {
notification: {
title: "",
body: snapshot.content
}
};
admin.messaging().sendToDevice(userWeAreSendingTo.fcmToken, payload)
.then((res) => {
// Response is a message ID string.
console.log('Successfully sent message:', res);
return true
})
.catch((error) => {
console.log('Error sending message:', error);
return true
})
})
})
This is a snapshot of the child node under the user node in my database.
"9mzAHeX3lcdzriPdC4TfbRTkaUm2" : {
"fcmToken" : "coC8uorosgc:APA91bGur2vvH4fwIProh87pUzVw0jYTOOFW3KfqWRVk4WdX0x8M1iBFwg28wM3tFyB5iRrowTWCZ_45oGwo0_7BFD6YvULE30NNZXxvE2O2XLjlLd_fqYwMfkndOqSUem2HqO-qvNcZ",
"profilePic" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/profile_images%2F832F8156-C14A-4EF3-86EB-D8F4CFC784E5.PNG?alt=media&token=b9d11ea1-8cb3-4d0f-b111-b0baf567ac7b",
"username" : "lol123"
}
This screenshot of the console log
enter image description here
My use case is similar to Parse Suggested Migration Strategy
(but I'm not using Parse, just integrating 3rd party auth)
On Node.js / express, here is relevant code:
firebaseWebSDK.auth().signInWithCustomToken(customToken)
.then(user => {
let nextStep
let message
// check if returned user has "email" field set..
if (!user.email) {
message = 'Signed up user, saved: email, password, and display name.'
const usersRef = firebaseServerSDK.database().ref('users')
nextStep = Promise.all([
user.updateEmail(email),
user.updatePassword(password),
user.updateProfile({ displayName }),
usersRef.child(user.uid).set({ displayName, email }),
])
} else {
message = `User already exists for that email: ${email}`
nextStep = Promise.resolve(null)
}
nextStep.then(() => {
delete req.session.user
return res.json({ message })
})
.catch(updateError => res.json({ error: updateError.message }))
})
.catch(signInError => {
const errorCode = signInError.code
const errorMessage = signInError.message
return res.json({ type: 'signInError', errorCode, errorMessage })
})
Here's what happens:
Sometimes user email updates, sometimes it doesn't
Never does the password update
Pretty sure the Profile updates always
database "/users" saves correctly, no issues there.
Always tested with new user, so it's always entering the "update" branch of code...
Any ideas? Code follows structure of documentation linked above, so not sure what issue is.