Environment
Firebase JavaScript SDK v8
Question
How can I re-authorize an already-logged-in user with their password? What I want to do is like below:
const password = "some-password"
firebase.reAuthorizeUser(password)
.then(() => console.log("ok"))
.catch(() => console.log("ng"))
Thank you in advance.
You are looking for reauthenticateWithCredential method.
const user = firebase.auth().currentUser;
// TODO(you): prompt the user to re-provide their sign-in credentials
const credential = promptForCredentials();
user.reauthenticateWithCredential(credential).then(() => {
// User re-authenticated.
}).catch((error) => {
// An error ocurred
// ...
});
Checkout reauthenticate a user in the documentation.
You can do a switch case based on providerId, below should help.
user.providerData.forEach((profile) => {
switch (profile.providerId) {
case 'google.com':
user
.reauthenticateWithPopup(new firebase.auth.GoogleAuthProvider())
.then((UserCredential) => {
**//reauthenticated successfully!**
})
})
.catch((error) => {
**//Something is wrong**
})
break
case 'password':
// eslint-disable-next-line no-case-declarations
const credentials = firebase.auth.EmailAuthProvider.credential(
user.email,
userPassword
)
user
.reauthenticateWithCredential(credentials)
.then(() => {
**//reauthenticated successfully!**
},
})
})
.catch(() => {
**//Something is wrong**
})
break
})
SDK v9
import {getAuth, reauthenticateWithCredential, EmailAuthProvider} from "firebase/auth";
const reauthenticate = async () => {
try {
const auth = getAuth();
const user = auth.currentUser;
const credential = await EmailAuthProvider.credential(
email,
password
);
await reauthenticateWithCredential(user, credential);
return true
} catch (e) {
return null
}
}
const credential = promptForCredentials();
this is giving me error
cant find variable: promptForCredentials.
Related
I'm still new to programming and especially Firebase so there probably will some obvious stuff I missed.
This is supposed to be login/register page. When the user type's in the needed info and click one of the buttons that corresponds to there field. Tt's supposed to load another page. Save that data in a Firebase realtime database and also in authentication.
It's doing the ladder and first but not the second. So I'm stuck with the code I have displayed under this. I read something about needing to give sometime for the data to be send out.
import { firebaseConfig } from "./database.mjs";
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.15.0/firebase-app.js";
import { getAuth, createUserWithEmailAndPassword,
signInWithEmailAndPassword, onAuthStateChanged,
signOut } from "https://www.gstatic.com/firebasejs/9.15.0/firebase-auth.js";
import {getDatabase, ref, get, set, child, update, remove, push} from "https://www.gstatic.com/firebasejs/9.15.0/firebase-database.js";
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const db = getDatabase();
const UserRegistration = () => {
const Username = document.getElementById('username').value
const Email = document.getElementById("email-signup").value;
const Passwd = document.getElementById("passwd-signup").value;
createUserWithEmailAndPassword(auth, Email, Passwd)
.then((userCredential) => {
const user = userCredential.user;
const loginTime = new Date()
set(ref(db, 'users/' + user.uid),{
user_email: Email,
user_username: Username,
last_login: `${loginTime}`
})
console.log(user, "User Created");
}).then(StatusMonitor())
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(error.message)
});
}
const UserLogIn = () => {
const Email = document.getElementById("email-signup").value;
const Passwd = document.getElementById("passwd-signup").value;
const auth = getAuth();
signInWithEmailAndPassword(auth, Email, Passwd)
.then((userCredential) => {
const user = userCredential.user;
const loginTime = new Date()
update(ref(db, 'users/' + user.uid), {
last_login: loginTime
});
console.log(user, "Login Successfull");
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(error.message);
});
StatusMonitor()
}
//Login checker
const StatusMonitor = () => { //This part specifically
onAuthStateChanged(auth, (user) => {
if (user) {
const uid = user.uid;
console.log("User is active");
window.location.replace("./product.html")
}
else {
console.log("User is inactive");
}
})
}
document.getElementById("signup").addEventListener("click", UserRegistration);
document.getElementById('login').addEventListener("click", UserLogIn);
I was able to get it to work with setTimeout but this created it's own problems such as small freezes whenever the thing got triggered and of course the extra time needed for it to load as I can't set to it change based on latency.
Tried to do it with async/await but personally couldn't get it to work.
Any help would be appreciated!
Code below outputs an array of users stored in Firestore db. Each document have the same id of a user.
const [user] = useAuthState(auth);
const [userData, setUserData] = useState([]);
const usersDB = collection(firestore, "Users");
const getUsers = async () => {
const data = await getDocs(usersDB);
setUserData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
useEffect(() => {
getUsers();
}, []);
I want to access the document with same id as logged in user and check if isAdmin field is true or false using useAuthState to get user uid. How should I write the code for this?
According to your code you are using getDocs instead of getDoc.
Here's a sample code using useEffect and checking boolean isAdmin.
const [userData, setUserData] = useState([]);
const email = "test#xyz.com";
const password = "123Addw1113#";
const getUsers = async () => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
const user = userCredential.user;
setDoc(doc(db, "<collection>", user.uid), {
someField: "<data>",
})
.then(async () => {
const docRef = doc(db, "<collection>", user.uid);
const docSnap = await getDoc(docRef);
if (docSnap.exists() && docSnap.data().isAdmin === true) {
setUserData(docSnap.data());
console.log("isAdmin is True");
} else if (docSnap.exists() && docSnap.data().isAdmin === false) {
console.log("isAdmin is False");
} else {
console.log("No such document!");
}
});
})
.catch((error) => {
console.log(error)
});
}
useEffect(() => {
getUsers();
}, []);
I am learning firebase. now want to change password with reauthenticateWithCredential(). but get error like this.
TypeError: credential._getReauthenticationResolver is not a function
this the code:
import { getAuth, reauthenticateWithCredential, signInWithEmailAndPassword } from "firebase/auth";
const auth = getAuth();
const user = auth.currentUser;
const credential = signInWithEmailAndPassword(auth, user.email, this.oldPassword);
reauthenticateWithCredential(user, credential).then(() => {
// User re-authenticated.
console.log(credential)
}).catch((error) => {
console.log(error)
});
can anyone point out where the error is?
Maybe still not quite right, but give this a try :
import {
getAuth,
reauthenticateWithCredential,
EmailAuthProvider,
} from "firebase/auth";
const auth = getAuth();
const user = auth.currentUser;
try {
const credential = EmailAuthProvider.credential(
user.email,
this.oldPassword
);
reauthenticateWithCredential(user, credential).then(() => {
// User re-authenticated.
// Code...
});
} catch (error) {
console.log(error.message);
}
I need your help.
I have an app. I can login with normal (email and password) and using Google Auth.
When i print my informations to console.log, it successfully prints, but I use firebase and i need to firebase.auth().onStateChanged for control the state.
For example, if i login with email and password, then onstateChanged function works with useEffect, and it redirect homepage (because this function know user has signed in), but when i login with google, i can't inform about user signed in or not because of google.
How can i use both google sign in and firebase? How can i tell firebase, i login with google, there are my informations don't worry.
Here google logs (my google name and googleId):
my codes:
google codes:
const GoogleAuth = () => {
const saveFirebase = (email, uid) => {
return firebase.firestore().collection("users").doc(uid).set({
email: email,
});
};
const onSuccess = (response) => {
const name = response.profileObj.name;
const uid = response.profileObj.googleId;
console.log(uid);
console.log(name);
return saveFirebase(name, uid);
};
const handleClick = () => {
return (
<GoogleLogin
clientId="1093050194946-tcn6k22l190klav7cat182leq09luthu.apps.googleusercontent.com"
buttonText="Login"
onSuccess={onSuccess}
onFailure={onSuccess}
cookiePolicy={"single_host_origin"}
theme="dark"
/>
);
};
return <div className="google-button">{handleClick()}</div>;
};
my constant variables:
const [user, setUser] = useState("");
onAuthStateChanged codes with useEffect:
const authListener = () => {
auth.onAuthStateChanged((user) => {
if (user) {
setUser(user);
setUsername(user.displayName);
} else {
}
});
};
useEffect(() => {
authListener();
});
To check if the user loged in with email or Google just use the providerId from user you get from the onAuthStateChanged like here:
const authListener = () => {
auth.onAuthStateChanged((user) => {
if (user) {
setUser(user);
setUsername(user.displayName);
//Here you can se what provider the user used
console.log('provider',user.providerId)
} else {
}
});
};
I have a function which uses Firebase auth to update a user's email:
export const updateEmail = async (email) => {
const user = auth.currentUser;
return user.updateEmail(email);
};
It is used in a function which gets an email from a form (in React) and tries to update the email. If there is an error, we change the state to reflect that.
handleSave = (e) => {
const email = e.target.email.value;
updateEmail(email).catch((err) => {
this.setState({ didError: true, emailError: err.message });
});
};
However, when an error occurs, in the console I get:
My question is: why does this still say 'Uncaught'? Does the .catch() in handleSave not take care of that?
update
Link to relevant Firebase docs
Assuming updateEmail returns a prmise, I guess you can try:
export const updateEmail = (email) => { // no need for async here
const user = auth.currentUser;
return user.updateEmail(email);
};
handleSave = async (e) => {
const email = e.target.email.value;
try{
await updateEmail(email);
}catch(err){
this.setState({ didError: true, emailError: err.message });
}
};
I'm not quite sure since I don't know so much about Firebase, let me suggest something.
export const updateEmail = async (email) => {
const user = auth.currentUser;
const response = await user.updateEmail(email);
if ( response.error ) {
throw new Error( response.error );
}
return "something else";
};