diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2017-12-09 14:20:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-09 14:20:02 +0100 |
commit | a865b62efc0f7025f789f4413a03ccacd57db7bb (patch) | |
tree | fd5e9a005e7788b906129ea2f57b480b77a1f056 /config | |
parent | 84cebad49d388a807bfc1f09cad825c6b9469883 (diff) |
Rate limit by user instead of IP when API user is authenticated (#5923)
* Fix #668 - Rate limit by user instead of IP when API user is authenticated * Fix code style issue * Use request decorator provided by Doorkeeper
Diffstat (limited to 'config')
-rw-r--r-- | config/initializers/rack_attack.rb | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index 53cb106ca..fddcbc52c 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -1,6 +1,41 @@ # frozen_string_literal: true class Rack::Attack + class Request + def authenticated_token + return @token if defined?(@token) + + @token = Doorkeeper::OAuth::Token.authenticate( + Doorkeeper::Grape::AuthorizationDecorator.new(self), + *Doorkeeper.configuration.access_token_methods + ) + end + + def authenticated_user_id + authenticated_token&.resource_owner_id + end + + def unauthenticated? + !authenticated_user_id + end + + def api_request? + path.start_with?('/api') + end + + def web_request? + !api_request? + end + end + + PROTECTED_PATHS = %w( + /auth/sign_in + /auth + /auth/password + ).freeze + + PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) + # Always allow requests from localhost # (blocklist & throttles are skipped) Rack::Attack.safelist('allow from localhost') do |req| @@ -8,24 +43,16 @@ class Rack::Attack '127.0.0.1' == req.ip || '::1' == req.ip end - # Rate limits for the API - throttle('api', limit: 300, period: 5.minutes) do |req| - req.ip if req.path =~ /\A\/api\/v/ - end - - # Rate limit logins - throttle('login', limit: 5, period: 5.minutes) do |req| - req.ip if req.path == '/auth/sign_in' && req.post? + throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req| + req.api_request? && req.authenticated_user_id end - # Rate limit sign-ups - throttle('register', limit: 5, period: 5.minutes) do |req| - req.ip if req.path == '/auth' && req.post? + throttle('throttle_unauthenticated_api', limit: 300, period: 5.minutes) do |req| + req.ip if req.api_request? && req.unauthenticated? end - # Rate limit forgotten passwords - throttle('reminder', limit: 5, period: 5.minutes) do |req| - req.ip if req.path == '/auth/password' && req.post? + throttle('protected_paths', limit: 5, period: 5.minutes) do |req| + req.ip if req.post? && req.path =~ PROTECTED_PATHS_REGEX end self.throttled_response = lambda do |env| |