mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Move logic for rate limiting user second factor to one place (#11941)
This moves all the rate limiting for user second factor (based on `params[:second_factor_token]` existing) to the one place, which rate limits by IP and also by username if a user is found.
This commit is contained in:
@@ -1735,11 +1735,12 @@ RSpec.describe SessionController do
|
||||
RateLimiter.enable
|
||||
RateLimiter.clear_all!
|
||||
|
||||
3.times do |x|
|
||||
6.times do |x|
|
||||
post "/session.json", params: {
|
||||
login: "#{user.username}#{x}",
|
||||
password: 'myawesomepassword',
|
||||
second_factor_token: '000000'
|
||||
second_factor_token: '000000',
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
@@ -1747,7 +1748,8 @@ RSpec.describe SessionController do
|
||||
post "/session.json", params: {
|
||||
login: user.username,
|
||||
password: 'myawesomepassword',
|
||||
second_factor_token: '000000'
|
||||
second_factor_token: '000000',
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
@@ -1759,11 +1761,12 @@ RSpec.describe SessionController do
|
||||
RateLimiter.enable
|
||||
RateLimiter.clear_all!
|
||||
|
||||
3.times do |x|
|
||||
6.times do |x|
|
||||
post "/session.json", params: {
|
||||
login: user.username,
|
||||
password: 'myawesomepassword',
|
||||
second_factor_token: '000000'
|
||||
second_factor_token: '000000',
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}, env: { "REMOTE_ADDR": "1.2.3.#{x}" }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
@@ -1773,7 +1776,8 @@ RSpec.describe SessionController do
|
||||
post "/session.json", params: {
|
||||
login: username,
|
||||
password: 'myawesomepassword',
|
||||
second_factor_token: '000000'
|
||||
second_factor_token: '000000',
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}, env: { "REMOTE_ADDR": "1.2.4.#{x}" }
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
|
||||
@@ -323,7 +323,6 @@ describe UsersController do
|
||||
end
|
||||
|
||||
context "rate limiting" do
|
||||
|
||||
before { RateLimiter.clear_all!; RateLimiter.enable }
|
||||
after { RateLimiter.disable }
|
||||
|
||||
@@ -332,7 +331,7 @@ describe UsersController do
|
||||
|
||||
token = user.email_tokens.create!(email: user.email).token
|
||||
|
||||
3.times do
|
||||
6.times do
|
||||
put "/u/password-reset/#{token}", params: {
|
||||
second_factor_token: 123456,
|
||||
second_factor_method: 1
|
||||
@@ -349,6 +348,27 @@ describe UsersController do
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
|
||||
it "rate limits reset passwords by username" do
|
||||
freeze_time
|
||||
|
||||
token = user.email_tokens.create!(email: user.email).token
|
||||
|
||||
6.times do |x|
|
||||
put "/u/password-reset/#{token}", params: {
|
||||
second_factor_token: 123456,
|
||||
second_factor_method: 1
|
||||
}, env: { "REMOTE_ADDR": "1.2.3.#{x}" }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
put "/u/password-reset/#{token}", params: {
|
||||
second_factor_token: 123456,
|
||||
second_factor_method: 1
|
||||
}, env: { "REMOTE_ADDR": "1.2.3.4" }
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
end
|
||||
|
||||
context '2 factor authentication required' do
|
||||
@@ -3997,6 +4017,36 @@ describe UsersController do
|
||||
expect(user.user_second_factors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "rate limits by IP address" do
|
||||
RateLimiter.enable
|
||||
RateLimiter.clear_all!
|
||||
|
||||
create_totp
|
||||
staged_totp_key = read_secure_session["staged-totp-#{user.id}"]
|
||||
token = ROTP::TOTP.new(staged_totp_key).now
|
||||
|
||||
7.times do |x|
|
||||
post "/users/enable_second_factor_totp.json", params: { name: "test", second_factor_token: token }
|
||||
end
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
|
||||
it "rate limits by username" do
|
||||
RateLimiter.enable
|
||||
RateLimiter.clear_all!
|
||||
|
||||
create_totp
|
||||
staged_totp_key = read_secure_session["staged-totp-#{user.id}"]
|
||||
token = ROTP::TOTP.new(staged_totp_key).now
|
||||
|
||||
7.times do |x|
|
||||
post "/users/enable_second_factor_totp.json", params: { name: "test", second_factor_token: token }, env: { "REMOTE_ADDR": "1.2.3.#{x}" }
|
||||
end
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
|
||||
context "when an incorrect token is provided" do
|
||||
before do
|
||||
create_totp
|
||||
|
||||
@@ -131,6 +131,57 @@ describe UsersEmailController do
|
||||
user.reload
|
||||
expect(user.email).to eq("new.n.cool@example.com")
|
||||
end
|
||||
|
||||
context "rate limiting" do
|
||||
before { RateLimiter.clear_all!; RateLimiter.enable }
|
||||
after { RateLimiter.disable }
|
||||
|
||||
it "rate limits by IP" do
|
||||
freeze_time
|
||||
|
||||
6.times do
|
||||
put "/u/confirm-new-email", params: {
|
||||
token: "blah",
|
||||
second_factor_token: "000000",
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}
|
||||
|
||||
expect(response.status).to eq(302)
|
||||
end
|
||||
|
||||
put "/u/confirm-new-email", params: {
|
||||
token: "blah",
|
||||
second_factor_token: "000000",
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
|
||||
it "rate limits by username" do
|
||||
freeze_time
|
||||
|
||||
6.times do |x|
|
||||
user.email_change_requests.last.update(change_state: EmailChangeRequest.states[:complete])
|
||||
put "/u/confirm-new-email", params: {
|
||||
token: user.email_tokens.last.token,
|
||||
second_factor_token: "000000",
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}, env: { "REMOTE_ADDR": "1.2.3.#{x}" }
|
||||
|
||||
expect(response.status).to eq(302)
|
||||
end
|
||||
|
||||
user.email_change_requests.last.update(change_state: EmailChangeRequest.states[:authorizing_new])
|
||||
put "/u/confirm-new-email", params: {
|
||||
token: user.email_tokens.last.token,
|
||||
second_factor_token: "000000",
|
||||
second_factor_method: UserSecondFactor.methods[:totp]
|
||||
}, env: { "REMOTE_ADDR": "1.2.3.4" }
|
||||
|
||||
expect(response.status).to eq(429)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "security key required" do
|
||||
|
||||
Reference in New Issue
Block a user