diff --git a/CHANGELOG.md b/CHANGELOG.md index 8219064..e8c61f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 2.3.0 + * Some code cleanup thanks to @xi + * Added: MFA_TOTP_FAILURE_WINDOW & MFA_TOTP_FAILURE_LIMIT + ## 2.2.0 * Added: MFA_REDIRECT_AFTER_REGISTRATION settings parameter * Fixed: Deprecation error for NullBooleanField diff --git a/README.md b/README.md index 482b1ab..be85c60 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,9 @@ Depends on MFA_OWNED_BY_ENTERPRISE = FALSE # Who owns security keys TOKEN_ISSUER_NAME="PROJECT_NAME" #TOTP Issuer name - + MFA_TOTP_FAILURE_LIMIT = 3 # Allowed TOTP Failures / user + MFA_TOTP_FAILURE_WINDOW = 5 # The number of minutes to check failed logins against. + U2F_APPID="https://localhost" #URL For U2F FIDO_SERVER_ID=u"localehost" # Server rp id for FIDO2, it the full domain of your project FIDO_SERVER_NAME=u"PROJECT_NAME" @@ -96,6 +98,8 @@ Depends on * Starting version 1.7.0, Key owners can be specified. * Starting version 2.2.0 * Added: `MFA_SUCCESS_REGISTRATION_MSG` & `MFA_REDIRECT_AFTER_REGISTRATION` + * Starting version 2.3.0 + * Added: `MFA_TOTP_FAILURE_LIMIT` & `MFA_TOTP_FAILURE_WINDOW` 1. Break your login function Usually your login function will check for username and password, log the user in if the username and password are correct and create the user session, to support mfa, this has to change diff --git a/example/example/settings.py b/example/example/settings.py index a3fe9f2..920964a 100644 --- a/example/example/settings.py +++ b/example/example/settings.py @@ -86,20 +86,20 @@ DATABASES = { # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", - }, -] +# AUTH_PASSWORD_VALIDATORS = [ +# { +# "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", +# }, +# { +# "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", +# }, +# { +# "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", +# }, +# { +# "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", +# }, +# ] # Internationalization diff --git a/mfa/migrations/0012_rename_user_keys_userkey.py b/mfa/migrations/0012_rename_user_keys_userkey.py index ddf4889..560f22d 100644 --- a/mfa/migrations/0012_rename_user_keys_userkey.py +++ b/mfa/migrations/0012_rename_user_keys_userkey.py @@ -6,12 +6,12 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('mfa', '0011_auto_20210530_0622'), + ("mfa", "0011_auto_20210530_0622"), ] operations = [ migrations.RenameModel( - old_name='User_Keys', - new_name='UserKey', + old_name="User_Keys", + new_name="UserKey", ), ] diff --git a/mfa/migrations/0013_auto_20210624_1505.py b/mfa/migrations/0013_auto_20210624_1505.py new file mode 100644 index 0000000..383a13e --- /dev/null +++ b/mfa/migrations/0013_auto_20210624_1505.py @@ -0,0 +1,35 @@ +# Generated by Django 2.2 on 2021-06-24 15:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("mfa", "0012_rename_user_keys_userkey"), + ] + + operations = [ + migrations.CreateModel( + name="OTPTracker", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("actor", models.CharField(max_length=50)), + ("value", models.CharField(max_length=6)), + ("success", models.BooleanField(blank=True)), + ("done_on", models.DateTimeField(auto_now=True)), + ], + ), + migrations.AddIndex( + model_name="otptracker", + index=models.Index(fields=["actor"], name="mfa_otptrac_usernam_1f423f_idx"), + ), + ] diff --git a/mfa/models.py b/mfa/models.py index ff60416..ac94ac8 100644 --- a/mfa/models.py +++ b/mfa/models.py @@ -33,11 +33,13 @@ class UserKey(models.Model): class OTPTracker(models.Model): - username = models.CharField(max_length=50) - value = models.CharField(max_length = 6) + actor = models.CharField( + max_length=50, help_text="Username" + ) # named this way for indexing purpose. + value = models.CharField(max_length=6) success = models.BooleanField(blank=True) done_on = models.DateTimeField(auto_now=True) class Meta: - app_label = 'mfa' - indexes = [models.Index(fields=['username'])] \ No newline at end of file + app_label = "mfa" + indexes = [models.Index(fields=["actor"])] diff --git a/mfa/templates/TOTP/recheck.html b/mfa/templates/TOTP/recheck.html index 87c5a7c..1a990bf 100644 --- a/mfa/templates/TOTP/recheck.html +++ b/mfa/templates/TOTP/recheck.html @@ -28,7 +28,7 @@ {% csrf_token %} {% if invalid %}