defmodule GitGud.Accounts.PasswordThrottle do
@moduledoc """
Password sign-in with a cap on wrong guesses, for every place a
password is accepted: the login form and Basic auth for git and the
package registries.
Two counts, both bumped by every wrong password and checked before
the password is tried:
* per login (the email or handle as typed, case-folded) — ten in
15 minutes, so one account can't be guessed at however many
addresses the guesses come from;
* per client address — fifty in 15 minutes, so one client can't
walk a list of accounts.
Counted whether or not the account exists, so being refused says
nothing about whether it does. A right password clears its login's
count. Limits live in `GitGud.RateLimit`.
"""
alias GitGud.Accounts
alias GitGud.Accounts.User
alias GitGud.RateLimit
require Logger
@doc """
`{:ok, user}` for the right password, `:error` for a wrong one or an
unknown login, `{:error, :rate_limited, retry_after_s}` when this
login or address has run out of guesses (the password isn't tried).
"""
@spec authenticate(String.t(), String.t(), :inet.ip_address() | nil) ::
{:ok, User.t()} | :error | {:error, :rate_limited, pos_integer()}
def authenticate(login, password, ip) when is_binary(login) and is_binary(password) do
login_key = normalize(login)
ip_key = RateLimit.ip_key(ip)
with :ok <- RateLimit.check(:login_account, login_key),
:ok <- RateLimit.check(:login_ip, ip_key) do
case Accounts.get_user_by_email_and_password(login, password) do
%User{} = user ->
RateLimit.clear(:login_account, login_key)
{:ok, user}
_ ->
RateLimit.record(:login_account, login_key)
RateLimit.record(:login_ip, ip_key)
:error
end
else
{:error, retry_after} ->
Logger.warning("password sign-in refused for #{ip_key}: too many wrong passwords")
{:error, :rate_limited, retry_after}
end
end
def authenticate(_login, _password, _ip), do: :error
defp normalize(login), do: login |> String.trim() |> String.downcase()
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
2.1 KiB · text
History
b868907