Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def increment_session_bad_password_count
end

def process_locked_out_session
warden.logout(:user)
sign_out(:user)
warden.lock!

flash[:error] = t(
Expand Down Expand Up @@ -100,7 +100,7 @@ def valid_captcha_result?

def process_failed_captcha
flash[:error] = t('errors.messages.invalid_recaptcha_token')
warden.logout(:user)
sign_out(:user)
warden.lock!
redirect_to root_url
end
Expand Down Expand Up @@ -176,6 +176,7 @@ def track_authentication_attempt(email)
bad_password_count: session[:bad_password_count].to_i,
sp_request_url_present: sp_session[:request_url].present?,
remember_device: remember_device_cookie.present?,
new_device: success ? new_device? : nil,
)
end

Expand Down
4 changes: 4 additions & 0 deletions app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ def edit_password_visit
# @param [String] bad_password_count represents number of prior login failures
# @param [Boolean] sp_request_url_present if was an SP request URL in the session
# @param [Boolean] remember_device if the remember device cookie was present
# @param [Boolean, nil] new_device Whether the user is authenticating from a new device. Nil if
# there is the attempt was unsuccessful, since it cannot be known whether it's a new device.
# Tracks authentication attempts at the email/password screen
def email_and_password_auth(
success:,
Expand All @@ -413,6 +415,7 @@ def email_and_password_auth(
bad_password_count:,
sp_request_url_present:,
remember_device:,
new_device:,
**extra
)
track_event(
Expand All @@ -424,6 +427,7 @@ def email_and_password_auth(
bad_password_count:,
sp_request_url_present:,
remember_device:,
new_device:,
**extra,
)
end
Expand Down
144 changes: 80 additions & 64 deletions spec/controllers/users/sessions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
bad_password_count: 0,
sp_request_url_present: false,
remember_device: false,
new_device: true,
)
end

Expand Down Expand Up @@ -113,6 +114,24 @@

response
end

it 'tracks as not being from a new device' do
stub_analytics

response

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: true,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 0,
sp_request_url_present: false,
remember_device: false,
new_device: false,
)
end
end
end

Expand Down Expand Up @@ -150,41 +169,41 @@
user = create(:user, :fully_registered)

stub_analytics
analytics_hash = {
expect(SCrypt::Engine).to receive(:hash_secret).once.and_call_original

post :create, params: { user: { email: user.email.upcase, password: 'invalid_password' } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: false,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 1,
sp_request_url_present: false,
remember_device: false,
}
expect(SCrypt::Engine).to receive(:hash_secret).once.and_call_original

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: user.email.upcase, password: 'invalid_password' } }
new_device: nil,
)
expect(subject.session[:sign_in_flow]).to eq(:sign_in)
end

it 'tracks the authentication attempt for nonexistent user' do
stub_analytics
analytics_hash = {
expect(SCrypt::Engine).to receive(:hash_secret).once.and_call_original

post :create, params: { user: { email: 'foo@example.com', password: 'password' } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: false,
user_id: 'anonymous-uuid',
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 1,
sp_request_url_present: false,
remember_device: false,
}
expect(SCrypt::Engine).to receive(:hash_secret).once.and_call_original

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: 'foo@example.com', password: 'password' } }
new_device: nil,
)
end

it 'tracks unsuccessful authentication for locked out user' do
Expand All @@ -195,20 +214,20 @@
)

stub_analytics
analytics_hash = {

post :create, params: { user: { email: user.email.upcase, password: user.password } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: false,
user_id: user.uuid,
user_locked_out: true,
valid_captcha_result: true,
bad_password_count: 0,
sp_request_url_present: false,
remember_device: false,
}

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: user.email.upcase, password: user.password } }
new_device: nil,
)
end

it 'tracks unsuccessful authentication for failed reCAPTCHA' do
Expand All @@ -229,6 +248,7 @@
valid_captcha_result: false,
bad_password_count: 0,
remember_device: false,
new_device: nil,
sp_request_url_present: false,
)
end
Expand All @@ -241,39 +261,38 @@

stub_analytics

analytics_hash = {
post :create, params: { user: { email: user.email.upcase, password: 'invalid' } }
post :create, params: { user: { email: user.email.upcase, password: 'invalid' } }
expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: false,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 2,
sp_request_url_present: false,
remember_device: false,
}

post :create, params: { user: { email: user.email.upcase, password: 'invalid' } }
expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)
post :create, params: { user: { email: user.email.upcase, password: 'invalid' } }
new_device: nil,
)
end

it 'tracks the presence of SP request_url in session' do
subject.session[:sp] = { request_url: mock_valid_site }
stub_analytics
analytics_hash = {

post :create, params: { user: { email: 'foo@example.com', password: 'password' } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: false,
user_id: 'anonymous-uuid',
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 1,
sp_request_url_present: true,
remember_device: false,
}

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: 'foo@example.com', password: 'password' } }
new_device: nil,
)
end

context 'IAL1 user' do
Expand Down Expand Up @@ -431,27 +450,24 @@
)

stub_analytics
analytics_hash = {

post :create, params: { user: { email: user.email, password: user.password } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: true,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 0,
sp_request_url_present: false,
remember_device: false,
}

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

profile_encryption_error = {
new_device: true,
)
expect(@analytics).to have_logged_event(
'Profile Encryption: Invalid',
error: 'Unable to parse encrypted payload',
}
expect(@analytics).to receive(:track_event).
with('Profile Encryption: Invalid', profile_encryption_error)

post :create, params: { user: { email: user.email, password: user.password } }

)
expect(controller.user_session[:encrypted_profiles]).to be_nil
expect(profile.reload).to_not be_active
end
Expand Down Expand Up @@ -558,20 +574,20 @@
}

stub_analytics
analytics_hash = {

post :create, params: { user: { email: user.email, password: user.password } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: true,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 0,
sp_request_url_present: false,
remember_device: true,
}

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: user.email, password: user.password } }
new_device: true,
)
end
end

Expand All @@ -584,20 +600,20 @@
}

stub_analytics
analytics_hash = {

post :create, params: { user: { email: user.email, password: user.password } }

expect(@analytics).to have_logged_event(
'Email and Password Authentication',
success: true,
user_id: user.uuid,
user_locked_out: false,
valid_captcha_result: true,
bad_password_count: 0,
sp_request_url_present: false,
remember_device: true,
}

expect(@analytics).to receive(:track_event).
with('Email and Password Authentication', analytics_hash)

post :create, params: { user: { email: user.email, password: user.password } }
new_device: true,
)
end
end

Expand Down