rails_api_base
rails_api_base copied to clipboard
Add rack attack for login endpoint
For security reasons, I think it makes sense to have the login endpoint limited.
For example something like this:
RACK_ATTACK_THROTTLE_LIMIT = ENV.fetch('RACK_ATTACK_THROTTLE_LIMIT', 6)
RACK_ATTACK_THROTTLE_PERIOD_IN_SECONDS = ENV.fetch('RACK_ATTACK_THROTTLE_PERIOD', 1.minute.to_i)
Rack::Attack.throttle(
'requests_to_api_login_path_per_minute_per_ip',
limit: RACK_ATTACK_THROTTLE_LIMIT,
period: RACK_ATTACK_THROTTLE_PERIOD_IN_SECONDS
) do |request|
login_path = Rails.application.routes.url_helpers.new_user_session_path
request.ip if request.path.starts_with?(login_path)
end
Why not add this to the whole API?
Related: https://blog.heroku.com/rate-throttle-api-client
Not only the login end but also a default config to block malicious ips https://github.com/rack/rack-attack/blob/master/docs/example_configuration.md
# If any single client IP is making tons of requests, then they're
# probably malicious or a poorly-configured scraper. Either way, they
# don't deserve to hog all of the app server's CPU. Cut them off!
#
# Note: If you're serving assets through rack, those requests may be
# counted by rack-attack and this throttle may be activated too
# quickly. If so, enable the condition to exclude them from tracking.
# Throttle all requests by IP (60rpm)
#
# Key: "rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}"
throttle('req/ip', limit: 300, period: 5.minutes) do |req|
req.ip # unless req.path.start_with?('/assets')
end```
I agree with @vitogit and you may also consider throttle for user emails:
# Throttle login attempts for a given email parameter to 6 reqs/minute
# Return the *normalized* email as a discriminator on POST /login requests
Rack::Attack.throttle('limit logins per email', limit: 6, period: 60) do |req|
if req.path == '/login' && req.post?
# Normalize the email, using the same logic as your authentication process, to
# protect against rate limit bypasses.
req.params['email'].to_s.downcase.gsub(/\s+/, "")
end
end
This is useful to be protected against malicious users trying to log in for another user email (with different ips)