diff --git a/lib/philomena_web/plugs/compromised_password_check_plug.ex b/lib/philomena_web/plugs/compromised_password_check_plug.ex new file mode 100644 index 00000000..07aff0b4 --- /dev/null +++ b/lib/philomena_web/plugs/compromised_password_check_plug.ex @@ -0,0 +1,42 @@ +defmodule PhilomenaWeb.CompromisedPasswordCheckPlug do + import Phoenix.Controller + + def init(opts), do: opts + + def call(conn, _opts) do + error_if_password_compromised(conn, conn.params) + end + + defp error_if_password_compromised(conn, %{"user" => %{"password" => password}}) do + case password_compromised?(password) do + true -> + conn + |> put_flash( + :error, + "We've detected that the password you entered has been compromised during a data breach of another website. Please choose a different password." + ) + |> redirect(external: conn.assigns.referrer) + + false -> + conn + end + end + + defp error_if_password_compromised(conn, _params), + do: conn + + defp password_compromised?(password) do + <> = + :crypto.hash(:sha, password) + |> Base.encode16() + + case HTTPoison.get(make_api_url(prefix)) do + {:ok, %HTTPoison.Response{body: body, status_code: 200}} -> String.contains?(body, rest) + _ -> false + end + end + + defp make_api_url(prefix) do + "https://api.pwnedpasswords.com/range/#{prefix}" + end +end diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index d8589364..fc5f8894 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -52,13 +52,23 @@ defmodule PhilomenaWeb.Router do plug PhilomenaWeb.FilterBannedUsersPlug end + pipeline :ensure_password_not_compromised do + plug PhilomenaWeb.CompromisedPasswordCheckPlug + end + pipeline :protected do plug Pow.Plug.RequireAuthenticated, error_handler: Pow.Phoenix.PlugErrorHandler end scope "/" do - pipe_through [:browser, :ensure_totp, :ensure_not_banned, :ensure_tor_authorized] + pipe_through [ + :browser, + :ensure_totp, + :ensure_not_banned, + :ensure_tor_authorized, + :ensure_password_not_compromised + ] pow_registration_routes() end