Project

General

Profile

Patch #17796 » 0001-Expire-all-other-sessions-on-password-change.patch

Jan from Planio www.plan.io, 2014-09-04 19:02

View differences:

app/controllers/application_controller.rb
49 49
    end
50 50
  end
51 51

  
52
  before_filter :session_expiration, :user_setup, :check_if_login_required, :check_password_change, :set_localization
52
  before_filter :session_expiration, :user_setup, :force_logout_if_password_changed, :check_if_login_required, :check_password_change, :set_localization
53 53

  
54 54
  rescue_from ::Unauthorized, :with => :deny_access
55 55
  rescue_from ::ActionView::MissingTemplate, :with => :missing_template
......
144 144
    user
145 145
  end
146 146

  
147
  def force_logout_if_password_changed
148
    password_changed_at = User.current.password_changed_at || Time.at(0)
149
    # Make sure we force logout only for web browser sessions, not API calls
150
    # if the password was changed after the session creation.
151
    if session[:user_id] && password_changed_at.utc.to_i > session[:ctime].to_i
152
      reset_session
153
      set_localization
154
      flash[:error] = l(:error_session_expired)
155
      redirect_to signin_url
156
    end
157
  end
158

  
147 159
  def autologin_cookie_name
148 160
    Redmine::Configuration['autologin_cookie_name'].presence || 'autologin'
149 161
  end
app/controllers/my_controller.rb
100 100
        @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
101 101
        @user.must_change_passwd = false
102 102
        if @user.save
103
          # Reset the session creation time to not log out this session on next
104
          # request due to ApplicationController#force_logout_if_password_changed
105
          session[:ctime] = Time.now.utc.to_i
103 106
          flash[:notice] = l(:notice_account_password_updated)
104 107
          redirect_to my_account_path
105 108
        end
app/models/user.rb
279 279
  def salt_password(clear_password)
280 280
    self.salt = User.generate_salt
281 281
    self.hashed_password = User.hash_password("#{salt}#{User.hash_password clear_password}")
282
    self.password_changed_at = Time.now
282 283
  end
283 284

  
284 285
  # Does the backend storage allow this user to change their password?
/dev/null → db/migrate/20140903143914_add_password_changed_at_to_user.rb
1
class AddPasswordChangedAtToUser < ActiveRecord::Migration
2
  def change
3
    add_column :users, :password_changed_at, :datetime
4
  end
5
end
test/functional/my_controller_test.rb
185 185
    assert User.try_to_login('jsmith', 'secret123')
186 186
  end
187 187

  
188
  def test_change_password_kills_other_sessions
189
    @request.session[:cdate] = (Time.now - 30.minutes).utc.to_i
190

  
191
    jsmith = User.find(2)
192
    jsmith.password_changed_at = Time.now
193
    jsmith.save!
194

  
195
    get 'account'
196
    assert_response 302
197
    assert flash[:error].match(/Your session has expired/)
198
  end
199

  
200

  
188 201
  def test_change_password_should_redirect_if_user_cannot_change_its_password
189 202
    User.find(2).update_attribute(:auth_source_id, 1)
190 203

  
191
- 
    (1-1/1)