#274 Remember Me & Reset Password
Jul 11, 2011 | 12 minutes | Authentication
It is easy to create authentication from scratch, but how do we extend it with more features? Here I add a "remember me" check box and a "forgotten password" link.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Since rails detects and rejects cookies that have been tampered with, could we just use the user id rather than the auth_token, and put it in a signed cookie? Or, since sessions seem to actually be signed cookies (no?), is there a way in rails to just directly extend the expiration of the session cookie (if there's nothing else we keep in the session that we want to expire sooner)?
Great point. You can store the user id in a signed cookie instead of generating a custom token. However for permanent cookies I prefer to keep it separate so it gives you more control over when to expire the session. For example you can reset the
auth_token
every time someone resets the password, or maybe every time someone logs in to automatically log-out previous ones. There's a lot more flexibility here.It is also possible to change when the session cookie expires, but I think it's better to stick with a separate cookie.
Is there then a reason why you didn't use
cookies.permanent.signed
for theauth_token
instead ofcookies.permanent
? It seems you can chain them and I can't find any drawbacks from using this.Signing cookie adds overhead to the size (http://yuiblog.com/blog/2007/03/01/performance-research-part-3/). So that depends on the security you need.
For better security you want to save also a expiry time inside the cookie and sign it. Then you can check e.g. that the cookie isn't more than year old so that info in old computers cannot be abused. But in most cases the way described in this screencast is enough.
Also, about Devise, it's an engine, so changing views or controllers is as simple as putting them directly in your app. With rails engines, what's in your app takes precedence over what's in the engine. If you have no view for X, the it takes it from the engine. If you do, it uses yours. I like the idea of building things from scratch (this is a great episode) and minimizing plugin bloat, but it's worth mentioning.
You're right, it is easy to customize Devise views. My point being that if you're going to customize this anyway, I feel it's a good portion of the work involved in adding these features from scratch. I also find I often need to customize more than this in Devise, such as overriding certain controller actions, and then things get messy.
Ryan, I agree with you.
I used to use Devise. But then I realised I spend way more time trying to customise it than just implementing it from scratch.
This is especially true when you need to do something that Devise doesn't support "out of the box".
Once again, nice screencast!
However, I think you have too much logic inside te password_resets_controller. Especially the 2.hours part. Now for small apps this might not be a big problem, but otherwise, I would create something like a PasswordReset class in the model directory to handle this logic for me.
And I agree with @introspectif that Devise is childishly easy to customize. So much so that I would never write my own authentication. There are too many security pitfalls to remember.
I agree that should probably go somewhere else, maybe in the User model or a separate config. I would hesitate to create a PasswordReset class just for this. True that it might fit the RESTful paradigm when there is a resource backing it, but I don't think the end result would be clearer or easier to read.
Good point about security. I personally feel Devise gets messy when needing to customize the behavior, however this may be just a personal opinion. I would love to see something lower level that can handle all of the security measures without taking over controllers. Something along the lines of Authlogic but which followed MVC a little better.
What's with Authlogic anyhow? I always felt it was the better level of abstraction compared to Devise.
I do like it that Authlogic does not try to take over views, but I think there are better solutions out there. It always bothered me how much it knows about the current request/session, and it felt a little over-complicated.
The authentication gem sorcery claims to be a "stripped-down, bare-bones authentication library" that lets you add common auth functionality from the library to your own controllers.
I haven't used it yet, but I plan to give it a shot on my next project.
https://github.com/NoamB/sorcery
Sorcery has been on my list to check out, but I haven't yet. Thanks for the reminder!
I also agree with @Iain and @introspectif that there are too many security loopholes to remember to close each time to build from scratch.
Also I would suggest adding an index on the email column of the user model since every time someone logs in you are performing an
user = User.find_by_email(params[:email])
Are there any specific security loopholes you see that would be difficult to remember? The most common security issue is hashing the password which is now handled nicely in Rails 3.1 with
has_secure_password
.Good point! The
auth_token
should be indexed as well.Ryan,
One problem with your method is that, while the authentication tokens cannot be guessed they can be duplicated and used on another system. It's close to session fixation. I think that the user record should probably store their log-in OS/Browser checksum to validate any returning users.
At least then it would be harder to steal a session.
I find users often want to log-in through multiple devices at the same time. Also if one can steal the cookie it would not be difficult to spoof their user agent.
I think it depends on the app, if you are making a banking site then security is much more critical and then you probably shouldn't listen to me. :)
Awesome episode as usual.
You're right, I prefer using custom logins and authentication over Devise or other methods. I just feel "out of control" when using a plug for something as secure and important as my login.
Keep up the great work!
Nice work. Again for those who didn't understand, this screencast should be consider as an introduction to authentication. The purpose of it is not to define all security hole and patch them.
The Devise source code is very good at this. The engine cover a lot of advance features. I suggest everyone to have a look at it and learn from it.
Secure an application is not an easy task to accomplish. I suggest everyone to create a checklist and verify there projects against it.
For anyone who is still using ruby 1.8.7 for rails 3.0.5
SecureRandom.urlsafe_base64 will generate a method not found error. I used SecureRandom.hex as a substitute and it worked. Just thought I'd share in case this helps anyone...
Nothing wrong with hex, but if you want base64, you could do this:
Thanks guys! That helped a lot! :)
Thanks for the hint -- exactly what I needed for my "legacy" app.
I like episodes about gems much more: just a little piece of code, and great result. This time i didn't see that. Instead, we got 5 times more code to remember - that's hard for me. :)
Still, there's no need to show everything in things-from-scratch, it's complicated, boring, and will never be the same for other case.
In my opinion, for modern small website we should forget about registering user emails - only omniauth - it's fast, it's handy, but i don't know a simple way to get it up and running on rails yet. For example: devise + omniauth still requires me to know user email. I don't really need it. I'd love to come to website, press "Add comment" button, choose authentication provider, and that's it (just like on railscasts, btw)
Anyways, i'll come back here, to this Episode, whenever i will need authentication from scratch.
Well I feel bad because I have been providing feedback that the screencasts have focused too much on gems. I like to see things from scratch, it helps become a better coder. Omniauth is a perfect example, sure you can just plug it into devise, but what if you need to use external services separate from login - most people would be stuck because they've relied so heavily on gems to do this kind of work. All I can say is we have a difference of opinion, i just wanted mine to be heard because I like a variety of screencasts, sometimes about specific code, and sometimes about gems.
I too prefer Omniauth for authentication, but not everyone wants to use external services for auth. Even when using Omniauth it's good to provide a fallback for username/password if users don't want to link the account to twitter/facebook.
Thanks for the feedback regarding gems vs. from scratch. I try to cover both because I think they both have their place. There are many cases where gems don't quite fit and require so much customization that the dependency is not worth it. Authentication is often that way for me.
Hi, Ryan. Just an observation.
At 5:45 you say something about not letting bad guys know if an email is already registered.
I've heard many people arguing that and many sites implementing it. My experience so far:
Why is it useless? Because on every site I've tried, you can just try to register with a given email address and it gives an error saying "email already registered" if it is.
@Javi, the idea is that authentication requires two parts - a
username
andpassword
. However, there are tools that allow you to brute force attacks on a login form.If the flash/error message changes depending on whether the username is valid, it will take far less time for a hacker to determine a valid username. Once a valid username is found, it becomes a simple attack (unless you implement some kind of failsafe in your code for multiple incorrect password attempts)
Mathematically, imagine it takes a computer 10 hours to brute-force a field of 64 characters (it's not, but I want easy math). If error messages don't reveal that a given username exists, the computer is required to compute 10x10 = 100 hours (for each username generated, it needs to produce passwords as well). However, if the hacker can determine a valid username first (10 hours), and then only brute-force the password (another 10 hours), it only takes 20 hours to hack the site.
It's not "useless", but it's not full-proof either.
and, back to parent post, imagine - i'm a hacker, and tryng to register existing email, it shows an error, so now i know valid email to attack.
Very good point. If you're giving an error that the email address is registered then there is no point in making the password reset message generic. In that case you might as well go with a more user friendly approach and state that the email address was not found.
I mentioned in the screencast that you may want to change that experience depending on the app.
Ryan,
Nice Podcast as always! You might want to consider doing a podcast on Two factor Authentication since security has been in the media lately and on our minds. https://moocode.com/posts/2-two-factor-authentication-with-rails is a nice tutorial but I think you could make it into a great podcast! Just a though thou. ;0)
Checkout https://github.com/rejeep/authlogic-password-reset-tutorial for reset with Authlogic!
Great episode. And I too want to put my vote down for more "from scratch" episodes.
I love the gem community and all the Github repos out there, and while I sometimes use these screencasts to find new "gems" amongst the gems, I mainly use it to learn and follow along while I write the same code, in my own style.
Thanks again!
Thanks for the feedback. I will try to do both because I think both have their place. I too try to reduce the number of gems I use in a project because having many dependencies has bitten me in the past.
Nice to see you active in the comments section as well. Wish you dropped by a little later to allow me to add this question to my reply, but here goes:
In the episode at 8:13 you talk about the URL the user uses to reset his/her password and that it isn't the most elegant RESTful route, but "it will work for us here".
I love (almost) all the screencasts you publish, and I watch every one of them at the start of the week (go self employed!) but I've noticed you've taken these "quick and dirty routes" a couple of more times in the past, and every time I hear you say that I get a nasty feeling, that I am following along writing some great code, and suddenly we make a shortcut and you leave me (us?) high and dry, wondering what I should do to make it actually be the best RESTful way to handle this.
On internal code (code that is never shown to the outer world) I don't mind quick'n'dirty techniques from time to time, if it helps me move on so I can come back to it later, but crucial parts (database layout) and code that is shown to the outside world (routing), I like to make it as good as possible.
Now this isn't criticism, instead I hope you take this as positive feedback. And perhaps you could elaborate on ways to improve the route at 8:13 for this screencast.
Thank again, and obviously we all have to try things ourself, so I'll definitely be trying to improve that piece of code.
That's a good point. When I mentioned the edit action not being truly RESTful I am not hiding a better solution, but more pointing out I am intentionally not following REST here. I considered a couple alternatives when preparing this episode.
What I consider the "proper" way to do this would be to have two controllers/resources. One being PasswordResetRequests with new/create actions, and one being "UserPasswords" with edit/update actions. But two controllers seem overboard for this one feature.
Alternatively we could handle the editing of the password in the Users controller, after all it is the User model we are working on, but if we add a way to edit the user profile then there is a conflict here. Suddenly the edit/update actions would need to have several "if" conditions determining if it is editing the profile or resetting the password. Not only that but it is mixing the password reset feature into other parts of the app. This would quickly get messy.
REST is actually more about the URLs than it is controllers, so we could keep everything in the same controller but add custom URLs. However, this would require 4 complex lines in the routes file instead of the simple
resources :password_resets
. I do not like that solution either.So, we're left with leaving everything in a PasswordResets controller which follows the REST pattern but it is not truly RESTful because it is working on two separate resources. Still I consider it to be the best solution for this problem. Maybe there are ways the Rails router itself can be improved to handle these situations.
Hey Ryan, thank you for the explanation. That makes a lot of sense. Still though, after reading your comment and seeing the episode I personally would prefer to go the UsersController way, having a special "reset_password" action.
I haven't tested this yet so I don't know if this is correct, but I guess this is all that is needed to get it working in the routes, which isn't all too complex and requires only three extra lines (two if you already have the :users resources):
routes.rb
or as an alternative:
UsersController
Actually the UsersController should be like this, the above is the update action, which should stay the same:
I can confirm that this method works. Thanks for the example.
Fantastic episode, Ryan. I am an experienced developer but a newbie to Rails. I enjoyed this "from scratch" episode immensely.
Do you any episodes where you go without scaffolding? Any where you plug in the different parts like controller, model(is this always necessary), view, custom validation, helpers by hand and as late as possible?
I see many blog posts about how scaffolding is not the recommended way but haven't found much guidance on how to do this from scratch.
Also, I am also very interested in BDD (behaviour driven development) and am hoping you can give some guidance on how to do that.
Thanks for your contribution
-Venu
I didn't use scaffolding in this episode, however I did use several generators (controller, mailer, migration). I think most Rails developers use these generators.
That said, I do scaffolding in my everyday development through Nifty Generators. I encourage everyone to create their own scaffold generators to improve their workflow.
I think scaffolding just gets a bad rap because the built-in scaffold generator is near useless in everyday Rails development.
I do hope to incorporate more of my development workflow into these screencasts. Maybe do some TDD at the beginning. We'll see.
Hey Ryan. If we're in the topic of authentication - is there any chance You could make an episode about creating oAuth provider?
There's no good tutorial out there about this.
Great episode btw! :)
One more great article. But I prefer using authlogic or device to achieve those results as those gems have a lot of features explained here and much more. And they're covered with tests what is important!
I am new also to rails. Is there a way to generate a unique token with a key (like the user id), which would ensure its uniqueness, which would prevent you from having to check if it already exist in the user table.
Thanks a lot Ryan,
Your approach does not allow a user to remember me from multiple machines. So I guess it worth to mention that. Also it worth to mention that probably storing the tokens in a Rails.cache is more scalable and durability can be achieved if the cache is backed by a durable cache (like membase)
Good point (re: remember me from multiple machines).
has anyone encountered this error going through this tut!!
undefined method `urlsafe_base64' for SecureRandom:Module
app/models/user.rb:39:in
generate_token'
send_password_reset'app/models/user.rb:31:in
app/controllers/password_resets_controller.rb:7:in `create'
because I have and i've no idea how to solve this..
Perhaps your problem is related to Matt-Bishop's comment?
Or use Gabe Kopley's solution:
Thanks a million Jean! Hit the bulls eye!! Spot on!!
I've just run into 'undefined method `urlsaf_base64' for SecureRandom:Module' on ruby 1.9.2p290
it would help if 'safe' were a word i could spell
Thanks
Ryan make a wonderful new Screencast! I instantly implemented this within my project.
For a rake-task (to reset auth_token)Ryan recommandedin the video I personally wrote:
Where does this section of code should be placed.
Does this code adds auth_token to previously existed users ?? Curiousity!
It's placed in
lib/tasks/rebuild_token_auth.rake
then you can run it with
I've also had to check it out!
Hey Ryan!
I'm new to Rails and I really like Your screencasts.
However, I think I've found kind of security flaw in this one.
In password_resets_controller.rb you do:
It allows the user to change any attribute he wants using prepared form/request.
I realize this is just an example, and in production you probably wouldn't do it, but still, it's not good example IMHO.
Correct me if I'm wrong.
i have the same concern, since it is quite possible to brute force many ids in password_resets/id/edit and then set the users password AND email to your own pw & email.
If you could not assign an email via the password_resets_controller, then it would be much harder to figure out which email was assigned to the updated password.
You could use UrlStore https://github.com/grosser/url_store and just encode user id and expiration time inside the url, no new columns needed. Only drawback is that the token gets longer.
Bye bye Authlogic/Devise, hello Ryan's "authentication from scratch" + CanCan. Thank you.
@Iain
That's only true for simple, small applications.
And that's true for Devise customizations in more complex scenarios ;)
For some reason
cookies.delete[:auth_token]
does not work in Rails 3.1.I had to use
cookies.delete :auth_token
to get it to destroy the session.It should be
cookies.delete(:auth_token)
, notcookies.delete[:auth_token]
.Great screencast! I realy love your "*from scratch" screencasts but i encountered some problems:
I had to use
save!(validate: false)
in the send_password_reset method after i added some validation on my user model. Why does the validation for the presence of a password and password_confirmation fire on the reset password form? And is there any way to validate only for a valid email withou using javascript?9 months bump.....
I also have this problem
have you tried using
validates_presence_of :password, on: :create
Would you not want validation when a user updates his details as well?
Hello, i retrieve an error by submit "reset the Password":
Have anybody a Idea? Thanks!
I keep getting
in my template I use:
in my application.rb it is defines
happens when a user is trying to reset the password.
Did you ever figure this out? I'm getting the same error.
I get same error. I even tried running the query from the console and I get nil.
I try find_by_email or find_by_first_name and it works. Only when running find_by_auth_token it returns nil.
I'm getting this too, I'm stuck!! Have compared my code with every file in the source code I can think of... Is it really working for everyone else following this screencast??
I'm running Rails 3.1.0, Ruby 1.9.2p290, sqlite3-ruby 1.3.3, Rake 0.8.7...
I ended up fixing this by rolling back my migrations and then migrating again. Anyone know why this would be necessary??
you didnt need to roll back you probably were trying to use/login with a user-account that was already in your database. After doing the tutorial, create a new user so the auth_token column is populated and it will fix your error. @fritzsche created a rake tasks that will fix all your current users in your database incase you dont want to do a rake db:migrate:reset.
in short you cannot login with a old user after doing this.
I ran into the same issue, I posted a solution at http://stackoverflow.com/a/15865006/1814446
I think it's important to mention that when you set @current_user with cookie instead of session you lose the efficiency of rails CSRF protection.
It's happen because when rails protect_from_forgery method identify CSRF attack it's reset only the session and not the user's cookies.
To fix it you need to override handle_unverified_request()
at MODULE ActionController::RequestForgeryProtection::ClassMethods
and define it to delete auth_token cookie
Hey...Anyone else having problems with validations?
Ny solutions?
for anybody having the same problem with testing, when switching from session to cookies. You need to use request.cookies to assign the cookie.
and in your normal specs where you use test_sign_in
in specs where you dont use test_sign_in but rather post :create, :email => "user@example.com", :password => "somepassword"
its really confusing me
@ryan is there any reason why in the
PasswordResetsController
you perform the 2 hour check in the update action and not in the edit action? It seems counter-intuitive to have the user post a new password, and then inform them that the password reset token has expired. Is there any reason why you wouldn't do it like this?And thanks for showing us this, I've now ditched Devise and feel cleansed.
Having a check in the edit action makes it more convenient.
However you should NOT remove the check from the update action, as attackers can now try outdated activation codes forever with forged PUT requests.
though i forgot, rails takes care of the forms validity with the authenticity token, however its probably still safer to have a time check in the update action.
I love this solution but as a total rails noob, I don't know how to test for it, it would be great to have some explanation or, even better, an episode on it.
Regarding validations...
Well, if you're like me, you have password validation and also encrypt the password before saving the user model.
That's a big monkey wrench for Ryan's excellent solution above.
To get it all to work, I created a PasswordReset model (the only way I know of to avoid the before save calls on the user model). I used almost all of Ryan's code but had to make a few modifications.
Then, I had to modify the password_resets controller to make use of the new model. I also moved the 2.hours_ago check to the edit action because it improves the user experience (oh, and I also plan on running a weekly job to remove old password reset tokens)
All-in-all it works pretty well (in need of some refactoring, though because I think the controller is too fat...) Here's the code - I hope it helps!
''' ruby
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user
user.create_password_reset
UserMailer.delay.password_reset(user)
end
redirect_to root_url, :notice => "Email sent with password reset instructions."
end
def edit
password_reset = PasswordReset.find_by_password_reset_token(params[:id])
if password_reset.nil?
redirect_to root_path
return
else
@user = password_reset.user
if password_reset.created_at < 2.hours.ago
flash[:notice] = "Password reset has expired. Please try again"
redirect_to new_password_reset_path
end
end
end
def update
@user = PasswordReset.find_by_password_reset_token!(params[:id]).user
if @user.update_attributes(params[:user])
redirect_to root_path, :notice => "Password has been reset!"
else
render :edit
end
end
end
'''
I overcame the validation errors by adding
:validate => false
to the save statement in send_password_reset:I overcame a problem with the above, which occurred when I submitted the email to which the password_reset email should be sent. It would say:
ActiveRecord::RecordInvalid in PasswordResetsController#create
Validation failed: Password is too short (minimum is 6 characters), Password confirmation can't be blank
I have no idea why it would say that, but the above fixed it. What exactly does
save!(:validate => false)
do?it basically 'overlooks' the validation you have in your user model
brilliant, thank you
I am learning Rails by myself and your tutorials have been extremely helpful!
I am coming across an issue with the remember me. Regardless of if I click on the "remember me" or not, the site still remembers me after I close and reopen a new browser. Is anyone else having that same issue?
Thanks.
The :auth_token is "text plain" accessible in the cookie (since signing it would not help), capturing it would give access (a valid current_user) to any one who knows how to inject it later, no need to a password-based authorization process... wouldn't be wise to generate a new :auth_token for the current_user and save it before SessionsController#destroy?
(e.g.: you can inspect the cookie once and then later in any javascript console -> document.cookie("auth_token=7h3$u53r&H45H"); )
-> Kind of have no time to read all the comments, sorry if the subject have already been discussed.
disclaimer: the cookie injection code is only an example.
@dicky - It sounds like the cookie is always being set as permanent. So, I'd check the 'if' statement that sets the cookie to and make sure it's actually doing what you'd like it to do. I'm sure if you post the code (here, or for example, on RailsForum,) someone will help you out.
I was getting an error and the emails weren't being sent when I was submitting the form after filling in my email address. I had to make a change to this code below:
def password_reset(user)
@user = user
mail :to => user.email, :subject => "Password Reset"
end
I had to change
user.email
to
@user.email
I'm guessing this is a little bug, but why would you want the reset_token to be considered expired if it is less than 2 hours old? shouldn't it be if it is more than 2 hours old??
I read it that way myself at first. Try it out. Better yet, write a rspec test. :)
Thanks for this great screencast. I have just implemented this into an application with omniauth identity.. However it seems
elsif @identity.update_attributes(params[:identity])
does not seem to change the password as it would if I were using roll-your-own authentication.
Where am I going wrong. I am still quite new to rails so any suggestions would be a big help
Thanks!
Has anybody gotten this to work with 1.9.3? There is the missing "authenticate" method error only with 1.9.3, and not with 1.9.2. I verified this by using the same app on both rubies.
On Chrome 14.0 and Firefox I am using on Ubuntu, cookies are generated even if I am not checking remember me. I see _auth_session and auth_token in the cookies browser. Both are set to expire when browser is closed. But after I closed the browser and reopened it, I am automatically signed in. Only way to sign out is to click logout.
Does anyone know what could be going on? I am using the original code.
Did figure it out? I am having similar problems although I am working in Linux. Tested on multiple browsers and I don't think this has anything to do with them. I seem to have cookies set to permanent despite of the fact that I never checked the remember me box. Please help if you have any idea what this can be caused by. Thank you.
Yup. same problem for me regardless of how remember_me checkbox is checked. Permanently logged in even between browser launches unless explicitly signing out…
Another great screencast.
I've implemented this auth_token into an app that uses simple omniauth (#241) for authentication. Is this auth_token the same token I could use for a user to call my app's API or do I need to generate a different token for that purpose?
I don't know if anyone else ran into this problem but I had to put
otherwise it would blow up when redirected back to the homepage after deleting a user account.
Definitely should set
password_reset_token
tonil
after successful password reset to prevent reusing the link, especially for long expiration time.The fields for the
password_resets
edit form are not validating for me. Has anyone else had this problem?Nevermind, my validations were failing because I had filtered them to only occur
:on => :create
.Nice episode, but I would recommend to set Http-only setting for auth-cookies so if site somehow have xss hole attacker cannot steal cookies through javascript.
Is there any good way to expose this authentication scheme to http requests? (or JSON)... I'm trying to write exposed apis for an iOS application that needs to talk to a rails app that I used this autentication scheme in.
Very useful episode.
Very useful, thanks, Ryan!!!
Real life example of similar auth you can find at http://gistflow.com (open source).
Famous Egor Homyakov hacked us using bug described here:
http://gistflow.com/posts/174
The thing is that if you store auth_token in cookies csrf protection will not work.
Good luck everyone with safe auth :)
As usual, a really useful and clear episode, thank you Ryan.
Just a couple of minor points. In the ASCIIcast, there is unrendered '↵' (in the config/environments/development.rb section).
Also, for people who have never used the mailer before (like me), it might be worth pointing out there is further configuration to get the Mailer fully working, as outlined in your Action Mailer railscast.
I've fixed the issue in the ASCIIcast by removing the '↵' which didn't really seem needed anyway.
Thank you Ryan, very interesting episode!
I'm trying to get the mailer to work on heroku. I did
heroku addons:add sendgrid:starter
but whenever I try to send an email from heroku, I get this error:
Anyone else had this problem? Any ideas how to fix this?
Thanks in advance!
https://devcenter.heroku.com/articles/smtp
actually i cannot find a solution for this in the link i sent. have you solved it?
You are a life saver Ryan. This episodes are golden.
Thank you.
I kept getting this when I tried to update my password:
ArgumentError in PasswordResetsController#update
comparison of Date with ActiveSupport::TimeWithZone failed
Fixed it by doing this:
Hi, when I try to call the send_password_reset I get this error:
Does anyone can help me, please?
I solve the problem. Thank you
so how you're to do?? please tell me
Hi when I try to reset password I get this error:
ArgumentError in PasswordResetsController#create
wrong number of arguments (1 for 0)
app/models/user.rb:48:in
create_remember_token'app/models/user.rb:40:in
send_password_reset'
create'`app/controllers/password_resets_controller.rb:7:in
Have anybody an Idea why?
I'm missing something trivial here.
but I want to see the reset_token parameter here don't I?
Now I have
and now I have problem with find user
undefined method
find_by_create_remember_token!' for #Class:0x007fca97926210`nm,
it was because of the non-restful reset link in the mail template.
Because I'm using multi-tenancy, and locales this is what my password_reset method must look like:
hmm..I have same problem 'Validation failed: Password can't be blank, Password is too short (minimum is 6 characters)'
'app/models/user.rb:64:in
send_password_reset'
create'app/controllers/password_resets_controller.rb:9:in
For anyone who is working with different locales (like Remmington above), make sure your mailer template looks something like this:
<%= edit_password_reset_path(@user, :locale => I18n.locale, :password_reset_token => @user.password_reset_token) %>
Especially when you have routes like these:
It took me ages to figure that out...
Sorry, better use this:
<%= edit_password_reset_path(@user.password_reset_token, :locale => "#{I18n.locale}") %>
Hi everyone and thank you Ryan for this great screencast
I have an issue with the password reset edit form. The reset url is correctly generate and I can access the form, but my update action doesn't seem to work. Actually, I can send my form with empty fields for "password" and "password confirmation" and it will still trigger the "Password has been reset!" notice.
It looks as though my user validations aren't being taken into account here.
I tried adding both password and password confirmation validation to my User model:
which is weird because when creating a new user, I didn't need those validations (the has_secure_password feature seemed to implement these validations), but the edit reset password form seems to need them.
Anyway, my edit_password_reset form worked, but it broke my new_password_reset form because it required both non blank password and password confirmation.
What am I missing here?
HI Ryan,
Well done on this one. I followed all your steps and it worked like a charm.
NOTE: I did have to restart the server after modifying the development.rb file. Any others who run into any weird snags along the way, just restart your server before trying anything else.
Hi, when I click the reset password button its giving me a validation error saying Validation failed: Password can't be blank?
Any help? I'm quite new to this?
Hi All,
Has anyone been able to figure out the "Validation failed: Password can't be blank, Password is too short (minimum is 6 characters" error when hitting Reset Password Submission button.
Please help???
Thanks in advance.
take a look in my commet
For all the guys with this problem:
"Validation failed: Password can't be blank, Password is too short minimum is 6
characters"
the solution is just change the line
and use instead
This validation subject is getting complex...
Let's say I validate like this:
and I use the tip above:
This works perfectly. But If I don't want the user to confirm the password every time he saves the profile I would do like this.
This works too. Even validates on the reset password form and ask for confirmation if the password changes on the profile. But, it has a problem. if I submit the reset password form without any value for the password or password_confirmation it won't validate the presence of :password or :password_confirmation. The password won't be updated but it'll be nice to show the validation errors for presence in this scenario.
I don't know if any one has this issue, but I would appreciate some light here.
Thanks
Ryan,
Great episode. When a person creates a new account, there is no remember me functionality and his session is not automatically stored after creating a new account.
In episode #270, you showed us how to accomplish this by adding the following code (and adding :
session[:user_id] = @user.id)
How would we accomplish this being that we are not using the session and we are now using the cookie?
Louis
I figured it out :). I knew it was something easy.
needed to replace:
session[:user_id] = @user.id
with:
cookies[:auth_token] = @user.auth_token
Hi Ryan,
Good screencast and help all newbies to learn rails easily.
I am using rails 4 and encountered one problem.
In password_resets_controller.rb you do:
elsif @user.update_attributes(params[:user])
IN console it showing
ActiveModel::ForbiddenAttributesError in PasswordResetsController#update
I don't know how to solve this issue.Please help me to solve this issue.
Change:
elsif @user.update_attributes(params[:user])
to:
elsif @user.update_attributes(params.permit![:user])
Thx @shamgar that's work for me !
For me, the following worked:
I get it from:
http://stackoverflow.com/questions/17568062/activemodelforbiddenattributeserror-in-passwordresetscontrollerupdate
Thanks for the railscast, can't tell you how many times this it's helped me on projects. I was trying this out but I seem to have a problem when the user clicks on the password reset link from their email I get an error saying that it cant find the user with the password reset token
`ActiveRecord::RecordNotFound in PasswordResetsController#edit
Couldn't find User with password_reset_token = eydSfVtGn2gBQyNJP0o9jA`
Excellent ScreenCast .
Thanks Ryan for all the hard work you put out there.
Hope to hear from you soon.
I like the screencast... It works, but how do you get it to work in production? like specifically? I've tried to figure out what to put in my production.rb file but can't find a single thing telling me what to do.
JohnsCurry:
in my case- (i may not be completely pristine with this railscast)
and
Thank you, I tried this I have no idea why it's not working still. I'm going to put it aside and try it later, its like the app isn't even trying to send an email, yet it works in development.
Thanks for this one more time amazing railscast !
I couldn't figure out for the life of me why current_user was returning nil with the new cookies authentication. I was using an old user for which there had been no auth token generated... if anyone else encounters the same there ya go. Make a new user or clear the db.
hey im having some problems i dont know if you can help me out?
There is always a security concern when it comes to authenticating users. We'd better to stick with session over cookie when we store authenticated user details. Cookie is only suited for storing the remember me flag, but not for the authorization hash.