auth against sha512-crypt password hashes, upgrade to pbkdf2
This commit is contained in:
parent
8143251f06
commit
1a8bc26e52
3 changed files with 52 additions and 2 deletions
|
@ -14,7 +14,17 @@ def call(conn, opts) do
|
|||
{:ok, user} <- opts[:fetcher].(username),
|
||||
false <- !!user.info["deactivated"],
|
||||
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
|
||||
if legacy_password and update_legacy_password do
|
||||
User.reset_password(verified_user, %{
|
||||
:password => password,
|
||||
:password_confirmation => password
|
||||
})
|
||||
end
|
||||
|
||||
conn
|
||||
|> assign(:user, verified_user)
|
||||
|> put_session(:user_id, verified_user.id)
|
||||
|
@ -34,7 +44,18 @@ defp verify(nil, _password, _user_id) do
|
|||
end
|
||||
|
||||
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}
|
||||
else
|
||||
:error
|
||||
|
|
3
mix.exs
3
mix.exs
|
@ -50,7 +50,8 @@ defp deps do
|
|||
{:ex_aws_s3, "~> 2.0"},
|
||||
{:ex_machina, "~> 2.2", only: :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
|
||||
|
||||
|
|
|
@ -21,6 +21,13 @@ defp fetch_nil(_name) do
|
|||
info: %{"deactivated" => true}
|
||||
}
|
||||
|
||||
@legacy %User{
|
||||
id: 1,
|
||||
name: "dude",
|
||||
password_hash:
|
||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
}
|
||||
|
||||
@session_opts [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
|
@ -139,6 +146,27 @@ test "it assigns the user", %{conn: conn} do
|
|||
assert get_session(conn, :user_id) == @user.id
|
||||
assert conn.halted == false
|
||||
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
|
||||
|
||||
describe "with a correct authorization header for an deactiviated user" do
|
||||
|
|
Loading…
Reference in a new issue