auth against sha512-crypt password hashes, upgrade to pbkdf2

This commit is contained in:
Moon Man 2018-09-05 00:21:44 -04:00
parent 8143251f06
commit 1a8bc26e52
3 changed files with 52 additions and 2 deletions

View File

@ -14,7 +14,17 @@ def call(conn, opts) do
{:ok, user} <- opts[:fetcher].(username), {:ok, user} <- opts[:fetcher].(username),
false <- !!user.info["deactivated"], false <- !!user.info["deactivated"],
saved_user_id <- get_session(conn, :user_id), saved_user_id <- get_session(conn, :user_id),
legacy_password <- String.starts_with?(user.password_hash, "$6$"),
update_legacy_password <-
!(Map.has_key?(opts, :update_legacy_password) && opts[:update_legacy_password] == false),
{:ok, verified_user} <- verify(user, password, saved_user_id) do {:ok, verified_user} <- verify(user, password, saved_user_id) do
if legacy_password and update_legacy_password do
User.reset_password(verified_user, %{
:password => password,
:password_confirmation => password
})
end
conn conn
|> assign(:user, verified_user) |> assign(:user, verified_user)
|> put_session(:user_id, verified_user.id) |> put_session(:user_id, verified_user.id)
@ -34,7 +44,18 @@ defp verify(nil, _password, _user_id) do
end end
defp verify(user, password, _user_id) do defp verify(user, password, _user_id) do
if Pbkdf2.checkpw(password, user.password_hash) do is_legacy = String.starts_with?(user.password_hash, "$6$")
valid =
cond do
is_legacy ->
:crypt.crypt(password, user.password_hash) == user.password_hash
true ->
Pbkdf2.checkpw(password, user.password_hash)
end
if valid do
{:ok, user} {:ok, user}
else else
:error :error

View File

@ -50,7 +50,8 @@ defp deps do
{:ex_aws_s3, "~> 2.0"}, {:ex_aws_s3, "~> 2.0"},
{:ex_machina, "~> 2.2", only: :test}, {:ex_machina, "~> 2.2", only: :test},
{:credo, "~> 0.9.3", only: [:dev, :test]}, {:credo, "~> 0.9.3", only: [:dev, :test]},
{:mock, "~> 0.3.1", only: :test} {:mock, "~> 0.3.1", only: :test},
{:crypt, git: "https://github.com/msantos/crypt"}
] ]
end end

View File

@ -21,6 +21,13 @@ defp fetch_nil(_name) do
info: %{"deactivated" => true} info: %{"deactivated" => true}
} }
@legacy %User{
id: 1,
name: "dude",
password_hash:
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
}
@session_opts [ @session_opts [
store: :cookie, store: :cookie,
key: "_test", key: "_test",
@ -139,6 +146,27 @@ test "it assigns the user", %{conn: conn} do
assert get_session(conn, :user_id) == @user.id assert get_session(conn, :user_id) == @user.id
assert conn.halted == false assert conn.halted == false
end end
test "it assigns legacy user", %{conn: conn} do
opts = %{
optional: true,
fetcher: fn _ -> {:ok, @legacy} end,
update_legacy_password: false
}
header = basic_auth_enc("dude", "password")
conn =
conn
|> Plug.Session.call(Plug.Session.init(@session_opts))
|> fetch_session
|> put_req_header("authorization", header)
|> AuthenticationPlug.call(opts)
assert %{user: @legacy} == conn.assigns
assert get_session(conn, :user_id) == @legacy.id
assert conn.halted == false
end
end end
describe "with a correct authorization header for an deactiviated user" do describe "with a correct authorization header for an deactiviated user" do