How to reset password in meteor application - meteor

I am building a Meteor application and am using the oaf:accounts-entry package to handle my user registration & authentication. I am working on the reset password function right now. However, when I click on "email reset password link", the application doesn't email me anything. Can someone help me or point me to instructions on how to configure the reset password function for the oaf:accounts-entry package? After doing a google search, I could not find instructions on how to configure it. The relevant packages I have installed are:
oaf:accounts-entry
accounts-password
email
Thank you!!

The password reset functionality should be working as it's provided by the package.
Have you properly configured your emails smtp settings and tested that your application is dispatching emails properly?
https://gentlenode.com/journal/meteor-3-smtp-configuration/5

NOTE: Using Meteor JS 1.6.1.1, package required are accounts-ui, accounts-password
To make forgot password link visible in the signup/sign in a widget, you need to do add little configuration in a file at location ROOT_FOLDER/client/main.js. The code is as below,
Accounts.ui.config({
passwordSignupFields: "USERNAME_AND_EMAIL"
});
If you do not choose passwordSignupFields: "USERNAME_AND_EMAIL" and choose something like passwordSignupFields: "USERNAME_ONLY", you won't be able to see forgot password option in the signup widget. (No one will tell you this, I discovered this weird scenario myself. Still, I wonder why MDG team did this? )
At Server end you also need to add little code at location PROJECT/server/main.js just outside Meteor.startup(()=>{}); to provide an email template for reset password link. Below is the code you need to adjust some properties yourself.
var username = 'you_id#gmail.com';
var password = 'your password';
var server = 'smtp.gmail.com';
var port = '465';
process.env.MAIL_URL = 'smtps://' +
encodeURIComponent(username) + ':' +
encodeURIComponent(password) + '#' +
encodeURIComponent(server) + ':' + port;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
Accounts.emailTemplates.from = 'support_team#yourappname.com';
Accounts.emailTemplates.siteName = 'APP NAME';
Accounts.emailTemplates.resetPassword = {
subject(user) {
return "Reset Password Link.";
},
text(user, url) {
return `Hello!
Click the link below to reset your password.
${url}
If you didn't request this email, please ignore it.
Thanks,
APP Team.
`
},
html(user, url) {
// This is where HTML email content would go.
// See the section about html emails below.
}
};
STEP 1:
See if you are able to view forgot password on the signup widget as below.
STEP 2:
When you click "forgot password", you should be able to view below popup at same widget location as below.
on valid Email entry, you must see a success full notification and most importantly you must receive a mail for reset password link as below.
Step 3:
When you click on the link, you can see a new window with a popup as below (NOTE: You must click the link before given token expiry time).
Voila!!! just add a new password and you automatically login to given page. Everything is already provided to us as discussed above by Meteor. You just need to configure the stuff and get it running.

Related

Amplify Reset Password Hangs

I used amplify's withAuthenticator as shown below for my /mainPage path. But when I tried to reset password, supply the confirmation code and submit it, the page hangs. It should refresh my /mainPage page.
import { withAuthenticator } from "#aws-amplify/ui-react";
import "#aws-amplify/ui-react/styles.css";
function MainPage({ signOut, user }) {
return (
<>
<h1>Hello {user.username}</h1>
<button onClick={signOut}>Sign out</button>
</>
);
}
export default withAuthenticator(MainPage);
Lots of missing information here but.. here's go nothing
page hangs == there was an error which can be viewed and inspected by your browser's developer tools - you should attach the error here in order to help others to assist (next time of course)
do you use the default reset password flow or make something custom?
in any case - why do you use the signOut method for this process? the user is not signed in (forgot password) so there is no point to sign out
The only scenerio I can think of is if the user is forced to change password (e.g. - getting kicked off with the signOut method, change password and sign in again). Even for that use-case - the signOut method alone (as present in your code) is only the first phase of this process (and not the entire process)
With that being said, I'll try to suggest a process that will simplify things for you (as the name Amplify applies) - reset one's password by using the build-in mechanism already provided with the library (please read the docs)
Long story short, the process would be:
User need to change password (forgot or forced to perform this action)
An email with temporary code is then send to user's email (this code is only valid for one hour - please generate it only when user is able to actually change current password)
User copy the code from email to your form, and then enter the new password
After confirmation - password changed. It's up to you to decide if you want to enter user into your app of force re-entry (e.g. typing the new password in the login screen in order to sign-in)
And you can use the forgotPassword and forgotPasswordSubmit methods in order to fulfill that process (more information in the link provided above) . In any other case (you have a custom flow) - please share more details
One last technical note:
In react this form of event handling
<button onClick={asyncFunc} >I am a button!</button>
Is the short way of wrtiting
<button onClick={async () => { await asyncFunc1(); await asyncFunc2() } }>
I am a button!
</button>
So either write your own custom async function and use the short way (preferred) or use the long way and use several functions in order to materialize your async process steps
Good luck 😊

How to get Iron-router query parameters in server hook

I am trying to add a referral system to my project, so currently I am basing it off of this package. The issue I am running into is my project only uses accounts-google and not accounts-password. The way this package works is it adds the iron router query parameters for the referrerCode (/register?r=ReferralCodeHere)through a preSignUpHook. I believe this only works with accounts-password wont work when creating an account with an API such as accounts-google.
My idea around this is to use a Meteor.users.before.insert hook to grab the iron router query parameters and insert them into my referrerCode field in Meteor.users since I'm already using Meteor Collection Hooks for a couple of other things.
The issue is I havent been able to find a way to get the query parameters on the server, I was hoping to do something like this:
Meteor.users.before.insert(function(userId, doc) {
doc.referrerCode = Referrer._referrerCode; // Link 1
});
(Link 1)
But this will just come up as undefined.
If I'm at my register page and it has a query like this for example: example.com/register?r=12345 Then I run Router.current().params.query.r on the client it returns 12345. Basically I just need to have that saved to the referralCode field in Meteor.users when a new user creates an account, if a referral code exists in the register URL.
I'm a bit lost with this one. I thought about setting it as a Session variable and then getting that in the before.insert hook, but that again only works on the client side. I'm thinking a meteor method might be best for this, but I'm not exactly sure how I would structure it. Any help is greatly appreciated!
Put the referral token into profile
Use that in your hook
Below I've copied some code that I've used before. It is built around an Invitations collection that tracks who invited who:
client:
var profile = {};
... any other profile settings you've captured
if ( token ) profile.referralToken = token;
Accounts.createUser({ email: email, password: password, profile: profile }, function(err){ ...})
hook:
if ( options.profile.referralToken ){ // referral case
var invitation = Invitations.findOne({ token: options.profile.referralToken });
if ( invitation )
user.invitationId = invitation._id; // the invitation used
user.invitedBy = invitation.userId; // the referring user
}
delete options.profile.referralToken;
}
return user;

Altering email sent to users when password is updated

There is an email that is generated when the users' passwords are updated, that is sent from the admin to the user notifying them what the new password is. I've been looking for a way to change that but cannot find any mention of it in the docs.
the closes thing I found was wp_password_change_notification, but that sends email to the admin, not the other way around.
If you mean you want to change the content of the message sent after resetting a lost password then the retrieve_password_message filter would work.
add_filter("retrieve_password_message", function ($message, $key) {
// modify the message with your code here
return $message;
}, 10, 2);

Secure way to store pending user's password in Meteor

For my Meteor application, I would like to have the following signup process:
User registers username, email and password. (He's not able to log in yet.)
Confirmation email sent [Accounts.sendEnrollmentEmail]
User confirms email [Accounts.onEnrollmentLink]
User is created. [Accounts.createUser] (He's able to log in.)
In order to achieve this, I feel like I would have to store the plain text password in a table of temporary users (step 1) in order to create the actual user later (step 3). Obviously this is a horrible idea.
I could of course only ask for the password as of step 3 and create the user at once - but it's not the behavior I would like to achieve.
So: Is there a proper way to store the password securely to later pass it to the user creation? Or is there a way to create a not-loginable users?
There is not much you have to do yourself as Meteor brings everything you need for save password storage when you create a user with the built in methods. So you should use these methods from the beginning (Your step 1: Accounts.createUser, step 2: Accounts.sendVerificationEmail, step 3: Accounts.verifyEmail, step 4 isn't necessary anymore).
Now to get where you want to be you can use an approach like David Weldon suggested but use Accounts.validateLoginAttempt on the sever side. That is a little easier and the login isn't allowed in the first place.
For example you could have this code server side:
Accounts.validateLoginAttempt(function(loginAttempt){
if (!loginAttempt.allowed) {
// Only tell the user that something went wrong but not what to enhance security
throw new Meteor.Error(901, 'Your login credentials are wrong. Try again.');
} else {
// In some cases this method isn't invoked with a correct user object...
if (!loginAttempt.user) {
throw new Meteor.Error(902, 'No valid user object. Make sure to validate your email address first.');
}
// If email verification is required check if the user has a valid email address and don't allow the login if he has none
if (!loginAttempt.user.emails[0].verified) {
throw new Meteor.Error(902, 'Your email address has to be verified first.');
}
// We have a correct login!
return true;
}
});
And now on the client side you can use a logic like this for the login
Meteor.loginWithPassword(email, password, function(callback) {
if (callback === undefined) {
// Your login logic
} else if (callback.error == 902) {
// Your "not verfied" logic
} else {
// Your other login errors logic
}
}
Note that you may have to adjust the registration process a little bit, too, as Meteor per default tries to login users directly after registration but this will not be possible anymore.
Also note that you may use Accounts.validateLoginAttempt for more than just that. For example you also could implement a logic here to only allow a certain amount of bad login attempts from the same IP.
We've used a slightly different pattern in our app based on the accounts package
User registers
User is logged in normally
Out main site template conditions content with
<template name="main">
{{#if currentUser}}
{{#if verified }}
...
{{else}}
Notice to user to look for their verification email
{{/if}}
{{/if}}
</template>
Based on a helper function
Template.main.helpers({
verified: function() { return Meteor.user().emails[0].verified; }
});
This meets the requirement that the user can't do much if anything until they have been verified yet uses the accounts package in a simple and secure way.
I could see taking a related approach using iron:router as well.

As3 Graph API Logout

i'm developing an application that'll be played by different's users, but i'm using the as3 graph api for authenticating users and posting on their wall, and i need to logout each user, before next user start his session on as3 graph api:
http://code.google.com/p/facebook-actionscript-api/
I search to force FB to ask for login's info but after a logout when login again, API skip the step and log, on the last user session.
None of the solutions I have seen on the web did work for me. The problem is indeed with StageWebView facebook cookie not being cleared on logout with FacebookMobile.logout() call. Loading logout.php with access token did not help me probably because there is no "next" parameter value for air applications that makes sense. I have seen people suggest to use localhost or facebook.com there but none of these options worked.
I have come up with a really questionable solution, but it works for now.
The point is to logout user in facebook normally like he would logout on his own. To do this we need to load facebook.com in StageWebView and click logout. Logout button is a submit form item for "logout_form" html form. So we need to make a javaScript call
document.getElementById('logout_form').submit();
in our StageWebView. And we can do just that by calling
webView.loadURL("javascript:document.getElementById('logout_form').submit();");
in ActionScript.
The full code that I use for now
protected var _logoutAttemptInProgress:Boolean = false;
public function fbLogout():void{
if(!_isLoggedIn) return;
if(_logoutAttemptInProgress) return;
_logoutAttemptInProgress = true;
var webView:StageWebView = new StageWebView();
webView.viewPort = new Rectangle(-1, 0, 1, 1);
webView.stage = this.stage;
webView.loadURL("http://www.facebook.com/lksmlrsgnlskn");
webView.addEventListener(Event.COMPLETE, runLogoutJs);
function runLogoutJs(event:Event):void{
webView.removeEventListener(Event.COMPLETE, runLogoutJs);
var jsString:String = "document.getElementById('logout_form').submit();";
webView.loadURL("javascript:"+jsString);
webView.addEventListener(Event.COMPLETE, closeWebView);
}
function closeWebView(event:Event):void{
webView.removeEventListener(Event.COMPLETE, closeWebView);
webView.stage = null;
webView.dispose();
_isLoggedIn = false;
_logoutAttemptInProgress = false;
}
FacebookDesktop.logout(null, APP_ORIGIN);
}
"lksmlrsgnlskn" is just some random garbage to get to error page that is much smaller than main page and loads faster.
FacebookDesktop.logout is to clear any local SharedObject data that Facebook lib might still have.
This is an issue that's been continuously revised by FacebookMobile, Facebook, and FacebookDesktop. Basically, you'll need to make sure you set FacebookDesktop.manageSession = false; and pass in the 2nd argument of "logout" your site's api url. If that doesn't work, the other method is to use "reallyLogout", as detailed here in this thread.
The notes in comment #24 detail the way to expos the Access Token from FacebooMobile (or whichever singleton you're using), and then manually calling the logout.php method on Facebook, with the access token.
http://code.google.com/p/facebook-actionscript-api/issues/detail?id=297#c24
This is a problem with the cookies, i mean, the firts user session remains and when you press to login the API logs in the first user.
I dont know why but the Facebook Api log out method dont log the user out of facebook, only log the user out from your application.
If you came to a solution or think something else, let me know so we could get the solution.

Resources