From a24c342f305f0974ca41ab5d7e4bcc3d01915866 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Fri, 10 Jun 2022 00:59:48 +0000 Subject: [PATCH] Rjb throttle verification challenge attempts --- make_post_sell/models/user.py | 9 +++++++ ...6ac162d096f_password_attempt_throttling.py | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 make_post_sell/scripts/alembic/versions/e6ac162d096f_password_attempt_throttling.py diff --git a/make_post_sell/models/user.py b/make_post_sell/models/user.py index a8cfbba..f478ee8 100644 --- a/make_post_sell/models/user.py +++ b/make_post_sell/models/user.py @@ -49,6 +49,7 @@ class User(RBase, Base): email = Column(Unicode(64), unique=True, nullable=False) #email_unverified = Column(Unicode(64)) password = Column(Unicode(64)) + password_attempts = Column(Integer, default=0) password_timestamp = Column(BigInteger) created_timestamp = Column(BigInteger, nullable=False) gravatar = Column(Boolean, default=False) @@ -111,17 +112,25 @@ class User(RBase, Base): bcrypt.gensalt() ).decode("utf-8") self.password_timestamp = now_timestamp() + self.password_attempts = 0 return raw_password def check_password(self, password): """Accept plain-text raw password, create hash, compare with DB.""" stored_hash = self.password + # increment password attempts. + self.password_attempts += 1 + # expire password after 15 minutes. # 900000 milliseconds == 15 minutes if self.password_timestamp_delta >= 900000: return False + # prevent brute force, allow 10 invalid verification code attempts. + if self.password_attempts >= 10: + return False + # bcrypt works with bytes so we encode to utf-8. new_hash = bcrypt.hashpw( password.encode("utf-8"), diff --git a/make_post_sell/scripts/alembic/versions/e6ac162d096f_password_attempt_throttling.py b/make_post_sell/scripts/alembic/versions/e6ac162d096f_password_attempt_throttling.py new file mode 100644 index 0000000..4a7156e --- /dev/null +++ b/make_post_sell/scripts/alembic/versions/e6ac162d096f_password_attempt_throttling.py @@ -0,0 +1,26 @@ +"""password-attempt-throttling + +Revision ID: e6ac162d096f +Revises: c263b4fba9e7 +Create Date: 2022-06-09 20:52:58.235423 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'e6ac162d096f' +down_revision = 'c263b4fba9e7' +branch_labels = None +depends_on = None + +from make_post_sell.models.meta import UUIDType + + +def upgrade(): + op.add_column('mps_user', sa.Column('password_attempts', sa.Integer(), nullable=True, server_default="0")) + + +def downgrade(): + op.drop_column('mps_user', 'password_attempts')