users: refactor login and authentication logic.
* Make authentication methods into User instance methods instead of class methods. * Fix API key authentication to use a secure string comparison. Fixes a hypothetical (unlikely to be exploitable) timing attack. * Move login logic from SessionCreator to SessionLoader.
This commit is contained in:
@@ -18,8 +18,8 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
|
||||
put_auth user_password_path(@user), @user, params: { user: { old_password: "12345", password: "abcde", password_confirmation: "abcde" } }
|
||||
|
||||
assert_redirected_to @user
|
||||
assert_equal(nil, User.authenticate(@user.name, "12345"))
|
||||
assert_equal(@user, User.authenticate(@user.name, "abcde"))
|
||||
assert_equal(false, @user.reload.authenticate_password("12345"))
|
||||
assert_equal(@user, @user.authenticate_password("abcde"))
|
||||
end
|
||||
|
||||
should "update the password when given a valid login key" do
|
||||
@@ -27,24 +27,24 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
|
||||
put_auth user_password_path(@user), @user, params: { user: { password: "abcde", password_confirmation: "abcde", signed_user_id: signed_user_id } }
|
||||
|
||||
assert_redirected_to @user
|
||||
assert_equal(nil, User.authenticate(@user.name, "12345"))
|
||||
assert_equal(@user, User.authenticate(@user.name, "abcde"))
|
||||
assert_equal(false, @user.reload.authenticate_password("12345"))
|
||||
assert_equal(@user, @user.authenticate_password("abcde"))
|
||||
end
|
||||
|
||||
should "not update the password when given an invalid old password" do
|
||||
put_auth user_password_path(@user), @user, params: { user: { old_password: "3qoirjqe", password: "abcde", password_confirmation: "abcde" } }
|
||||
|
||||
assert_response :success
|
||||
assert_equal(@user, User.authenticate(@user.name, "12345"))
|
||||
assert_equal(nil, User.authenticate(@user.name, "abcde"))
|
||||
assert_equal(@user, @user.reload.authenticate_password("12345"))
|
||||
assert_equal(false, @user.authenticate_password("abcde"))
|
||||
end
|
||||
|
||||
should "not update the password when password confirmation fails for the new password" do
|
||||
put_auth user_password_path(@user), @user, params: { user: { old_password: "12345", password: "abcde", password_confirmation: "qerogijqe" } }
|
||||
|
||||
assert_response :success
|
||||
assert_equal(@user, User.authenticate(@user.name, "12345"))
|
||||
assert_equal(nil, User.authenticate(@user.name, "abcde"))
|
||||
assert_equal(@user, @user.reload.authenticate_password("12345"))
|
||||
assert_equal(false, @user.authenticate_password("abcde"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'test_helper'
|
||||
class SessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
context "the sessions controller" do
|
||||
setup do
|
||||
@user = create(:user)
|
||||
@user = create(:user, password: "password")
|
||||
end
|
||||
|
||||
context "new action" do
|
||||
@@ -14,15 +14,27 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
context "create action" do
|
||||
should "create a new session" do
|
||||
post session_path, params: {:name => @user.name, :password => "password"}
|
||||
should "log the user in when given the correct password" do
|
||||
post session_path, params: { name: @user.name, password: "password" }
|
||||
|
||||
assert_redirected_to posts_path
|
||||
assert_equal(@user.id, session[:user_id])
|
||||
assert_not_nil(@user.reload.last_ip_addr)
|
||||
end
|
||||
|
||||
should "not allow IP banned users to create a new session" do
|
||||
should "not log the user in when given an incorrect password" do
|
||||
post session_path, params: { name: @user.name, password: "wrong"}
|
||||
|
||||
assert_response 401
|
||||
assert_nil(nil, session[:user_id])
|
||||
end
|
||||
|
||||
should "redirect the user when given an url param" do
|
||||
post session_path, params: { name: @user.name, password: "password", url: tags_path }
|
||||
assert_redirected_to tags_path
|
||||
end
|
||||
|
||||
should "not allow IP banned users to login" do
|
||||
create(:ip_ban, ip_addr: "1.2.3.4")
|
||||
post session_path, params: { name: @user.name, password: "password" }, headers: { REMOTE_ADDR: "1.2.3.4" }
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_redirected_to User.last
|
||||
assert_equal("xxx", User.last.name)
|
||||
assert_equal(User.last, User.authenticate("xxx", "xxxxx1"))
|
||||
assert_equal(User.last, User.last.authenticate_password("xxxxx1"))
|
||||
assert_equal(nil, User.last.email_address)
|
||||
assert_no_enqueued_emails
|
||||
end
|
||||
@@ -128,7 +128,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_redirected_to User.last
|
||||
assert_equal("xxx", User.last.name)
|
||||
assert_equal(User.last, User.authenticate("xxx", "xxxxx1"))
|
||||
assert_equal(User.last, User.last.authenticate_password("xxxxx1"))
|
||||
assert_equal("webmaster@danbooru.donmai.us", User.last.email_address.address)
|
||||
assert_enqueued_email_with UserMailer, :welcome_user, args: [User.last]
|
||||
end
|
||||
|
||||
@@ -18,15 +18,15 @@ class ApiKeyTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
should "authenticate via api key" do
|
||||
assert_not_nil(User.authenticate_api_key(@user.name, @api_key.key))
|
||||
assert_equal(@user, @user.authenticate_api_key(@api_key.key))
|
||||
end
|
||||
|
||||
should "not authenticate with the wrong api key" do
|
||||
assert_nil(User.authenticate_api_key(@user.name, "xxx"))
|
||||
assert_equal(false, @user.authenticate_api_key("xxx"))
|
||||
end
|
||||
|
||||
should "not authenticate with the wrong name" do
|
||||
assert_nil(User.authenticate_api_key("xxx", @api_key.key))
|
||||
assert_equal(false, create(:user).authenticate_api_key(@api_key.key))
|
||||
end
|
||||
|
||||
should "have the same limits whether or not they have an api key" do
|
||||
|
||||
@@ -43,7 +43,7 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
|
||||
should "reset the password" do
|
||||
@deletion.delete!
|
||||
assert_nil(User.authenticate(@user.name, "password"))
|
||||
assert_equal(false, @user.authenticate_password("password"))
|
||||
end
|
||||
|
||||
should "remove any favorites" do
|
||||
|
||||
@@ -39,11 +39,9 @@ class UserTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
should "authenticate" do
|
||||
assert(User.authenticate(@user.name, "password"), "Authentication should have succeeded")
|
||||
assert(!User.authenticate(@user.name, "password2"), "Authentication should not have succeeded")
|
||||
assert(User.authenticate_hash(@user.name, User.sha1("password")), "Authentication should have succeeded")
|
||||
assert(!User.authenticate_hash(@user.name, User.sha1("xxx")), "Authentication should not have succeeded")
|
||||
should "authenticate password" do
|
||||
assert_equal(@user, @user.authenticate_password("password"))
|
||||
assert_equal(false, @user.authenticate_password("password2"))
|
||||
end
|
||||
|
||||
should "normalize its level" do
|
||||
|
||||
Reference in New Issue
Block a user