Packages
phauxth
0.9.0
2.5.1
retired
2.5.0
2.4.0
2.3.2
2.3.1
2.3.0
2.2.0
2.1.1
2.1.0
2.0.1
2.0.0
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.1
2.0.0-beta.0
2.0.0-alpha.5
2.0.0-alpha.4
retired
2.0.0-alpha.3
retired
2.0.0-alpha.2
retired
2.0.0-alpha.1
retired
2.0.0-alpha.0
retired
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
0.17.1
0.17.0
0.16.0
0.15.1
0.15.0
0.14.0
0.13.0-rc.1
0.13.0-rc.0
0.12.1-rc.1
0.12.1-rc.0
0.12.0-rc
0.11.0
0.10.3
0.10.2
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
Authentication library for Phoenix, and other Plug-based, web applications
Current section
Files
Jump to
Current section
Files
lib/phauxth/otp.ex
defmodule Phauxth.Otp do
@moduledoc """
Module to handle one-time passwords, usually for use in two factor
authentication.
`Phauxth.Otp` checks the one-time password, and returns a
`phauxth_user` message (the user model) if the one-time password is
correct or a `phauxth_error` message if there is an error.
After this function has been called, you need to either add the user
to the session, by running `put_session(conn, :user_id, id)`, or send
an API token to the user.
## Options
There are the following options for the one-time passwords:
* HMAC-based one-time passwords
* token_length - the length of the one-time password
* the default is 6
* last - the count when the one-time password was last used
* this count needs to be stored server-side
* window - the number of future attempts allowed
* the default is 3
* Time-based one-time passwords
* token_length - the length of the one-time password
* the default is 6
* interval_length - the length of each timed interval
* the default is 30 (seconds)
* window - the number of attempts, before and after the current one, allowed
* the default is 1 (1 interval before and 1 interval after)
See the documentation for the Comeonin.Otp module for more details
about generating and verifying one-time passwords.
## Examples
Add the following line to your controller to call Otp with the
default values:
plug Phauxth.Otp when action in [:login_twofa]
And to set the token length to 8 characters:
plug Phauxth.Otp, [token_length: 8] when action in [:login_twofa]
"""
@behaviour Plug
import Ecto.{Changeset, Query}
import Phauxth.Login.Base
alias Comeonin.Otp
alias Phauxth.Config
@doc false
def init(opts), do: opts
@doc false
def call(%Plug.Conn{params: %{"user" => %{"id" => id, "hotp" => hotp}}} = conn, opts) do
{:ok, result} = Config.repo.transaction(fn ->
get_user_with_lock(Config.user_mod, id)
|> check_hotp(hotp, opts)
|> update_otp
end)
report(result, conn, id, "successful one-time password login")
end
def call(%Plug.Conn{params: %{"user" => %{"id" => id, "totp" => totp}}} = conn, opts) do
Config.repo.get(Config.user_mod, id)
|> check_totp(totp, opts)
|> update_otp
|> report(conn, id, "successful one-time password login")
end
defp check_hotp(user, hotp, opts) do
{user, Otp.check_hotp(hotp, user.otp_secret, [last: user.otp_last] ++ opts)}
end
defp check_totp(user, totp, opts) do
{user, Otp.check_totp(totp, user.otp_secret, opts)}
end
defp get_user_with_lock(user_model, id) do
from(u in user_model, where: u.id == ^id, lock: "FOR UPDATE")
|> Config.repo.one!
end
defp update_otp({_, false}), do: {:error, "invalid one-time password"}
defp update_otp({%{otp_last: otp_last} = user, last}) when last > otp_last do
change(user, %{otp_last: last}) |> Config.repo.update
end
defp update_otp(_), do: {:error, "invalid user-identifier"}
end