I am trying to discover how to make a statement appear when someone registering to the form that I was made but the email address was already used. I am using firebase. I am not familiar with fetchSignInForEmail and am wondering how to use it and implement it.
I am thinking I can use an if statement
if(email exists) {
push firebase user to directed page
} else {
statement.style.display === block
}
I am also curious on how to do this with passwords as well.
Thank you
Listen for that error. However, I prefer to merge the accounts and let the user sign in. Below is an example snippet. I've got this done for you, provided you want to allow email link authentication (no password required). Firebase offers a pre-rolled one as well that supports passwords and federation/oAuth (twitter, facebook, etc).
} catch (error) {
if(error.code === "auth/email-already-in-use"){
// REMEMBER AUTH CURRENT USER OBJECT
previousUser = firebase.auth().currentUser;
// WE MUST HANDLE DB READ AND DELETE WHILE SIGNED IN AS PREVIOUS USER PER FIRESTORE SECURITY RULES
if(localUserDoc){
if(localUserDoc.data().apples){
apples = localUserDoc.data().apples;
}
}
//DELETE CURRENT USER RECORD WHILE STILL SIGNED IN
await firebase.firestore().collection("users").doc(previousUser.uid).delete();
// CLEAN UP DONE. NOW SIGN IN USING EMAIL LINK CREDENTIAL
try {
var firebaseUserObj = await firebase.auth().signInAndRetrieveDataWithCredential(credential);
// FIRESTORE USER RECORD FOR EMAIL LINK USER WAS CREATED WHEN THEY ADDED APPLE TO CART
try {
var doc = await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).get();
if (doc.exists) {
if(doc.data().apples){
apples = apples + doc.data().apples;
}
}
await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).update({
apples: apples
});
} catch(error) {
console.log("Error getting document:", error);
}
previousUser.delete();
} catch (error) {
console.log(".signInWithCredential err ", error);
}
}
}
Related
I've followed this tutorial on how to link existing credentials with the new credentials from Facebook and everything is working as expected, except for the last part which is linking the user with the new credentials, I keep getting "user.linkWithCredential is not a function" error.
Here's my code:
$(document).on('click', "#btn-login-fb", function (event) {
//A bunch of code here where I do the login process
}).catch(function (error) {
//Here is where I need to handle the error and link accounts
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
//
// LINKING FACEBOOK WITH EXISTING EMAIL/PASSWORD USER
//
if (error.code === 'auth/account-exists-with-different-credential') {
// Step 2.
// User's email already exists.
// The pending Facebook credential.
var pendingCred = error.credential;
// The provider account's email address.
var email = error.email;
// Get sign-in methods for this email.
firebase.auth().fetchSignInMethodsForEmail(email).then(function (methods) {
// Step 3.
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (methods[0] === 'password') {
// Asks the user their password.
// In real scenario, you should handle this asynchronously.
//Abrir modal
document.getElementById("btnPwModal").click();
$(document).on('click', "#btnConfirmPw", function (event) {
document.getElementById("btnFecharModal").click();
var password = $("#inputPassword").val();
firebase.auth().signInWithEmailAndPassword(email, password).then(function (user) {
// Step 4a.
user.linkWithCredential(pendingCred).then(function () {
alert("linko");
// Facebook account successfully linked to the existing Firebase user.
});;
});
})
}
});
}
});
});
Any ideas on why everything else is working but linkWithCredential is not? Thanks.
What you get after calling signInWithEmailAndPassword is a UserCredential object, not a User object. To get from UserCredential to ``, you call user on it.
So:
firebase.auth().signInWithEmailAndPassword(email, password).then(function (cred) {
cred.user.linkWithCredential(pendingCred)...
First time on SO so I'm hoping this goes well.
I'm using Mongoose on a current project and until now I haven't had any issues. As the title states, after querying for a document and verifying that document actually exists in the database using a simple console.log, I can't get my document's object references to populate when I use the populate method.
I'm working on a simple authentication route. My client document is broken into two object references, login and user profiles. In my query I'm searching for a client document where the login profile object reference id matches a previously queried login profile's id. Then I want to populate both the user profile and login profile on the client document, then return the client document.
My console log is showing the client document but the population methods don't seem to be executing. Code is below.
const login = await LoginProfile.findOne({ email });
if (login === null) {
console.log("Account doesn't exist.");
} else {
let validPassword = await bcrypt.compare(password, login.password);
if (!validPassword) {
console.log("Email or Password is incorrect");
} else {
const clientDoc = await Client.findOne({
loginProfile: login,
});
console.log(clientDoc.populate("userProfile").populate("loginProfile");
}
}
I'm probably doing this all wrong but I'm self taught and I'm trying. Thanks for whatever solutions you may have. If you have other ways of implementing this, please share! Thanks!
Welcome to Stack Overflow, MrGeonDeaux
Instead of :
console.log(clientDoc.populate("userProfile").populate("loginProfile"));
You could populate the documents on finding, here's the full snippet:
const login = await LoginProfile.findOne({ email });
if (login === null) {
console.log('Account doesn\'t exist.');
} else {
const validPassword = await bcrypt.compare(password, login.password);
if (!validPassword) {
console.log('Email or Password is incorrect');
} else {
const clientDoc = await Client.findOne({
loginProfile: login
}).populate('userProfile loginProfile');
console.log(clientDoc);
}
}
I am coding a simple registration form using mongoose.
I have use a javascript file to process the values of the registration form.
Here is my registrationButtonAction.js
window.onload = function() {
var User = require('/models/Mongoose Database/user_database');
// this line is causing the problem
var registerButton = document.getElementById("registerMe");
var firstName = document.getElementById("firstName");
var lastName = document.getElementById("lastName");
var usernameRegister = document.getElementById("usernameRegister");
var passwordRegister = document.getElementById("passwordRegister");
var repasswordRegister = document.getElementById("repasswordRegister");
registerButton.onclick = function () {
if(!firstName.value || !passwordRegister.value || !repasswordRegister.value || !usernameRegister.value){
alert("Enter all required fields");
}else if (passwordRegister.value != repasswordRegister.value){
alert("Passwords must match");
}else {
var newUser = new User({
username : usernameRegister.value,
password : passwordRegister.value
});
User.find({username:usernameRegister.value}, function (error, user) {
if (error) throw error;
if(user){
window.location("/register");
}else {
newUser.save(function (error) {
if(error) throw error;
});
window.location("/login");
}
// user.comparePassword(passwordRegister.value, function (error, isMatch) {
// if (error) throw error;
//
// return 1;
//})
});
}
}
}
When I comment the var User = require('/models/Mongoose Database/user_database');, all the checks are working fine inside the onclick function. But when I uncomment it, it is not recognizing the button click.
I want to know whether this is a correct way of taking values from the registration page and storing them in a mongoose database.
You are mixing server and client code. Mongoose models and Node.js functions are not accessible inside window.onload on your client.
To put it simply, you need to create a REST API to perform database operations on the server. You have all the right tools aready, just need to reorder them.
The flow would be as such :
get the values entered in the browser
call an endpoint on your server (for example /api/createUser)
in the express router, have a route called /api/createUser in which you can access your User model and perform creation/deletion/update, etc.
My suggestion would be for you to go through this tutorial which should remove your confusion and bring you up to speed in no time. Good Luck!
Also, Passport can help you with authentication, but I believe you should first learn how to build a basic API. Authentication is a tricky beast ;)
I'm using the nodeJS password-hash-and-salt library to encrypt password which I then store in a DB. This works fine. The problem comes in when I try to verify the password. Looking at the documentation, it should be simple... The example works flawlessly, but verifying a hash which was previously stored in a DB is failing. I've verified that the hash is not changing in-database, and that the hash is been returned when queried... I've also hashed a string and then tried to verify that string using the same string in-code (with no variables). I must be doing SOMETHING wrong... Anyone have any ideas? (Code below, library link here https://github.com/florianheinemann/password-hash-and-salt)
verifyPassword = function(user,pw){
// Connect to db
myuser = {};
var con = connect();
// Run query
con.query('SELECT UID,password FROM users WHERE username = ?', user, function(err,res){
if(err){ throw err; }
else {
myuser.userID = res[0].UID;
myuser.pswdV = res[0].password;
// Verifying hash
//console.log(pw);
//console.log(myuser.pswdV);
password(pw).verifyAgainst(myuser.pswdV, function(error, verified) {
//console.log(verified);
if(error)
throw new Error('Something went wrong!');
if(!verified) {
//socket.emit('popError','Invalid username or password. Please check your password and try again.');
//return {err:'Invalid username or password. Please check your password and try again.'}
console.log('Not verified');
} else {
var token = crypto.randomBytes(64);
token = buf.toString('hex');
myuser.secret = token;
delete myuser.pswdV;
con.query('UPDATE users SET magicSecret = ? WHERE username = ?', [token,user], function(err,res){
if(err) {
socket.emit('popError','Failed to login, this is a server problem.');
//return {err:'Failed to login, this is a server problem.'}
}
else {
socket.emit('login_success',myuser);
// return {err:myuser}
}
});
}
});
}
});
con.end(function(err) {
// The connection is terminated gracefully
// Ensures all previously enqueued queries are still
// before sending a COM_QUIT packet to the MySQL server.
});
};
Please excuse the debugging code... This should give you an idea of what I'm trying to do. If you see why it's failing please let me know.
There are some irreversible actions that user can do in my app. To add a level of security, I'd like to verify that the person performing such an action is actually the logged in user. How can I achieve it?
For users with passwords, I'd like a prompt that would ask for entering user password again. How can I later verify this password, without sending it over the wire?
Is a similar action possible for users logged via external service? If yes, how to achieve it?
I can help with the first question. As of this writing, meteor doesn't have a checkPassword method, but here's how you can do it:
On the client, I'm going to assume you have a form with an input called password and a button called check-password. The event code could look something like this:
Template.userAccount.events({
'click #check-password': function() {
var digest = Package.sha.SHA256($('#password').val());
Meteor.call('checkPassword', digest, function(err, result) {
if (result) {
console.log('the passwords match!');
}
});
}
});
Then on the server, we can implement the checkPassword method like so:
Meteor.methods({
checkPassword: function(digest) {
check(digest, String);
if (this.userId) {
var user = Meteor.user();
var password = {digest: digest, algorithm: 'sha-256'};
var result = Accounts._checkPassword(user, password);
return result.error == null;
} else {
return false;
}
}
});
For more details, please see my blog post. I will do my best to keep it up to date.
I haven't done this before, but I think you will need something like this on your server
Accounts.registerLoginHandler(function(loginRequest) {
console.log(loginRequest)
var userId = null;
var username = loginRequest.username;
// I'M NOT SURE HOW METEOR PASSWORD IS HASHED...
// SO YOU NEED TO DO A BIT MORE RESEARCH ON THAT SIDE
// BUT LET'S SAY YOU HAVE IT NOW
var password = loginRequest.password;
var user = Meteor.users.findOne({
$and: [
{username: username},
{password: password}
]
});
if(!user) {
// ERROR
} else {
// VERIFIED
}
});
then you can call this function from the client side like this:
// FETCH THE USERNAME AND PASSWORD SOMEHOW
var loginRequest = {username: username, password: password};
Accounts.callLoginMethod({
methodArguments: [loginRequest]
});
I have a project on github for different purpose, but you can get a sense of how it is structured: https://github.com/534N/apitest
Hope this helps,
I have found the best way to validate the users password is to use the Accounts.changePassword command and
pass in the same password for old and new password. https://docs.meteor.com/api/passwords.html#Accounts-changePassword
Accounts.changePassword(this.password, this.password, (error) => {
if(error) {
//The password provided was incorrect
}
})
If the password provided is wrong, you will get an error back and the users password will not be changed.
If the password is correct, the users password will be updated with the same password as is currently set.