Controlling TOTP Authetication
This commit is contained in:
@@ -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",
|
||||
),
|
||||
]
|
||||
|
||||
35
mfa/migrations/0013_auto_20210624_1505.py
Normal file
35
mfa/migrations/0013_auto_20210624_1505.py
Normal file
@@ -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"),
|
||||
),
|
||||
]
|
||||
@@ -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'])]
|
||||
app_label = "mfa"
|
||||
indexes = [models.Index(fields=["actor"])]
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{% csrf_token %}
|
||||
{% if invalid %}
|
||||
<div class="alert alert-danger">
|
||||
Sorry, The provided token is not valid.
|
||||
{{ invalid_msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if quota %}
|
||||
|
||||
29
mfa/totp.py
29
mfa/totp.py
@@ -16,17 +16,34 @@ from .views import login
|
||||
|
||||
|
||||
def verify_login(request, username, token):
|
||||
FAILURE_LIMIT = getattr("settings", "MFA_TOTP_FAILURE_LIMIT", 3)
|
||||
start_time = timezone.now() + datetime.timedelta(
|
||||
minutes=-1 * getattr(settings, "MFA_TOTP_FAILURE_WINDOW", 5)
|
||||
)
|
||||
if (
|
||||
OTPTracker.objects.filter(
|
||||
done_on__gt=start_time, actor=username, success=0
|
||||
).count()
|
||||
>= FAILURE_LIMIT
|
||||
):
|
||||
return [
|
||||
False,
|
||||
"Using this method is temporarily suspended on your account, use another method, or later again later ",
|
||||
]
|
||||
for key in UserKey.objects.filter(username=username, key_type="TOTP"):
|
||||
totp = pyotp.TOTP(key.properties["secret_key"])
|
||||
if totp.verify(token, valid_window=30):
|
||||
if OTPTracker.objects.filter(username=username, value=token).exists():
|
||||
return [False, "Used Before, please generate another token"]
|
||||
TOTP_Tracker.objects.create(username=username,value=token, success=True)
|
||||
if OTPTracker.objects.filter(actor=username, value=token).exists():
|
||||
return [
|
||||
False,
|
||||
"This code is used before, please generate another token",
|
||||
]
|
||||
OTPTracker.objects.create(actor=username, value=token, success=True)
|
||||
key.last_used = timezone.now()
|
||||
key.save()
|
||||
return [True, key.id]
|
||||
TOTP_Tracker.objects.create(username = username, value = token, success = False)
|
||||
return [False,"Invalid Token"]
|
||||
OTPTracker.objects.create(actor=username, value=token, success=False)
|
||||
return [False, "Invalid Token"]
|
||||
|
||||
|
||||
def recheck(request):
|
||||
@@ -68,7 +85,7 @@ def auth(request):
|
||||
return render(request, "TOTP/Auth.html", context)
|
||||
|
||||
|
||||
def getToken(request):
|
||||
def get_token(request):
|
||||
secret_key = pyotp.random_base32()
|
||||
totp = pyotp.TOTP(secret_key)
|
||||
request.session["new_mfa_answer"] = totp.now()
|
||||
|
||||
Reference in New Issue
Block a user