[devise] Implementing first login password change

2,815 views
Skip to first unread message

Nilesh C

unread,
May 17, 2010, 9:30:31 AM5/17/10
to Devise
I have been trying to force a password change on first login. I can
see the sign_in_count attribute. But I am facing a difficulty in
placing the logic.

If I place a method to check first login in application controller, I
get a double redirection error. I tried using the warden callbacks
(after_authentication, after_set_user) in the application controller.
but to no avail.

Just want to know if there is a clean way to do this using Devise.

José Valim

unread,
May 17, 2010, 9:46:01 AM5/17/10
to plataforma...@googlegroups.com
I implemented something like that already. What I did was to use the recoverable settings to achieve what I want. Basically, all you need to do is:

* include recoverable in your model (do not include confirmable);

* create your user with a random password, a reset password token and send an e-mail after it's created with the reset password url and the reset password token;

Then the user should access the reset your password url in the e-mail and set his new password before first logging in.

If you want however, the user to be able to access with the random password, you will need to create another column in your object to work as a flag. I would implement it as a before filter, as you did. Don't know why it's raising a double render error, please do investigate.
--
José Valim

Director of Engineering - Plataforma Tecnologia
Know more about us: http://plataformatec.com.br/en/

Andrew Hodgkinson

unread,
May 17, 2010, 9:50:32 AM5/17/10
to plataforma...@googlegroups.com
On 17/05/2010 14:30, Nilesh C wrote:

> I have been trying to force a password change on first login. I can
> see the sign_in_count attribute. But I am facing a difficulty in
> placing the logic.

I see Jos� beat me to it, but here's an alternative idea. As a simple
example, in application_controller.rb do something like this:

def stored_location_for( resource )
if ( resource.is_a?( User ) && resource.sign_in_count <= 1 )
redirect_to( change_password_path() ) # Or similar...
end

super( resource )
end

(Untested).

The "stored_location_for" method is a it like "after_sign_in_path_for" as
documented in Devise, except the stored location is checked for each and
every login. The after sign-in path is only consulted if there is no
stored location - so it only works for clean user logins, but not if the
user's session had timed out and they had been redirected to the login
form prior to being redirected back where they came from. This is fragile
though, because if a user logs in again due to timeout, their sign in
count will increment, so Jos�'s approach may have more mileage.

Once the user has been redirected, they can ignore the form you present
and visit some other part of the site. If you want to *force* a change,
preventing the user from doing anything else on the site, then you
probably need to have a field in your User model which is set when the
user needs to be forced into changing a password and only cleared once
they've done so. Jos� touches on this in his reply too. A before_filter
in Application Controller can consult this field for the currently logged
in user (if logged in) and redirect to the passwords controller - unless
already on the passwords controller, of course, else you'll get infinite
redirection again. Check variable "controller_name" in your
application_controller.rb's filter code to avoid this.

Personally I dislike sites which do the password changing dance. It's
unnecessarily complex. Just let me sign up with a password of my choice
in the first place and don't bother e-mailing passwords and reset tokens
around, which is an insecure thing to do. Why add all that code?

--
TTFN, Andrew Hodgkinson
Find some electronic music at: Photos, wallpaper, software and more:
http://pond.org.uk/music.html http://pond.org.uk/
Reply all
Reply to author
Forward
0 new messages