forked from GithubBackups/healthchecks
Add rate limiting for TOTP auth attempts
This commit is contained in:
parent
222722569e
commit
8ed5e93cd2
@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from hc.api.models import TokenBucket
|
||||||
from hc.test import BaseTestCase
|
from hc.test import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
@ -75,3 +76,11 @@ class LoginTotpTestCase(BaseTestCase):
|
|||||||
|
|
||||||
r = self.client.post(self.url, {"code": "000000"})
|
r = self.client.post(self.url, {"code": "000000"})
|
||||||
self.assertContains(r, "The code you entered was incorrect.")
|
self.assertContains(r, "The code you entered was incorrect.")
|
||||||
|
|
||||||
|
def test_it_uses_rate_limiting(self):
|
||||||
|
obj = TokenBucket(value=f"totp-{self.alice.id}")
|
||||||
|
obj.tokens = 0
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
r = self.client.post(self.url, {"code": "000000"})
|
||||||
|
self.assertContains(r, "Too Many Requests")
|
||||||
|
@ -848,6 +848,9 @@ def login_totp(request):
|
|||||||
|
|
||||||
totp = pyotp.totp.TOTP(user.profile.totp)
|
totp = pyotp.totp.TOTP(user.profile.totp)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
if not TokenBucket.authorize_totp(user):
|
||||||
|
return render(request, "try_later.html")
|
||||||
|
|
||||||
form = forms.TotpForm(totp, request.POST)
|
form = forms.TotpForm(totp, request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
request.session.pop("2fa_user")
|
request.session.pop("2fa_user")
|
||||||
|
@ -983,3 +983,11 @@ class TokenBucket(models.Model):
|
|||||||
|
|
||||||
# 10 sudo attempts per day
|
# 10 sudo attempts per day
|
||||||
return TokenBucket.authorize(value, 10, 3600 * 24)
|
return TokenBucket.authorize(value, 10, 3600 * 24)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def authorize_totp(user):
|
||||||
|
value = "totp-%d" % user.id
|
||||||
|
|
||||||
|
# 96 attempts per 24 hours
|
||||||
|
# (or, on average, one attempt per 15 minutes)
|
||||||
|
return TokenBucket.authorize(value, 96, 3600 * 24)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user