To prevent potential denial of service for valid users via account lockouts.
defmodule VulnerableApp do
def login(user, password) do
case authenticate(user, password) do
:ok -> {:ok, get_user(user)}
{:error, :invalid_credentials} -> update_failed_attempts(user)
end
end
defp update_failed_attempts(user) do
user
|> increment_failed_attempts()
|> case do
%{failed_attempts: 3} -> lock_account(user)
_ -> :ok
end
end
end
This code accepts user credentials and locks the user account after three failed login attempts. An attacker could exploit this by purposely failing login attempts for a targeted user, effectively locking them out of their account.
defmodule SecureApp do
def login(user, password) do
case authenticate(user, password) do
:ok -> {:ok, get_user(user)}
{:error, :invalid_credentials} -> update_failed_attempts(user)
end
end
defp update_failed_attempts(user) do
user
|> increment_failed_attempts()
|> case do
%{failed_attempts: 3} -> notify_user_and_lock_account(user)
_ -> :ok
end
end
end
This code implements a progressive delay after each failed login attempt, slowing down potential brute force attacks without locking out legitimate users. It also sends a notification to the user when their account is locked, providing a way for legitimate users to unlock their account.