Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise with Ruby on Rails - Force user to change password on first login

I have a RoR application (Rails 4.2, Ruby 2.2.0) running Devise. I have set it up so that admin users (identified the "is_admin" boolean I added to the user model) are able to create new user account, provide them with a generated password and confirmation email. This is all working properly. I have also added the datetime column pass_changed which should be updated when a user changes their password, and then checked against created_at to make sure that the password has changed since the account was created. If the two dates are equal then the user is redirected to the password change form.

I wrote a procedure for checking that the user has changed their password and placed it in my application_controller.rb:

def check_changed_pass
@user = current_user
    if @user.pass_changed == @user.created_at #make sure user has changed their password before accessing internal pages
    redirect_to edit_user_registration_path, alert: "You must change your password before logging in for the first time"
    end
end

Then in my internal_controller.rb (used for all internal that require the user to be logged in:

before_action :check_changed_pass

So far so good, but the problem comes with attempting to update pass_changed at the right time. I have tried various configurations, but I can't find where to put this code so that it triggers when a password is updated, but not every time the user model is updated, which includes every login and logout, when I only want it to trigger if the password gets updated.

If I place "before_save :update_pass_change, only: [:edit, :update]" in my controller it doesn't trigger on a password update, and if I place it in the User model, I have to put the procedure in the model as well and then it won't pick up current_user as its not available in the model. The ideal thing would be if Devise had a hook for after_password_edit similar to the after_database_authentication hook. I had to override Devise's registrations_controller.rb to remove the line

prepend_before_filter :require_no_authentication, only: [ :cancel]

So that admin users would be able to add new users. I tried placing update_pass_change there, but it doesn't seem to trigger before_save on a password edit.

In application_controller.rb

def update_pass_change # records that the user has changed their password
    unless current_user.pass_changed != current_user.created_at
    current_user.pass_changed = Time.now
    end
end

Similar unanswered question: Ruby on Rails: Devise - password change on first login

like image 562
Henry D Avatar asked Apr 02 '15 14:04

Henry D


People also ask

Is it possible to force the user to change the password at their at first login?

Using passwd Command To force a user to change his/her password, first of all the password must have expired and to cause a user's password to expire, you can use the passwd command, which is used to change a user's password by specifying the -e or --expire switch along with username as shown.

How do you make a new user to reset his password upon his first login in Linux?

Changing user passwords on Linux First sign on or “su” or “sudo” to the “root” account on Linux, run: sudo -i. Then type, passwd tom to change a password for tom user. The system will prompt you to enter a password twice.

How do I force a user to change password on first login in Solaris?

Using passwd command Another way to force user for password change is to use the command passwd with -e option. The -e option expires the current user password forcing user to set a new one on next login. From the man page of passwd command : -e This is a quick way to expire a password for an account.


2 Answers

You could use a callback on your model and check, before save, if the changes includes your password attribute. Something like this:

class User < ActiveRecord::Base
  before_save :check_password_changed

  private
  def check_password_changed
    self.pass_changed = Time.now if changed.include? 'encrypted_password'
  end
end
like image 156
Doguita Avatar answered Sep 19 '22 10:09

Doguita


You can also try this

  1. change datatype of pass_changed to boolean with default value false

  2. Then in your application_controller.rb

    before_action :check_pass_changed
    
    private
    
    def check_pass_changed
     unless current_user.pass_changed
       redirect_to custome_password_edit_path, alert: "You must change your password before logging in for the first time"
     end
    end
    
  3. Then Create custom action in ur users_controller to display the password change form and to update. eg. To display form : custome_password_edit To update : update_user_password also dont forget to write above in routes.rb

  4. after successful change update the value of pass_changed to true

like image 25
Amit Sharma Avatar answered Sep 19 '22 10:09

Amit Sharma