How to use session in Reactjs - javascript

I am new in Reactjs and I am working on "login" module, I integrated the login module successfully, and Now I want if the user enters the correct email and password then the email should be in session, And if the user is not logged in he can't see any further page, How can I do this? Here is my current code
const data = {
email: email,
password: password
};
axios.post("https://xxxxxxxxxxx/Checklogin/", data).then(function (response) {
if (response.data.msg == "wrong") {
$("#errormsg4").show("slow").delay(5000).fadeOut();
} else {
//"response.data.email"should be in session
}
});

To store the email in a session in React, as you specified, you can use the sessionStorage API. The sessionStorage API allows you to store key-value pairs in the user's browser. The data is stored in the session, which means it will only be available for the current tab and will be deleted when the user closes the tab.
Here is an example of how you can use the sessionStorage API to store the email in a session:
const data = {
email: email,
password: password
};
axios.post("https://xxxxxxxxxxx/Checklogin/", data).then(function (response) {
if (response.data.msg == "wrong") {
$("#errormsg4").show("slow").delay(5000).fadeOut();
} else {
// Store the email in the session
sessionStorage.setItem("email", response.data.email);
}
});
To check if the user is logged in, you can use the sessionStorage.getItem() method to retrieve the email from the session. If the getItem() method returns a non-null value, it means that the user is logged in and has an email stored in the session.
Here is an example of how you can use the sessionStorage.getItem() method to check if the user is logged in:
const email = sessionStorage.getItem("email");
if (email) {
// The user is logged in
} else {
// The user is not logged in
}
I hope this helps!

Related

how to get the user email from the applyActionCode in Firebase?

I have my own custom server that also records users. So what I want to achieve is, after a user registers, Then I will generate a custom token by signInWithCustomToken, then send a sendEmailVerification to them for verifying.
Here is how I generate the custom token from my backend
FirebaseAuth.getInstance().createCustomToken(id, additionalClaims)
Then in my front end, it will signInWithCustomToken right after they registered. (this is to get the user for sendEmailVerification)
await axios
.post(`/authorization/sign-up`, {
username: inputData.username,
password: inputData.password,
})
.then(async (response) => {
const auth = getAuth();
signInWithCustomToken(auth, response.data.content.token)
.then(async(userCredential) => {
await updateEmail(userCredential.user, inputData.username)
const actionCodeSettings = {
url: `https://domain host/test?email=${inputData.username}`
};
await sendEmailVerification(userCredential.user, actionCodeSettings)
navigate("/"); //login page
})
})
.catch((error) => toast(error.message));
} else {
toast("Please input valid data");
}
In my Login Backend I will check my database's user, whether their email has been verified or not. So if its not verified, the login will be rejected
select * from user where user = foo and password = foo and isEmailVerified = true
In my front-end verify-email page :
console.log("verifying email")
const mode = searchParams.get('mode') // mode = verifyEmail
const oobCode = searchParams.get('oobCode')
const auth = getAuth()
applyActionCode(auth, oobCode).then(() => {
//how to update my backend based on the user's email
})
Then in my Backend I will check the decodedToken.isEmailVerified, if its false, I will force them to activate their email first.
So, after the user click the activation link, it will be redirected to my verify-email page, which then will also update the status of the user in my database. But, I notice that the applyActionCode function returns Promise<void>.
For example if I register my email through my PC/Laptop, then I confirm the verify email through my phone / table / other device, then I won't be able to get the currentUser to retrieve some data, ex. their email.
I also cannot put the email into the continueUrl parameter right? since the user might change the parameter themself.
So How can I get the user's email safely after applyActionCode?
Or do I just redirect them back to the login page, then each time after they click login, I will compare the decodedToken.isEmailVerified vs my database's isEmailVerified ?

Send verification email before logging in

This is the code that i'm practicing in to create a new user. I can receive the email verification and confirm it however, the site will still logged me in even if I have not yet confirmed my email yet.
try{
const { user } = await auth.createUserWithEmailAndPassword(email,password);
await user.sendEmailVerification();
await handleUserProfile(user, { displayName});
this.setState({
...initialSate
});
}catch(err){
console.log(err);
}
}
This is the handleUserProfile in another js file.
export const handleUserProfile = async (userAuth, additionalData) => {
if (!userAuth) return;
const {uid} = userAuth;
const userRef = firestore.doc(`users/${uid}`);
//create new user
const snapshot = await userRef.get();
if (!snapshot.exists){
const { displayName, email} = userAuth;
const timestamp = new Date();
//if the user exist does not exist
try{
await userRef.set({
displayName,
email,
createdDate: timestamp,
...additionalData
});
}catch(err){
console.log(err);
}
}
return userRef;
};
Everything is explained in the firebase documentation.
There you have the corresponding code snippets to try.
You would need to narrow down your question with some of this trials.
Even you have the chance to check if user opens the link from a differenc device from which waas signed up.
I think this is the snippet you might need:
// Confirm the link is a sign-in with email link.
if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
// Additional state parameters can also be passed via URL.
// This can be used to continue the user's intended action before triggering
// the sign-in operation.
// Get the email if available. This should be available if the user completes
// the flow on the same device where they started it.
var email = window.localStorage.getItem('emailForSignIn');
if (!email) {
// User opened the link on a different device. To prevent session fixation
// attacks, ask the user to provide the associated email again. For example:
email = window.prompt('Please provide your email for confirmation');
}
// The client SDK will parse the code from the link for you.
firebase.auth().signInWithEmailLink(email, window.location.href)
.then((result) => {
// Clear email from storage.
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
})
.catch((error) => {
// Some error occurred, you can inspect the code: error.code
// Common errors could be invalid email and invalid or expired OTPs.
});
}
The site will still logged me in even if I have not yet confirmed my
email yet.
Yes this is how it is implemented in Firebase: there is nothing, out of the box, that prevents a user with a non-verified email to authenticate to your app.
You should manage that yourself, by:
Checking the email is verified in the back-end security rules (Firestore, Cloud Storage, etc..). For example with a function like:
function isVerifiedEmailUser() {
return request.auth.token.email_verified == true;
}
Possibly redirect and logout the user from your app if his/her email is not verified. For example, right after signing-up, as follows:
try {
const { user } = await auth.createUserWithEmailAndPassword(email,password);
await user.sendEmailVerification();
if (user.emailVerified) {
// display the content, redirect to another page, etc...
} else {
auth.signOut(); // Maybe call that after showing an error message
}
} catch(err){
console.log(err);
}
}
plus, potentially, something similar with signInWithEmailAndPassword() and onAuthStateChanged().

Checkout page signs out the user

The only way I check if user if logged in to my web app is using the following on the frontend
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
However, I have a cloud-function that I use in order to process a payment, it looks like the following
app.post("/payment", function (req, res) {
const orderId = new Date().getTime();
mollieClient.payments
.create({
amount: {
value: req.body.amount.amount,
currency: req.body.amount.currency,
},
description: req.body.description,
//redirectUrl: `http://localhost:5500/project/order.html?id=${orderId}`,
redirectUrl: `https://......web.app/order.html?id=${orderId}`,
webhookUrl: .....
})
.then((payment) => {
res.send({
redirectUrl: payment.getCheckoutUrl(),
});
return payment.getCheckoutUrl();
})
My problem is regarding the redirect URL, the redirect to order page is supposed to display information about that order, but it does not display anything because I set that only logged in users can see it. My question is why does it log out the user. I tried both to redirect to 'localhost' and 'URL-of-deployed-firebase-app' and in both cases it logs out the user. I thought by intuition that Firebase stores auth information to local storage because I can enter to any page I want without have to login. But I think this is not the case here. I am not using any let token = result.credential.accessToken tokens to keep track of auth status. What is the problem here and how should I proceed?
Here is Order page
function getOrderDetails() {
const url = new URL(window.location.href);
let orderId = url.searchParams.get("id");
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
console.log("User logged in " + user);
firebase
.firestore()
.doc(`orders/${orderId}`)
.get()
.then((doc) => {
let orderSelected = {
category: doc.data().category,
delivery: doc.data().delivery,
description: doc.data().description,
price: doc.data().price,
title: doc.data().title,
quantity: doc.data().quantity,
};
// set textContent of divs
} else {
console.log("User not logged in " + user);
}
});
}
getOrderDetails();
On a new page it takes time to restore the user credentials, as it may require a call to the server. So it is normal that your onAuthStateChanged() listener first is called with null and only after that with the actual user. So you will have to handle the flow in a way that deals with the initial null, for example by waiting a few seconds before assuming that the user session isn't restored.
Alternatively, you can store a marker value in local storage yourself to indicate the was signed in recently, and then on the next page use that to assume the restore will succeed.

Firebase auth isn't storing data in local storage

My app successfully signs the user into Firebase when the user clicks on "Submit", but Firebase doesn't store the user auth data in local storage in Chrome. I checked and the user object is returned successfully by Firebase, and the program prints "user signed in" with the correct user ID. However, when I run "localStorage" in the console, the object isn't there, and the user authentication doesn't persist. I'm not sure why it's not working. Here is my code:
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
function authenticate(event){
event.preventDefault();
let email = document.getElementById("email").value;
let password = document.getElementById("password").value;
let result = firebase.auth().signInWithEmailAndPassword(email, password)
.then(
(user) => {
alert("User: " + JSON.stringify(user)); //this works
}
)
.catch(console.log);
}
firebase.auth().onAuthStateChanged( function(user){
if(user){
console.log("user signed in"); //this works
console.log("user id: " + firebase.auth().currentUser.uid);
window.location.href = "./calendar.html";
} else {
console.log("No user");
window.location.href = "./index.html";
}
});
You have to use localStorage
localStorage.setItem('userData', JSON.stringify(userDetail));
To get Data
JSON.parse(localStorage.getItem('userData'));
To remove
localStorage.removeItem('userData');

How to validate firebase user current password

I am creating a form, in react-redux to change user password. I am wondering how can I validate the user current password in order to change to new one.
in my form I have 2 fields: old password, new password.
this is my action:
const { currentUser } = auth
currentUser.updatePassword(newPassword)
.then(
success => {
dispatch({
type: CHANGE_USER_PASSWORD_SUCCESS,
payload: currentUser
})
},
error => {
dispatch({
type: CHANGE_USER_PASSWORD_FAIL,
error: error.message
})
}
)
I am wondering, how to validate the old password in firebase? Should I use signInWithEmailAndPassword()? Or, is there a function to validate the current password without calling the signIn again, since my user is already logged in?
Thanks
Well, I believe you want the user to enter the old password just to verify whether it's the actual owner of the account or not.
Firebase handles this situation very well, you just need to call the updatePassword method on the user object and pass in the new password.
const changePassword = async newPassword => {
const user = firebase.auth().currentUser;
try {
await user.updatePassword(newPassword)
console.log('Password Updated!')
} catch (err) {
console.log(err)
}
}
If it's been quite a while that the user last logged in then firebase will return back an error -
"This operation is sensitive and requires recent authentication. Log in before retrying this request."
Thus, you don't really need to check the old password as firebase does it for you.
But if you just want to do it in one go, without having the user to log in again.
There's a way for that as well.
There is a method on user object reauthenticateAndRetrieveDataWithCredential you just need to pass in a cred object(email and password) and it refreshes the auth token.
const reauthenticate = currentPassword => {
const user = firebase.auth().currentUser;
const cred = firebase.auth.EmailAuthProvider.credential(
user.email, currentPassword);
return user.reauthenticateAndRetrieveDataWithCredential(cred);
}
In your particular case, you can have something like this
const changePassword = async (oldPassword, newPassword) => {
const user = firebase.auth().currentUser
try {
// reauthenticating
await this.reauthenticate(oldPassword)
// updating password
await user.updatePassword(newPassword)
} catch(err){
console.log(err)
}
}
Learn more about firebase reauth - https://firebase.google.com/docs/auth/web/manage-users#re-authenticate_a_user
Hope it helps

Categories

Resources