Add exponential backoff of login attempts.
This commit is contained in:
parent
066b3ed8f0
commit
2dcdd7ba5b
5 changed files with 46 additions and 1 deletions
|
@ -1,12 +1,17 @@
|
|||
import bcrypt
|
||||
import logging
|
||||
import datetime
|
||||
import dateutil.parser
|
||||
import json
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from data.database import *
|
||||
from util.validation import *
|
||||
from util.names import format_robot_username
|
||||
from util.backoff import exponential_backoff
|
||||
|
||||
|
||||
EXPONENTIAL_BACKOFF_SCALE = timedelta(seconds=1)
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -68,6 +73,12 @@ class TooManyUsersException(DataModelException):
|
|||
pass
|
||||
|
||||
|
||||
class TooManyLoginAttemptsException(Exception):
|
||||
def __init__(self, message, retry_after):
|
||||
super(TooManyLoginAttemptsException, self).__init__(message)
|
||||
self.retry_after = retry_after
|
||||
|
||||
|
||||
def is_create_user_allowed():
|
||||
return True
|
||||
|
||||
|
@ -551,11 +562,30 @@ def verify_user(username_or_email, password):
|
|||
except User.DoesNotExist:
|
||||
return None
|
||||
|
||||
now = datetime.utcnow()
|
||||
|
||||
if fetched.invalid_login_attempts > 0:
|
||||
can_retry_at = exponential_backoff(fetched.invalid_login_attempts, EXPONENTIAL_BACKOFF_SCALE,
|
||||
fetched.last_invalid_login)
|
||||
|
||||
if can_retry_at > now:
|
||||
retry_after = can_retry_at - now
|
||||
raise TooManyLoginAttemptsException('Too many login attempts.', retry_after.total_seconds())
|
||||
|
||||
if (fetched.password_hash and
|
||||
bcrypt.hashpw(password, fetched.password_hash) ==
|
||||
fetched.password_hash):
|
||||
|
||||
if fetched.invalid_login_attempts > 0:
|
||||
fetched.invalid_login_attempts = 0
|
||||
fetched.save()
|
||||
|
||||
return fetched
|
||||
|
||||
fetched.invalid_login_attempts += 1
|
||||
fetched.last_invalid_login = now
|
||||
fetched.save()
|
||||
|
||||
# We weren't able to authorize the user
|
||||
return None
|
||||
|
||||
|
|
Reference in a new issue