mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-31 19:36:44 +01:00
fixups
This commit is contained in:
parent
f627677cb6
commit
7784c09b3e
4 changed files with 41 additions and 25 deletions
|
@ -4,7 +4,8 @@ defmodule Philomena.Users.User do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
use Pow.Ecto.Schema,
|
use Pow.Ecto.Schema,
|
||||||
password_hash_methods: {&Password.hash_pwd_salt/1, &Password.verify_pass/2}
|
password_hash_methods: {&Password.hash_pwd_salt/1, &Password.verify_pass/2},
|
||||||
|
password_min_length: 6
|
||||||
|
|
||||||
use Pow.Extension.Ecto.Schema,
|
use Pow.Extension.Ecto.Schema,
|
||||||
extensions: [PowResetPassword, PowPersistentSession]
|
extensions: [PowResetPassword, PowPersistentSession]
|
||||||
|
@ -128,44 +129,43 @@ defmodule Philomena.Users.User do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def consume_totp_token_changeset(user, token) do
|
def consume_totp_token_changeset(changeset, params) do
|
||||||
|
changeset = change(changeset, %{})
|
||||||
|
user = changeset.data
|
||||||
|
token = extract_token(params)
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
totp_valid?(user, token) ->
|
totp_valid?(user, token) ->
|
||||||
user
|
changeset
|
||||||
|> change(%{consumed_timestep: token})
|
|> change(%{consumed_timestep: String.to_integer(token)})
|
||||||
|
|
||||||
backup_code_valid?(user, token) ->
|
backup_code_valid?(user, token) ->
|
||||||
user
|
changeset
|
||||||
|> change(%{otp_backup_codes: remove_backup_code(user, token)})
|
|> change(%{otp_backup_codes: remove_backup_code(user, token)})
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
user
|
changeset
|
||||||
|> add_error(:consumed_timestep, "invalid token")
|
|> add_error(:consumed_timestep, "invalid token")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def totp_changeset(user, params, backup_codes) do
|
def totp_changeset(changeset, params, backup_codes) do
|
||||||
token =
|
changeset = change(changeset, %{})
|
||||||
case params do
|
user = changeset.data
|
||||||
%{"user" => %{"twofactor_token" => t}} ->
|
token = extract_token(params)
|
||||||
to_string(t)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
""
|
|
||||||
end
|
|
||||||
|
|
||||||
case user.otp_required_for_login do
|
case user.otp_required_for_login do
|
||||||
true ->
|
true ->
|
||||||
# User wants to disable TOTP
|
# User wants to disable TOTP
|
||||||
user
|
changeset
|
||||||
|> pow_current_password_changeset(params)
|
|> pow_password_changeset(params)
|
||||||
|> consume_totp_token_changeset(token)
|
|> consume_totp_token_changeset(token)
|
||||||
|> disable_totp_changeset()
|
|> disable_totp_changeset()
|
||||||
|
|
||||||
false ->
|
_falsy ->
|
||||||
# User wants to enable TOTP
|
# User wants to enable TOTP
|
||||||
user
|
changeset
|
||||||
|> pow_current_password_changeset(params)
|
|> pow_password_changeset(params)
|
||||||
|> consume_totp_token_changeset(token)
|
|> consume_totp_token_changeset(token)
|
||||||
|> enable_totp_changeset(backup_codes)
|
|> enable_totp_changeset(backup_codes)
|
||||||
end
|
end
|
||||||
|
@ -226,6 +226,12 @@ defmodule Philomena.Users.User do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp extract_token(%{"user" => %{"twofactor_token" => t}}),
|
||||||
|
do: to_string(t)
|
||||||
|
|
||||||
|
defp extract_token(_params),
|
||||||
|
do: ""
|
||||||
|
|
||||||
defp totp_valid?(user, token),
|
defp totp_valid?(user, token),
|
||||||
do: :pot.valid_totp(token, totp_secret(user), window: 60)
|
do: :pot.valid_totp(token, totp_secret(user), window: 60)
|
||||||
|
|
||||||
|
@ -234,4 +240,4 @@ defmodule Philomena.Users.User do
|
||||||
|
|
||||||
defp remove_backup_code(user, token),
|
defp remove_backup_code(user, token),
|
||||||
do: user.otp_backup_codes |> Enum.reject(&Password.verify_pass(token, &1))
|
do: user.otp_backup_codes |> Enum.reject(&Password.verify_pass(token, &1))
|
||||||
end
|
end
|
|
@ -34,18 +34,20 @@ defmodule PhilomenaWeb.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", PhilomenaWeb do
|
scope "/", PhilomenaWeb do
|
||||||
pipe_through [:browser, :ensure_totp]
|
pipe_through [:browser, :protected]
|
||||||
|
|
||||||
# Additional routes for TOTP
|
# Additional routes for TOTP
|
||||||
scope "/registration", Registration, as: :registration do
|
scope "/registration", Registration, as: :registration do
|
||||||
pipe_through :protected
|
|
||||||
resources "/totp", TotpController, only: [:edit, :update], singleton: true
|
resources "/totp", TotpController, only: [:edit, :update], singleton: true
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/session", Session, as: :session do
|
scope "/session", Session, as: :session do
|
||||||
pipe_through :protected
|
|
||||||
resources "/totp", TotpController, only: [:new, :create], singleton: true
|
resources "/totp", TotpController, only: [:new, :create], singleton: true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scope "/", PhilomenaWeb do
|
||||||
|
pipe_through [:browser, :ensure_totp]
|
||||||
|
|
||||||
get "/", ActivityController, :index
|
get "/", ActivityController, :index
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ header.header
|
||||||
span.hide-limited-desktop< Filters
|
span.hide-limited-desktop< Filters
|
||||||
.dropdown.header__dropdown
|
.dropdown.header__dropdown
|
||||||
a.header__link.header__link-user href="/"
|
a.header__link.header__link-user href="/"
|
||||||
/= user_avatar(@current_user, 'avatar--28px'.freeze, @current_user.name)
|
= render PhilomenaWeb.UserAttributionView, "_user_avatar.html", object: %{user: @current_user}, class: "avatar--28px"
|
||||||
span.header__link-user__dropdown-arrow.hide-mobile data-click-preventdefault="true"
|
span.header__link-user__dropdown-arrow.hide-mobile data-click-preventdefault="true"
|
||||||
nav.dropdown__content.dropdown__content-right.hide-mobile.js-burger-links
|
nav.dropdown__content.dropdown__content-right.hide-mobile.js-burger-links
|
||||||
a.header__link href="/profiles"
|
a.header__link href="/profiles"
|
||||||
|
|
8
lib/philomena_web/templates/session/totp/new.html.slime
Normal file
8
lib/philomena_web/templates/session/totp/new.html.slime
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
h1 Two Factor Authentication
|
||||||
|
|
||||||
|
= form_for @changeset, Routes.session_totp_path(@conn, :create), [as: :user, method: "post"], fn f ->
|
||||||
|
.field
|
||||||
|
h4 Please enter your 2FA code
|
||||||
|
= text_input f, :twofactor_token, class: "input", placeholder: "6-digit code", required: true, autofocus: true, autocomplete: "off"
|
||||||
|
|
||||||
|
= submit "Sign in", class: "button"
|
Loading…
Reference in a new issue