please help.
I'm trying to ensure that the user does not log out after reloading the page.
const signUp = async (loginEmail, loginPassword) => {
const auth = getAuth()
setPersistence(auth, browserSessionPersistence)
.then(({ user }) => {
dispatch(
setUser({
email: user.email,
id: user.uid,
token: user.accessToken,
})
)
return signInWithEmailAndPassword(auth, loginEmail, loginPassword)
})
.catch((error) => {
console.log(error.message)
})
}
This is what the example looks like in the official documentation
const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
.then(() => {
// Existing and future Auth states are now persisted in the current
// session only. Closing the window would clear any existing state even
// if a user forgets to sign out.
// ...
// New sign-in will be persisted with session persistence.
return signInWithEmailAndPassword(auth, email, password);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
The recommended way to get the current user is by setting an observer on the Auth object:
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
const uid = user.uid;
// ...
} else {
// User is signed out
// ...
}
});
documentation
Related
When the user clicks on the "sign-in" button and if user.challangeName === 'NEW_PASSWORD_REQUIRED'is true, I redirect the user to a page (form screen) where he can provide the input for required attributes and a new password. Even tho the user object is getting populated upon clicking on the sign-in button, using Auth.currentsession on the form screen will print "No user found"
Can someone let me know why I'm seeing no user? What am I doing wrong here?
Here's my login function (triggered when clicked on sign-in button) where I direct the user to the change password screen (form screen) if user.challangeName === 'NEW_PASSWORD_REQUIRED' is true.
const login = async (email, password) => {
try {
const user = await Auth.signIn(email, password);
if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
navigate('/change-password');
return;
}
if (user) {
setToken(user.signInUserSession.idToken.jwtToken);
const userDetails = await getAccountDetails();
dispatch({
type: LOGIN,
payload: {
user: {
attributes: user.attributes,
username: user.username
},
client: userDetails
}
});
}
} catch (error) {
await logout();
throw error;
}
};
Here's my onSubmit function on the change password screen where eventually I want to use Auth.completeNewPassword to update the user's password in Cognito
const onSubmitClick = (e) => {
e.preventDefault();
if (validateFields());
Auth.currentSession()
.then((user) => console.log(user))
.catch((err) => console.log(err));
};
Here's the documentation provided by AWS https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#forgot-password, and the code provided by AWS to update password
Auth.signIn(username, password)
.then(user => {
if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
const { requiredAttributes } = user.challengeParam; // the array of required attributes, e.g ['email', 'phone_number']
Auth.completeNewPassword(
user, // the Cognito User Object
newPassword, // the new password
// OPTIONAL, the required attributes
{
email: 'xxxx#example.com',
phone_number: '1234567890'
}
).then(user => {
// at this time the user is logged in if no MFA required
console.log(user);
}).catch(e => {
console.log(e);
});
} else {
// other situations
}
}).catch(e => {
console.log(e);
});
New updated answer to reflect your updated post, change the onSubmitClick to the following:
const onSubmitClick = (e) => {
e.preventDefault();
if (validateFields());
Auth.currentAuthenticatedUser()
.then(user => {
console.log(user))
})
.then((data) => console.log(data))
.catch((err) => console.log(err));
};
You are looking at the documentation which shows how to use the user after Auth.signIn() (which was my previous answer), compared to what you use: Auth.currentAuthenticatedUser(). The proper documentation example you have to look at is this one: https://www.docs.amplify.aws/lib/auth/manageusers/q/platform/js
I am trying to update my firebase realtime database with user info when I am creating new user through firebase password authentication. And on successful sign in I am moving to another page. The problem is that my database is not getting updated in the above scenario however if stay in the login page and don't change to any other url; the database gets updated.
Here's my create user code
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
if (user !== null) {
const db = firebase.database();
db.ref("/").set({
uid: user.uid,
});
}
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
// ..
});
And here's where I'm switching to another page,
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
console.log(user);
//If I remove the below line, database is updated
window.location.href = "../html/home.html";
// ...
} else {
// User is signed out
// ...
console.log("not logged in");
}
});
This calls is asynchronous:
db.ref("/").set({
uid: user.uid,
});
That means that the code continues to run after the set() function returns, and asynchronously sends the data to the database. But when you change window.location, it interrupts this write operation. That's also why it works when you don't send the user to a new location: the write operation can then complete without interruption.
A quick simple fix is to flag when you're updating the database:
isCreatingUser = true; // 👈 Flag that we're creating a user
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
var user = userCredential.user;
if (user !== null) {
const db = firebase.database();
db.ref("/").set({
uid: user.uid,
}).then(() => {
isCreatingUser = false; // 👈 We're done
window.location.href = "../html/home.html"; // 👈 Navigate away
}).catch((e) => {
isCreatingUser = false; // 👈 We're done
throw e;
})
}
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
// ..
isCreatingUser = false; // 👈 We're done
});
And then:
firebase.auth().onAuthStateChanged((user) => {
if (user && !isCreatingUser) {
...
You'll probably need some more synchronization, but that's the gist of it.
I am creating an e-commerce web site.
Now I finished creating the new account with email and password.
And I want to insert the user email, full name, and timestamp in the database.
As you can see in the picture below, I could see the USER data in the google chrome dev console.
But when I checked the firebase database in the browser, I cannot see the user id. And instead, I see undefined in the user id column.
Now I am on the step3 process.
Add user data into database
I cannot figure out why it's happening, so I hope you can help me out.
This is my store/index.js file.
import fireApp from '#/plugins/firebase'
export const state = () => ({
user: null,
error: null,
busy: false,
jobDone: false
})
export const mutations = {
setUser (state, payload) {
state.user = payload
},
setError (state, payload) {
state.error = payload
},
clearError (state, payload) {
state.error = null
},
setBusy (state, payload) {
state.busy = payload
},
setJobDone (state, payload) {
state.jobDone = payload
},
}
export const actions = {
signUpUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.Signup new user.
//2.Update firebase user profile & set local user data.
//3.Add user data into database
//4.Attach user to consumer group
let newUser = null
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(user => {
newUser = user
var user = fireApp.auth().currentUser;
user.updateProfile({ displayName: payload.fullname })
const currentUser = {
id: user.uid,
email: payload.email,
name: payload.fullname,
role: 'consumer'
}
console.log('USER', currentUser)
commit('setUser', currentUser)
})
.then(() => {
const userData = {
email: payload.email,
fullname: payload.fullname,
createdAt: new Date().toISOString()
}
fireApp.database().ref(`users/${newUser.uid}`).set(userData)
})
.then(() => {
commit('setJobDone', true)
commit('setBusy', false)
})
.catch(error => {
commit('setBusy', false)
commit('setError', error)
})
}
}
export const getters = {
user (state) {
return state.user
},
error (state) {
return state.error
},
busy (state) {
return state.busy
},
jobDone (state) {
return state.jobDone
}
}
This is because the promise returned by createUserWithEmailAndPassword() method resolves with an UserCredential object and not with a User one.
You should use the user property of the UserCredential, as follows:
let newUser = null
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
newUser = userCredential.user;
//...
Note also that you don't need to call fireApp.auth().currentUser to get the user.
When using the createUserWithEmailAndPassword() method, on successful creation of the user account, this user will also be signed in to your application, so just get the user with userCredential.user, as explained above.
In addition, note that the updateProfile() method is asynchronous and returns a Promise, which you need to include in your promises chain.
So the following should do the trick (untested):
signUpUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.Signup new user.
//2.Update firebase user profile & set local user data.
//3.Add user data into database
//4.Attach user to consumer group
let user = null;
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
user = userCredential.user;
return user.updateProfile({ displayName: payload.fullname });
})
.then(() => {
const currentUser = {
id: user.uid,
email: payload.email,
name: payload.fullname,
role: 'consumer'
}
console.log('USER', currentUser)
commit('setUser', currentUser)
const userData = {
email: payload.email,
fullname: payload.fullname,
createdAt: new Date().toISOString()
}
return fireApp.database().ref(`users/${user.uid}`).set(userData)
})
.then(() => {
commit('setJobDone', true)
commit('setBusy', false)
})
.catch(error => {
commit('setBusy', false)
commit('setError', error)
})
}
I have a register screen that contains "username, email, phone number, Password"
and in this case, I use Phone Number Authentication to verify the number so after user verify his number I save his data into firebase DB,
so after that, I navigate hem to login screen! that should contain Email, Password "he registered by them before"
So I don't just compare if his data exist in DB or not,
So it should be used Email/Password Firebase Auth,
But I think it's will take a lot of hits to my Bill or something,
so what you think to achieve these cases because I'm forced to register by Email For Reset Password later?
here is my register Code
signUp = async () => {
const {phoneNumber} = this.state;
this.setState({message: 'code was sent'});
const phoneWithAreaCode = phoneNumber.replace(/^0+/, '+972');
console.log(phoneWithAreaCode);
auth()
.signInWithPhoneNumber(phoneWithAreaCode, true)
.then(confirmResult => {
console.log('confirmResult', confirmResult);
this.setState({confirmResult, message: 'code was sent'});
// this.createUserDatabase();
})
.then(() => {
this.props.navigation.navigate('Confirmation', {
message: this.state.message,
confirmResult: this.state.confirmResult,
createUser: uid => this.createUserDatabase(uid),
phoneWithAreaCode: phoneWithAreaCode,
signInPhoneNumber: phone => auth().signInWithPhoneNumber(phone),
});
});
};
createUserDatabase = uid => {
const {userName, phoneNumber, email} = this.state;
// const uid = auth().currentUser.uid;
const data = {
uid,
name: userName,
email: email,
phoneNumber: phoneNumber,
};
database()
.ref(`users/${uid}`)
.set(data)
.then(() => {
console.log('New poll data sent!');
})
.catch(error => console.log('Error when creating new poll.', error));
};
I am updating the Firebase user profile photoURL
it's upadted in the store but not in the Firebase users db...
when I signout then signin with this user, the photoURL is NOT changed
here is my store action
updateProfilePhotoURL ({commit}, payload) {
const updateFBUserProfile = async (commit, payload) => {
commit(types.SET_LOADING, true)
let db = firebase.database()
const updatedData = {
photoURL: payload.photoURL
}
// Update the Firebase user profile too...
await db.ref('users/' + payload.uid).update(updatedData)
// Update the store profile too...
commit(types.UPDATE_PROFILE_PHOTO_URL, updatedData.photoURL)
return 'ok'
}
return new Promise((resolve, reject) => {
updateFBUserProfile(commit, payload)
.then(result => {
commit(types.SET_LOADING, false)
resolve(result)
}, error => {
console.log('ERROR: ', error)
reject(error)
})
})
}
where am I wrong ?
thanks for feedback
According to question comments - I think your user has no permissions to write to db. You can check it with firebase.auth().currentUser or check your Rules for database in Firebase Console.