Getting the error: "No such email address for user." when calling Accounts.sendVerificationEmail( userId ) in meteor - meteor

I am getting an error when I try to send an email verification link to the user. I have used the email feature of Meteor in other projects without any issues. But in the current project, I am getting this error and I have no idea what could be causing it.
The user.emails[0].address does have an email address.
Exception while invoking method 'sendVerificationLink' Error: No such email address for user.
at AccountsServer.Accounts.sendVerificationEmail (packages/accounts password/password_server.js:745:11)
at [object Object].sendVerificationLink(server/user/users_methods.js:25:23)
I am using METEOR#1.3-beta.11 and my code is as follows:
**Client:**
let user = { email: signupEmail,password: password }
Accounts.createUser(user, (err) => {
if(!err) {
Meteor.call('sendVerificationLink');
}
})
**Server:**
Meteor.startup(function () {
process.env.MAIL_URL = 'smtp://postmaster%40sandboxd9...7.mailgun.org:<pwrd>#smtp.mailgun.org:587';
});
...
Meteor.methods({
sendVerificationLink() {
let userId = Meteor.userId();
if ( userId ) {
return Accounts.sendVerificationEmail( userId );
}
}
});
process.env.MAIL_URL and mailgun is set correctly. I have tested it from server using the following server code and the email was delivered correctly.
Email.send({
to: "xxxxx#gmail.com",
from: "xxxxx#gmail.com",
subject: "Example Email",
text: "This is a test email."
});

I found the error after a day of wasted debugging. There is nothing wrong in the code I posted above in my original question. There was an error in the schema definition for User collection with another package that I had installed - jagi:astronomy. The validation rule for 'Verified' (email verified flag) was set to string. It should have been boolean. I still don't understand why that would prevent from sending out the verification email though. Email field validation itself was correct and email was saved. But once I changed the validation rule to Boolean for 'Verified' field to boolean, the error went away.

Related

Disabling auth/user-not-found functionality

I have a React application with email & password sign in method available (implemented with firebase). In the log in form, if you enter incorrect email, you will get auth/user-not-found error as expected.
What are my options to disable this kind of behaviour? To me it seems to be a security risk where malicious user could query email addresses and see if the user exists on my platform or not.
You cannot disable what firebase would respond with, but you should handle the error in your client to show a less specific response.
try {
...
} catch (err) {
if (err.code === 'auth/user-not-found') {
alert("Invalid email address and/or password")
} else {
console.log("Other error handling method")
}
}

Firebase user.delete() method works but with error

I am using angular, and have an application that stores user details, and login info. When trying to delete a user, I am first deleting all the user related information. Then asking the user to re-authenticate themselves, after authentication, user gets logged out, and their basic details fetched to show profile id deleted followed by their sign-in info using user.delete().
All this works as expected, but at the end I am getting an error. Why am I am getting this error even when I have already logged out the user of the application.
Error Message: {code: "auth/user-token-expired", message: "The user's credential is no longer valid. The user must sign in again.", a: null}
My code -
deleteAccount(){
var userToDelete = firebase.auth().currentUser;
this.logout();
this.store.dispatch(UI.StartAppLoad({status:'Deleting User Details...'}));
this.userService.DeleteUser(userToDelete.uid)
.then((res)=>{
console.log(res);
}).catch(this.HandleError.bind(this));
userToDelete.delete().then(
(res)=>{
console.log(res);
this.uiService.showSnackbar('User Account Deleted',null,3000);
this.store.dispatch(UI.LoadApp());
}
).catch(this.HandleError.bind(this));
}
logout() {
this.afAuth.signOut();
}
where, HandleError is used to display the Error Message in a snackbar.
deleteAccount() is called after the user successfully authenticates themselves.
Instead of getting the error message displayed, I want to display the message 'User Account Deleted'.
Entire Flow -
onDeleteAccount(){
const confirmResult = this.uiService.showConfirm({
isDanger:true,
title:'Delete Account?',
content:'All your user account data will be permamnently deleted.'+
' You will need to create a new account later. Are you sure you want to continue?',
okText:'Delete'
});
confirmResult.subscribe(async isDelete=>{
if(isDelete){
this.store.dispatch(UI.StartAppLoad({status:'Deleting Excercise Data...'}));
const isResetDone = await this.trainingService.resetPastExercise();
if(isResetDone){
this.store.dispatch(UI.StartAppLoad({status:'Deleting Follow list...'}));
this.userService.clearFollowList();
this.authService.actionToPerform.next(actions.Delete_Account);
this.store.dispatch(UI.LoadApp());
this.router.navigate([AppRoutes.ReAuthenticate]);
}
}
});
}
Authenticate Page's submit() method:
this.authService.reauthenticate({
email:form.value.email,
password:form.value.password
});
this.authService.deleteAccount();
AuthService:
reauthenticate(authdata: AuthData) {
this.store.dispatch(UI.StartLoading());
var credential = firebase.auth.EmailAuthProvider.credential(
authdata.email,
authdata.password
);
this.afAuth.currentUser.then((user) => {
user.reauthenticateWithCredential(credential)
.then((res)=>{
this.prevPwd = authdata.password;
console.log(res);
this.store.dispatch(UI.StopLoading());
})
.catch(this.HandleError.bind(this))
});
}
And then the above method deleteAccount()
Please suggest.
As explained in the doc, this happens because:
delete() is a security-sensitive operation that requires the user to
have recently signed in.
The doc also indicates that:
If this requirement isn't met, ask the user
to authenticate again and then call firebase.User.reauthenticateWithCredential.
So, you need to handle this specific error and do as indicated by the doc, i.e. "ask the user to authenticate again and then call reauthenticateWithCredential."

User Not Found when trying to reset password

I have a user who forgot their password. Using the Accounts package the user tried to get their password reset with the "Reset password" function. When they enter their email address it states "User Not Found".
What is causing this? More importantly how do I fix it? I've been beating my head into a wall trying to find a solution so any help would be great. I've tried to duplicate but my test accounts don't have the same issue.
My build is Meteor 1.2 with the accounts-password and accounts-base packages. My setup is:
passwordSignupFields: "USERNAME_AND_EMAIL"
When resetting the user's password, Meteor tries to look up the user by the provided e-mail. If it cannot find the user using the e-mail - it throws the "User not found" - link to code here
Meteor.methods({forgotPassword: function (options) {
check(options, {email: String});
var user = Accounts.findUserByEmail(options.email);
if (!user)
throw new Meteor.Error(403, "User not found");
const emails = _.pluck(user.emails || [], 'address');
const caseSensitiveEmail = _.find(emails, email => {
return email.toLowerCase() === options.email.toLowerCase();
});
Accounts.sendResetPasswordEmail(user._id, caseSensitiveEmail);
}});
Is the user providing the correct e-mail? Check that the e-mail being provided actually exists in the DB in the Meteor.users collection

Meteor custom login procedure

This Meteor app has the insecure and autopublish removed and accounts-ui accounts-password added.
The code below needs to get the username and password, send them the to server which will run a method validateUser that returns true if valid.
validateUser tries to login to another server on the web, and returns true if successful, then my code should create a user account for this user.
The app is crashing because of this line
Accounts.createUser(useername: digest[0], password: digest[1]);
But even if it does not, Is this the meteor way to get this particular task done? Thanks
Edit:
After adding {} to the problem line in order to pass an object as suggested in the comments, I now get this error printed in the terminal;
Exception while invoking method 'logMeIn' Error: Match error: Failed Match.OneOf or Match.Optional validation in field password
<template name="myLogin">
<input type="text" name="username">
<input type="text" name="password">
<button id="logMe">log me in</button>
</template>
Template.myLogin.events({
'click #logMe': function() {
var credentials = [$('#password').val(), $('#username').val()];
Meteor.call('logMeIn', credentials, function(err, result) {
if (result) {
console.log('logged in!');
}
});
}
});
// on the server
Meteor.methods({
logMeIn: function(credenticals) {
//do work , if logged in, do next line
console.log("user account created");
Accounts.createUser({useername: credenticals[0], password: credenticals[1]});
}
});
Match error: Failed Match.OneOf - is because this method checks if email or username is presented in the object you are passing. You have typo in username and don't have email.
Next thing you are saying, after fixing typo you get Exception while invoking method 'logMeIn' Error: Match error: Expected string, got object in field username
This is because you have array with two undefined "members". Look at your jquery selectors. You are trying to select by id # but have inputs without ids.
Please organise yourself.
Your line
Accounts.createUser({useername: credenticals[0], password: credenticals[1]});
Has two typos, it should be
Accounts.createUser({username: credentials[0], password: credentials[1]});

Meteor - get email address of attempted login

I need to get the email address that a user was using in a failed login attempt to check if they registered outside of the application.
Here is my code;
Accounts.validateLoginAttempt(function(info){
if (!info.allowed)
{
console.log("we don't have that user " + info.user.emails[0]['address']);
return false;
} else {
var user = info.user;
console.log("created " + user.createdAt);
console.log("emails is " + user.emails[0]['address']);
return true;
}
});
If the login is not allowed I get this Cannot read property 'emails' of undefined because obviously the user is not in the users collection. My question is, is the email and password of the attempted login somehow available to see?
Try this:
Accounts.validateLoginAttempt(function(info) {
console.log("user");
console.dir(info.methodArguments[0].user);
console.log("password");
console.dir(info.methodArguments[0].password);
});
EDIT: Also, I wrote a Meteor package to solve this problem, available on Atmosphere at https://atmospherejs.com/chipcastledotcom/accounts-email.

Resources