4be3641fd9e07e6ed3c06c8d691e8a33a0efbce3
[anni] / lib / pleroma / web / auth / totp_authenticator.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.Auth.TOTPAuthenticator do
6   alias Pleroma.MFA
7   alias Pleroma.MFA.TOTP
8   alias Pleroma.User
9   alias Pleroma.Web.Plugs.AuthenticationPlug
10
11   @doc "Verify code or check backup code."
12   @spec verify(String.t(), User.t()) ::
13           {:ok, :pass} | {:error, :invalid_token | :invalid_secret_and_token}
14   def verify(
15         token,
16         %User{
17           multi_factor_authentication_settings:
18             %{enabled: true, totp: %{secret: secret, confirmed: true}} = _
19         } = _user
20       )
21       when is_binary(token) and byte_size(token) > 0 do
22     TOTP.validate_token(secret, token)
23   end
24
25   def verify(_, _), do: {:error, :invalid_token}
26
27   @spec verify_recovery_code(User.t(), String.t()) ::
28           {:ok, :pass} | {:error, :invalid_token}
29   def verify_recovery_code(
30         %User{multi_factor_authentication_settings: %{enabled: true, backup_codes: codes}} = user,
31         code
32       )
33       when is_list(codes) and is_binary(code) do
34     hash_code = Enum.find(codes, fn hash -> AuthenticationPlug.checkpw(code, hash) end)
35
36     if hash_code do
37       MFA.invalidate_backup_code(user, hash_code)
38       {:ok, :pass}
39     else
40       {:error, :invalid_token}
41     end
42   end
43
44   def verify_recovery_code(_, _), do: {:error, :invalid_token}
45 end