philomena/lib/pow_multi_factor/phoenix/controller_callbacks.ex
2019-11-02 09:14:03 -04:00

69 lines
2 KiB
Elixir

defmodule PowMultiFactor.Phoenix.ControllerCallbacks do
@moduledoc """
Controller callback logic for multi-factor authentication.
### 2FA code not submitted
Triggers on `Pow.Phoenix.SessionController.create/2`.
When a user with 2FA enabled attempts to sign in without submitting their
TOTP token, the session will be cleared, and the user redirected back to
`Pow.Phoenix.Routes.session_path/1`.
### User updates account
Triggers on `Pow.Phoenix.RegistrationController.update/2`
When a user changes their account settings, they are required to confirm a
current 2FA token.
See `PowMultiFactor.Ecto.Schema` for more.
"""
use Pow.Extension.Phoenix.ControllerCallbacks.Base
alias Pow.Plug
alias PowMultiFactor.Plug, as: PowMultiFactorPlug
def before_respond(Pow.Phoenix.SessionController, :create, {:ok, conn}, config) do
return_path = routes(conn).session_path(conn, :new)
clear_unauthorized(conn, config, {:ok, conn}, return_path)
end
def before_respond(Pow.Phoenix.RegistrationController, :update, {:ok, user, conn}, config) do
return_path = routes(conn).registration_path(conn, :edit)
halt_unauthorized(conn, config, {:ok, user, conn}, return_path)
end
defp clear_unauthorized(conn, config, success_response, return_path) do
case PowMultiFactorPlug.mfa_authorized?(conn, config) do
false -> clear_auth(conn) |> go_back(return_path)
true -> success_response
end
end
defp halt_unauthorized(conn, config, success_response, return_path) do
case PowMultiFactorPlug.mfa_authorized?(conn, config) do
false -> go_back(conn, return_path)
true -> success_response
end
end
def clear_auth(conn) do
{:ok, conn} = Plug.clear_authenticated_user(conn)
conn
end
defp go_back(conn, return_path) do
error = extension_messages(conn).invalid_multi_factor(conn)
conn =
conn
|> Phoenix.Controller.put_flash(:error, error)
|> Phoenix.Controller.redirect(to: return_path)
{:halt, conn}
end
end