I'm trying to change a users password and it successfully changes but it doesn't let me do anything afterwards because the user becomes unauthorized... I'm probably missing a piece that reauthenticates them.
This is my code to update their password
def password
if current_user.valid_password?(params[:current_password])
current_user.password = params[:new_password]
if current_user.save
#sign them in
#tried doing this to sign them in again but didn't work
sign_in(:user, current_user)
response.headers['X-CSRF-Token'] = form_authenticity_token
response.headers['X-Pyne-Auth'] = current_user.authentication_token
render :json => {:success => true} and return
else
render :json => {:success => false, error: "Unexpected error while trying to save user. Please try again."} and return
end
else
render :json => {:success => false, error: "Your current password is incorrect. Please try again"} and return
end
end
I can update the password but have trouble accessing the app again because the user becomes unauthorized.
Thank you
Try bypass_sign_in(#user) as suggested in the Devise wiki.
Related
I am using rails HTTP digest authentication on some of my website's controller. It is working fine for my purpose but it timeout very quick.
How can I adjust the timeout parameter for HTTP digest authentication?
How can I implement logout for HTTP basic authentication?
Thanks,
If a user leaves the site, or closes their browser, etc, and you would like them to stay logged in:
In your SessionsController:
def create
member = Member.find_by_user_name(params[:user_name])
if member && member.authenticate(params[:password])
session[:member_id] = member.id
if params["remember_me"] == "1"
cookies[:digest] = {:value => member.password_digest, :expires => Time.now + 720000}
else
cookies[:digest] = nil
end
redirect_to (url_to_go_to_after_login), :notice => "Logged in!"
else
redirect_to (login_url), :alert => "Invalid email or password"
end
end
How to log out a user:
def destroy
session[:member_id] = nil
cookies[:digest] = nil
redirect_to url_to_go_to_after_logout, :notice => "Logged out!"
end
How to log in a user from the rememberme cookie:
def new
if member = Member.find_by_password_digest(cookies[:digest])
session[:member_id] = member.id
redirect_to (url_to_go_to_after_login), :notice => "Hello#{member.first_name}"
end
end
To set the expire time for later (should work in rails > 2.3 https://github.com/rails/rails/blob/2-3-stable/actionpack/lib/action_controller/session/abstract_store.rb#L175 ):
Your::Application.config.session_store :active_record_store, {
key: "your_session_id",
domain: ".your-domain.com",
expire_after: 48.hours,
}
I am using devise and when a user changes a password the site logs them out. I read online that adding the sign_in will do the trick but not working and the user gets logged out when a password change. Here is my code
if #user.errors[:base].empty? and #user.update_attributes(params[:user])
sign_in(current_user, :bypass => true)
flash[:success] = "User account has been successfully updated"
redirect_to edit_user_path(params[:site_id], #user)
else
render :action => :edit, :status => :unprocessable_entity
end
I was assuming that this would work but regardless of what i do i still get logged out....anything missing or maybe one devise setting is off...any help would be appreciated
I usually folow these instructions and it works. Maybe you should do
sign_in(#user, :bypass => true)
instead of
sign_in(current_user, :bypass => true)
In my Rails app I'm trying to produce a separate flash.now[:alert] for invalid :email and :password, respectively. So if a user enters the correct email but wrong password, the :alert warns the user of an invalid password and vice versa. Here's what I have in my SessionsController:
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
redirect_to user.profile, :notice => "Logged in successfully"
elsif user.email != params[:email]
session[:email] = #user.email
flash.now[:alert] = "Invalid email. Try again!"
render :action => 'new'
else
session[:password] = #user.password
flash.now[:alert] = "Invalid password. Try again!"
render :action => 'new'
end
end
Rendering this gives me an undefined method for email. Can anyone help me figure out what I'm doing wrong?
DISCLAIMER: Obviously this is a really bad idea as an attacker could keep on trying emails until he found one that did match and then he could start trying passwords for this email he knows exists at your database, but you're asking, so it's up to you deciding to do this or not.
Your authenticate method obviously only returns the user if the email and password did match, change your authenticate method to return a boolean and a user if there is any available. It would look somewhat like this:
def authenticate(email, password)
u = first(:conditions => {:email => email, :state => 'active'})
u && u.authenticated?(password) ? [true, u] : [false, u]
end
Then, at your controller:
def create
result , user = User.authenticate(params[:email], params[:password])
if result
session[:user_id] = user.id
redirect_to user.profile, :notice => "Logged in successfully"
elsif user
session[:email] = #user.email
flash.now[:alert] = "Invalid email. Try again!"
render :action => 'new'
else
session[:password] = #user.password
flash.now[:alert] = "Invalid password. Try again!"
render :action => 'new'
end
end
And this should work.
When i run in my page this code :
<% user = User.find(session[:userid]) %>
i get the error :
line #1 raised:
Couldn't find User without an ID
although i have in my authentification in my sessions_controller this :
def create
if user = User.authenticate(params[:username],params[:password])
session[:user_id]= user.id
session[:language_id]= user.language_id
User.find(user.id).update_attributes(:last_login => Time.now)
redirect_to root_path , :notice => (I18n.t :"session.login_success")
else
flash.now[:alert] = (I18n.t :"session.error")
render :action => 'new'
end
end
and the session should contain the userid
In your log-in you set session[:user_id], and you try to find session[:userid] (note the spurious underscore). That's why.
Your controller is looking for params session[:user_id], but in your views it is session[:userid] so it will complain that session[:user_id] is nil.
guys. I have a problem when doing the authlogic login validation. I have the magical "active" field in the user model, say if active is false, when login with correct password, it will pop up the message like "You are suspended, please contact your administration" (I defined this message in I18n file); when login with wrong password, it will pop up the the not_active message plus password_invalid message like "password invalid". I think that is because authlogic did the validation both for "active" field and password and it seems password validation comes first.
My question is, how can bypass the password validation if 'active' is false. Or, can I only show not_active message? my code like:
if #user_session.save
redirect_to home_path
else
render :json => {:success => false, :error => #user_session.errors.full_messages.join("\n")}
end
OK, so I don't like this as a user-experience, but if you really want to, do something like:
before_filter :restrict_inactive_users, :on=>:create
def restrict_inactive_users
#user = User.find_by_login(params[:user_session][:login]) rescue nil
return unless #user
unless #user.active?
flash[:error] = "You are suspended, please contact your administration"
render :action=>:new
return false
end
end
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
redirect_to home_path
else
render :json => {:success => false, :error => #user_session.errors.full_messages.join("\n")}
end
end
Today I thought out a solution which doesn't bypass the password validation but just delete the password error message from user_session. Code like:
if #user_session.save
redirect_to home_path
else
#user_session.errors.delete(:password) unless #user_session.attempted_record.active
render :json => {:success => false, :error => #user_session.errors.full_messages.join("\n")}
end
Start with fetching the user by the identifier of your choice, like the email or user name.
If the user is not active you can remove the other errors before redirecting back to the login page.
#user_session.errors.clear
Then the errors will not show when the page is rerendered. But you must provide a custom error message, for example via the flash.now[:error] or your json response.