views:

206

answers:

1

An application I inherited has the following action for updating a user's profile:

class UsersController < ApplicationController
  # ...
  def update
    @user = current_user
    if @user.update_attributes(params[:user])
      flash[:notice] = "Successfully updated profile."
      redirect_to root_url
    else
      flash[:error] = "Hrm, something went wrong."
      render :action => 'edit'
    end
  end
end

The form that PUTs (really POSTs with a _method=PUT) to that action has a password and password_confirmation field, but no old_password field. I've noticed through testing that I don't even have to fill in the password_confirmation field.

First question: is there a more established way of doing a password change when using Authlogic?

Second question: is there any literature on best practices (especially from a usability standpoint) on password-changes? Should it be a separate form, not mixed in with other user fields?

Third question: Most sites have an old_password field, but Authlogic doesn't seem to support that natively. What's the Authlogic-ey way of confirming it's actually the user him/herself changing the password rather than somebody who has hacked their session?

+2  A: 

First answer: Authlogic gives you the framework but the implementation is up to you. Most sites simply provide a "change password" page which shows only the 'password' and 'password_confirmation' fields or an "edit profile" page which allows you to UPDATE the fields you want altered in the user's record. Depending on how many fields are in your user's record, you may opt for a separate change password page. You want the forms to be short.

As for password_confirmation not being required:

  • For testing, it depends on how you mock it or what you're testing... is it the controller/forms or the model that you're testing?
  • Is require_password_confirmation true? (which is the default)

Second answer: You will find many usability standards out there but I simply go with KISS. From a usability stand-point, most people are comfortable with what's working and what's established - so checkout Google, Facebook, and 37signals. Very simple process. As mentioned above, short forms are an important usability goal.

If you're talking security requirements, your best bet is PCI Compliance [PDF] which states several rules for transmitting and storing financial records though they have no mention of user credentials. If you applied the same rules to accounts as you did credit cards, you'll have a really secure setup. Since PCI Compliance has fallen short to deliver, banks are another great resource to look at since poor session handling could lead to a lot of missing money. Several of my bank accounts now confirm my logins and password changes with images and security questions above my standard password. I found several good articles covering that as well.

Which leads to the third question...

Third answer: In AuthLogic, simply check the user's "old password" field before proceeding with the update in your users_controller with: @user.valid_password?("old pass")

Like so:

Add attr_accessor :old_password to your users model

And change your users controller to:

def update
    @user = current_user
    if @user.valid_password?(params[:user][:old_password])
      if @user.update_attributes(params[:user].reject{|key, value| key == "old_password"})
        flash[:notice] = 'Successfully updated profile.'
        redirect_back_or_default root_url
      else
        render :action => 'edit'
      end
    else
      flash[:warning] = 'Your old password is WRONG! What is your malfunction!?!'
      render :action => 'edit'
    end
  end

(you may want to change the warning...)

databyte