identity-vault/config/initializers/rack_attack.rb
2026-01-01 17:47:36 -05:00

60 lines
1.5 KiB
Ruby

class Rack::Attack
throttle("logins/email", limit: 5, period: 5.minutes) do |req|
if req.path == "/login" && req.post?
req.params["email"]&.to_s&.downcase&.presence
end
end
throttle("logins/ip", limit: 10, period: 5.minutes) do |req|
if req.path == "/login" && req.post?
req.ip
end
end
throttle("email_verify/attempt", limit: 10, period: 5.minutes) do |req|
if req.path.match?(%r{^/login/(.+)/verify$}) && req.post?
$1
end
end
throttle("totp_login/attempt", limit: 5, period: 5.minutes) do |req|
if req.path.match?(%r{^/login/(.+)/totp$}) && req.post?
$1
end
end
throttle("backup_code_login/attempt", limit: 5, period: 5.minutes) do |req|
if req.path.match?(%r{^/login/(.+)/backup_code$}) && req.post?
$1
end
end
throttle("login_verify/ip", limit: 20, period: 5.minutes) do |req|
if req.path.match?(%r{^/login/.+/(verify|totp|backup_code)$}) && req.post?
req.ip
end
end
throttle("email_change/ip", limit: 3, period: 1.hour) do |req|
if req.path == "/email_changes" && req.post?
req.ip
end
end
throttle("email_change_verify/ip", limit: 10, period: 5.minutes) do |req|
if req.path.match?(%r{^/email_changes/verify/(old|new)$}) && %w[GET POST].include?(req.request_method)
req.ip
end
end
self.throttled_responder = lambda do |env|
headers = {
"Content-Type" => "text/html",
"Retry-After" => "300" #
}
message = "slow your roll!"
[ 429, headers, [ message ] ]
end
end