Store the salt in session and expire the session if the user changes his password
This commit is contained in:
parent
6613653df0
commit
617e142e34
|
@ -11,6 +11,7 @@
|
||||||
* Ensure the friendly token does not include "_" or "-" since some e-mails may not autolink it properly (by github.com/rymai)
|
* Ensure the friendly token does not include "_" or "-" since some e-mails may not autolink it properly (by github.com/rymai)
|
||||||
* Extracted encryptors into :encryptable for better bcrypt support
|
* Extracted encryptors into :encryptable for better bcrypt support
|
||||||
* :rememberable is now able to use salt as token if no remember_token is provided
|
* :rememberable is now able to use salt as token if no remember_token is provided
|
||||||
|
* Store the salt in session and expire the session if the user changes his password
|
||||||
|
|
||||||
* bugfix
|
* bugfix
|
||||||
* after_sign_in_path_for always receives a resource
|
* after_sign_in_path_for always receives a resource
|
||||||
|
|
|
@ -31,6 +31,7 @@ class Devise::RegistrationsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
if resource.update_with_password(params[resource_name])
|
if resource.update_with_password(params[resource_name])
|
||||||
set_flash_message :notice, :updated
|
set_flash_message :notice, :updated
|
||||||
|
sign_in resource_name, resource, :bypass => true
|
||||||
redirect_to after_update_path_for(resource)
|
redirect_to after_update_path_for(resource)
|
||||||
else
|
else
|
||||||
clean_up_passwords(resource)
|
clean_up_passwords(resource)
|
||||||
|
|
|
@ -87,18 +87,29 @@ module Devise
|
||||||
# Sign in an user that already was authenticated. This helper is useful for logging
|
# Sign in an user that already was authenticated. This helper is useful for logging
|
||||||
# users in after sign up.
|
# users in after sign up.
|
||||||
#
|
#
|
||||||
|
# All options given to sign_in is passed forward to the set_user method in warden.
|
||||||
|
# The only exception is the :bypass option, which bypass warden callbacks and stores
|
||||||
|
# the user straight in session. This option is useful in cases the user is already
|
||||||
|
# signed in, but we want to refresh the credentials in session.
|
||||||
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
#
|
#
|
||||||
# sign_in :user, @user # sign_in(scope, resource)
|
# sign_in :user, @user # sign_in(scope, resource)
|
||||||
# sign_in @user # sign_in(resource)
|
# sign_in @user # sign_in(resource)
|
||||||
# sign_in @user, :event => :authentication # sign_in(resource, options)
|
# sign_in @user, :event => :authentication # sign_in(resource, options)
|
||||||
#
|
# sign_in @user, :bypass => true # sign_in(resource, options)
|
||||||
|
#
|
||||||
def sign_in(resource_or_scope, *args)
|
def sign_in(resource_or_scope, *args)
|
||||||
options = args.extract_options!
|
options = args.extract_options!
|
||||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||||
resource = args.last || resource_or_scope
|
resource = args.last || resource_or_scope
|
||||||
expire_session_data_after_sign_in!
|
|
||||||
warden.set_user(resource, options.merge!(:scope => scope))
|
if options[:bypass]
|
||||||
|
warden.session_serializer.store(resource, scope)
|
||||||
|
else
|
||||||
|
expire_session_data_after_sign_in!
|
||||||
|
warden.set_user(resource, options.merge!(:scope => scope))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sign out a given user or scope. This helper is useful for signing out an user
|
# Sign out a given user or scope. This helper is useful for signing out an user
|
||||||
|
|
|
@ -73,6 +73,9 @@ module Devise
|
||||||
:inactive
|
:inactive
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def authenticatable_salt
|
||||||
|
end
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
Devise::Models.config(self, :authentication_keys, :request_keys, :http_authenticatable, :params_authenticatable)
|
Devise::Models.config(self, :authentication_keys, :request_keys, :http_authenticatable, :params_authenticatable)
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,28 @@ end
|
||||||
|
|
||||||
class Warden::SessionSerializer
|
class Warden::SessionSerializer
|
||||||
def serialize(record)
|
def serialize(record)
|
||||||
[record.class.name, record.id]
|
[record.class.name, record.id, record.authenticatable_salt]
|
||||||
end
|
end
|
||||||
|
|
||||||
def deserialize(keys)
|
def deserialize(keys)
|
||||||
klass, id = keys
|
if keys.size == 2
|
||||||
klass.constantize.find(:first, :conditions => { :id => id })
|
raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
|
||||||
rescue NameError => e
|
"you can fix it by changing one character in your cookie secret, forcing all previous " <<
|
||||||
if e.message =~ /uninitialized constant/
|
"cookies to expire, or cleaning up your database sessions if you are using a db store."
|
||||||
Rails.logger.debug "Trying to deserialize invalid class #{klass}"
|
end
|
||||||
nil
|
|
||||||
else
|
klass, id, salt = keys
|
||||||
raise
|
|
||||||
|
begin
|
||||||
|
record = klass.constantize.find(:first, :conditions => { :id => id })
|
||||||
|
record if record && record.authenticatable_salt == salt
|
||||||
|
rescue NameError => e
|
||||||
|
if e.message =~ /uninitialized constant/
|
||||||
|
Rails.logger.debug "Trying to deserialize invalid class #{klass}"
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -100,6 +100,13 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||||
@controller.sign_in(user)
|
@controller.sign_in(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'sign in accepts bypass as option' do
|
||||||
|
user = User.new
|
||||||
|
@mock_warden.expects(:session_serializer).returns(serializer = mock())
|
||||||
|
serializer.expects(:store).with(user, :user)
|
||||||
|
@controller.sign_in(user, :bypass => true)
|
||||||
|
end
|
||||||
|
|
||||||
test 'sign out proxy to logout on warden' do
|
test 'sign out proxy to logout on warden' do
|
||||||
@mock_warden.expects(:user).with(:user).returns(true)
|
@mock_warden.expects(:user).with(:user).returns(true)
|
||||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||||
|
|
|
@ -98,6 +98,20 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||||
assert_equal "user.new@email.com", User.first.email
|
assert_equal "user.new@email.com", User.first.email
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'a signed in user should still be able to use the website after changing his password' do
|
||||||
|
sign_in_as_user
|
||||||
|
get edit_user_registration_path
|
||||||
|
|
||||||
|
fill_in 'password', :with => '12345678'
|
||||||
|
fill_in 'password confirmation', :with => '12345678'
|
||||||
|
fill_in 'current password', :with => '123456'
|
||||||
|
click_button 'Update'
|
||||||
|
|
||||||
|
assert_contain 'You updated your account successfully.'
|
||||||
|
get users_path
|
||||||
|
assert warden.authenticated?(:user)
|
||||||
|
end
|
||||||
|
|
||||||
test 'a signed in user should not change his current user with invalid password' do
|
test 'a signed in user should not change his current user with invalid password' do
|
||||||
sign_in_as_user
|
sign_in_as_user
|
||||||
get edit_user_registration_path
|
get edit_user_registration_path
|
||||||
|
|
Loading…
Reference in New Issue