I will show you how to rate-limit your authentication endpoints with Rack Attack.
Rack::Attack is a middleware for blocking or throttling requests based on rules. It uses the configured cache store of Rails to store the necessary data, but a separate data store can be configured too.
In the examples, I will use Devise's endpoints, but the same setup works with any authentication system, you just need to change the URLs.
Setting up Rack::Attack is very simple, you need to add the gem to your project with bundle add rack-attack
.
Once we have the gem installed, we can add our configuration to an initializer, I use config/initializers/rack_attack.rb
for that.
To prevent credential stuffing attacks on the login endpoint, you can throttle requests by IP address to a 15 attempts per minute:
class Rack::Attack
throttle('logins/ip', limit: 15, period: 1.minute) do |req|
if req.path == '/users/sign_in' && req.post?
req.ip
end
end
end
The throttle
call expects the name for the rule and the options as parameters. In the above example, we limit post requests to the /users/sign_in
path to 15 per minute for the IP address.
We can harden the configuration even more and add another rule to throttle requests with the same email address:
throttle('logins/email', limit: 10, period: 1.minutes) do |req|
if req.path == '/users/sign_in' && req.post?
req.params['user']['email'].to_s.downcase.gsub(/\s+/, "").presence
end
end
The above rule will throttle login attempts with the same email address to 10 per every minute. This rule prevents brute force attacks.
These two rules will significantly improve the security posture of your Rails app, but depending on your needs, you can introduce additional throttling easily with Rack Attack.
Top comments (2)
Checkin if this uses Hotwire
Hotwire doesn't make a difference here.