Skip to content

Commit cbff267

Browse files
author
John Pinto
committed
Fix for bug #3214 which had noted there was no request rate limit to
resetting the password. The Rack-Attack middleware for blocking & throttling abusive requests is being used. https://github.com/rack/rack-attack/blob/6-stable/README.md Changes: - Added rack-attack version 6.6.1 gem. https://rubygems.org/gems/rack-attack/versions/6.6.1 - Added config/initializers/rack_attack.rb: - The rack-attack functionality is enabled with Rack::Attack.enabled = true but may be switched off Rack::Attack.enabled = false. - Password reset requests are currently throttled from from an IP address for POSTs to path /users/passwords and is limited 2 requests every 30 seconds. ess - Login requests are throttled from an IP address for POSTs to path /users/sign_in and is limited 4 requests every 30 seconds. - A new html page public/429.html with title "Too Many Request" is added.
1 parent a803f43 commit cbff267

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ gem 'jwt'
119119
# OO authorization for Rails (https://github.com/elabs/pundit)
120120
gem 'pundit'
121121

122+
# Gem for throttling malicious attacks
123+
gem 'rack-attack', '~> 6.6', '>= 6.6.1'
124+
122125
# ========== #
123126
# UI / VIEWS #
124127
# ========== #

config/initializers/rack_attack.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
# NB: `req` is a Rack::Request object (basically an env hash with friendly accessor methods)
4+
5+
# Enable/disable Rack::Attack
6+
Rack::Attack.enabled = true
7+
8+
# Cache store required to work.
9+
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache
10+
11+
# Throttle should send a 429 Error responsec code and display public/429.html
12+
Rack::Attack.throttled_responder = lambda do |env|
13+
html = ActionView::Base.empty.render(file: 'public/429.html')
14+
[429, {'Content-Type' => 'text/html'}, [html]]
15+
end
16+
17+
# Throttle attempts to a particular path. 2 POSTs to /users/password every 30 seconds
18+
Rack::Attack.throttle "password_resets/ip", limit: 2, period: 30.seconds do |req|
19+
req.post? && req.path == "/users/password" && req.ip
20+
end
21+
22+
# Throttle attempts to a particular path. 2 POSTs to /users/sign_in every 20 seconds
23+
Rack::Attack.throttle "logins/ip", limit: 2, period: 20.seconds do |req|
24+
req.post? && req.path == "/users/sign_in" && req.ip
25+
end

public/429.html

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>We're sorry, but something went wrong (500)</title>
5+
<style type="text/css">
6+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7+
div.dialog {
8+
width: 25em;
9+
padding: 0 4em;
10+
margin: 4em auto 0 auto;
11+
border: 1px solid #ccc;
12+
border-right-color: #999;
13+
border-bottom-color: #999;
14+
}
15+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16+
</style>
17+
</head>
18+
19+
<body>
20+
<!-- This file lives in public/429.html -->
21+
<div class="dialog">
22+
<h1>Too Many Requests</h1>
23+
24+
<p>You have exceeded the number of requests for this resource. For security reasons access is limited to a fixed number in a given period. Retry later.</p>
25+
26+
27+
</div>
28+
</body>
29+
</html>

0 commit comments

Comments
 (0)