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.
Related
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")
}
}
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
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.
In my Meteor.js application, I'm using the accounts-google package in order to be connected with a google account. I have two questions about it.
First, is there a simple way to filter the account used? I would like that the users can connect only with google accounts belonging to my company. Our google account mails end with #mycompany.com. So it would be a simple mail filtering.
I already done that with some post log in hooks but I was wondering if there was a simpler way for doing it.
My second question is how to force the opening of the google account choser. For now, if I try to connect with a wrong google account, and if I only added this account (like in gmail, drive, etc), the google choser doesn't pop and automatically connect with this wrong account. So, in this case, the user is totally blocked (my application disconnect him if he tries to log in with a wrong account but the google account module doesn't propose him to connect with another account).
Thank you for your help.
In order to restrict signup/login to your domain, simply do on the server:
var checkEmailAgainstAllowed = function(email) {
var allowedDomains = ['mycompanydomain.com'];
var allowedEmails = ['otheruser#fromotherdomain.com','anotheruser#fromanotherdomain.com'];
var domain = email.replace(/.*#/,'').toLowerCase();
email = email.toLowerCase();
return _.contains(allowedEmails, email) || _.contains(allowedDomains, domain);
};
Accounts.config({
restrictCreationByEmailDomain: function(email) {
if (!email) {
throw new Meteor.Error(403,'This email address is not allowed');
}
if (!checkEmailAgainstAllowed(email)) {
throw new Meteor.Error(403,'This email domain is not allowed');
}
return true;
}
});
And to login, you'll need on the client:
Meteor.loginWithGoogle({
forceApprovalPrompt: true, //this is what you want, to rerequest approval each time that prompts the google login prompt
loginStyle : "redirect", //or not, depending on your need
requestPermissions : ['profile', 'email'],
requestOfflineToken: true
}, function (err) {
if (err)
// set a session variable to display later if there is a login error
Session.set('loginError', 'reason: ' + err.reason + ' message: ' + err.message || 'Unknown error');
});
Side note:
Alternatively, you can set up your routes so that every time a new route is called, you login, and every time a route is destroyed or on windows's unload, you call logout. This causes login/logout roundtrip everytime the route changes, but you'll make sure that the new user always has a fresh session
Edit:
When you log out of your meteor app, you don't log out of google. That's how oauth works. So, basically, if you want a meteor log out to also log the user out of their google account, so that the next time they come back, they need to provide credentials again, you should do:
Meteor.logout(function(e) {
if (e) {
console.log("Could not log the user out")
} else {
window.location.replace('https://accounts.google.com/Logout');
}
});
This uses the callback of Meteor.logout() so that when the logout is successfull, the user is redirected to google's central account logout url where the user is also logged out of all google services.
I'm trying to create a user account through the apigee JS API. This worked just fine when I was last doing this before the holidays in mid December. Now, however, I get a 401 Unauthorized error reading token_expired.
Is there a way to refresh the token? I don't know why it would have expired.
This is what I'm trying. First I instantiate the data client. No problems here:
var dataClient;
var client_creds = {
orgName: '*******',
appName: '*******'
}
dataClient = new Apigee.Client(client_creds);
Later, when trying to create a new user, I get the token_expired error:
dataClient.request(options, function (error, response) {
if (error) {
console.log(response);
alert("Something went wrong when trying to create the user. " + response.error)
// Error
} else {
// Success - the user has been created, now login.
dataClient.login(user.email, user.password,
function (err) {
if (err) {
//error - could not log user in
console.log("There was an error logging in " + user.name);
} else {
//success - user has been logged in
}
}
);
}
});
I've also tried dataClient.signup, but same error.
There are no refresh tokens within App Services; you'll need to follow the login flow in order to retrieve a new token. Note that you can specify the ttl parameter, like so, so you don't need to do this as frequently:
https://api.usergrid.com/{org}/{app}/token?ttl=604800
By default, this is set to 7 days, but you can change the default app max ttl to 0 (non-expiring) or something else like 31104000000 (365 days).
To do that, you make a PUT request:
https://api.usergrid.com/{org}/{app}/?client_id={app_client_id}&client_secret={app_client_secret}
With JSON payload:
{
"accesstokenttl":0
}
Or for 1 year:
{
"accesstokenttl":31104000000
}
If that doesn't work for you, the authorization tokens for the JavaScript SDK are kept in your browser's local storage. In Chrome, use the Developer Tools. In the Resources tab on the left hand side expand the Local Storage entry. You should see something like "http://usergrid.dev" or something similar. Choose that and on the right hand side you should see an entry for accessToken. Delete that and it should solve your problem.