views:

51

answers:

4

Hello,

I am using the following for my customers to unsubscribe from my mailing list;

  def index
    @user = User.find_by_salt(params[:subscribe_code]) 
    if @user.nil? 
      flash[:notice] = "the link is not valid...."
      render :action => 'index'
    else    
      Notification.delete_all(:user_id => @user.id)
      flash[:notice] = "you have been unsubscribed....."
      redirect_to :controller => 'home'
    end 
  end 

my link looks like; http://site.com/unsubscribe/32hj5h2j33j3h333

so the above compares the random string to a field in my user table and accordingly deletes data from the notification table.

My question; is this approach secure? is there a better/more efficient way for doing this?

All suggestions are welcome.

A: 

I think this is safer:

@user = User.find :all, :conditions => { salt => params[:subscribe_code] }

That way you are sure that Rails knows params[:subscribe_code] is to be escaped. There are probably lots of ways to write it that would work though.

Mike Williamson
The `User.find_by_salt` call escapes the string. So there is no difference.
KandadaBoggu
I had a vague feeling that might be the case. Good to know for sure. Thanks!
Mike Williamson
+3  A: 

I don't see anything wrong in your solution if the action doesn't require authentication.

If the action requires authentication then I would make sure that the salt belongs to the current user

@user = User.find_by_id_and_salt(current_user.id, params[:subscribe_code])
KandadaBoggu
Thank you, there is no authentication. I just wanted to be sure it is ok. Thank you all.
Adnan
A: 

your link should be

http://site.com/unsubscribe/?subscribe_code=32hj5h2j33j3h333

otherwise "32hj5h2j33j3h333" will get as a params[:id]

else is fine. Assuming subscribe_code will be unique.

Salil
Not true, he may have `map.unsubscribe 'unsubscribe/:subscribe_code', :controller => "where", :action => "ever"`.
Ryan Bigg
Yea Ryan that is what I have.
Adnan
+1  A: 

Is it all that important that the user be informed if their unsubscribe link was wrong? What are the chances of that anyway? Wasn't it generated programmatically and that program is tested? If the answer is "yes" (hint: it should be) then my suggestion would be to always tell the user that they've unsubscribed, regardless of what happened.

def index
  begin
    @user = User.find_by_salt!(params[:subscribe_code]) 
  rescue ActiveRecord::RecordNotFound
  ensure
    @user.notifications.delete_all if @user
    flash[:notice] = "You have been unsubscribed."
    redirect_to :action => "index"
  end
end
Ryan Bigg