Added MFRENAMEMETHOD, MFA_REDIRECT_USER_TO_LAST_METHOD, Alot of theme fixes
This commit is contained in:
@@ -137,7 +137,7 @@ def authenticate_complete(request):
|
||||
except:
|
||||
pass
|
||||
return HttpResponse(simplejson.dumps({'status': "ERR",
|
||||
"message": excep.message}),
|
||||
"message": str(excep)}),
|
||||
content_type = "application/json")
|
||||
|
||||
if request.session.get("mfa_recheck", False):
|
||||
|
||||
@@ -9,6 +9,9 @@ import simplejson
|
||||
import random
|
||||
import string
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
|
||||
USER_FRIENDLY_NAME = "Recovery Codes"
|
||||
|
||||
class Hash(PBKDF2PasswordHasher):
|
||||
algorithm = 'pbkdf2_sha256_custom'
|
||||
@@ -38,6 +41,7 @@ def genTokens(request):
|
||||
hashedKeys.append(hashedToken)
|
||||
clearKeys.append(token)
|
||||
uk=User_Keys()
|
||||
|
||||
uk.username = request.user.username
|
||||
uk.properties={"secret_keys":hashedKeys, "salt":salt}
|
||||
uk.key_type="RECOVERY"
|
||||
@@ -51,10 +55,11 @@ def verify_login(request, username, token):
|
||||
secret_keys = key.properties["secret_keys"]
|
||||
salt = key.properties["salt"]
|
||||
hashedToken = make_password(token, salt, "pbkdf2_sha256_custom")
|
||||
for i in range(len(secret_keys)):
|
||||
if hashedToken == secret_keys[i]:
|
||||
for i,token in enumerate(secret_keys):
|
||||
if hashedToken == token:
|
||||
secret_keys.pop(i)
|
||||
key.properties["secret_keys"] = secret_keys
|
||||
key.last_used= timezone.now()
|
||||
key.save()
|
||||
return [True, key.id, len(secret_keys) == 0]
|
||||
return [False]
|
||||
@@ -89,10 +94,10 @@ def auth(request):
|
||||
resBackup=verify_login(request, request.session["base_username"], token=request.POST["recovery"])
|
||||
if resBackup[0]:
|
||||
mfa = {"verified": True, "method": "RECOVERY","id":resBackup[1], "lastBackup":resBackup[2]}
|
||||
if getattr(settings, "MFA_RECHECK", False):
|
||||
mfa["next_check"] = datetime.datetime.timestamp((datetime.datetime.now()
|
||||
+ datetime.timedelta(
|
||||
seconds=random.randint(settings.MFA_RECHECK_MIN, settings.MFA_RECHECK_MAX))))
|
||||
# if getattr(settings, "MFA_RECHECK", False):
|
||||
# mfa["next_check"] = datetime.datetime.timestamp((datetime.datetime.now()
|
||||
# + datetime.timedelta(
|
||||
# seconds=random.randint(settings.MFA_RECHECK_MIN, settings.MFA_RECHECK_MAX))))
|
||||
request.session["mfa"] = mfa
|
||||
if resBackup[2]:
|
||||
#If the last bakup code has just been used, we return a response insead of redirecting to login
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<script type="application/javascript" src="{% static 'mfa/js/ua-parser.min.js' %}"></script>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
|
||||
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2 offset-2 col-8">
|
||||
<div class="panel panel-default card">
|
||||
<div class="panel-heading card-header">
|
||||
<strong> Security Key</strong>
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-3" style="padding-left: 15px">
|
||||
<div class="col-md-12 mb-3" style="padding-left: 25px">
|
||||
|
||||
{% if request.session.mfa_methods|length > 1 %}
|
||||
<a href="{% url 'mfa_methods_list' %}">Select Another Method</a>
|
||||
|
||||
@@ -45,31 +45,31 @@
|
||||
<br/>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div align="center">
|
||||
<div class="offset-5 col-2" style="text-align: center">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-success dropdown-toggle" data-toggle="dropdown" data-bs-toggle="dropdown">
|
||||
Add Method <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if not 'TOTP' in UNALLOWED_AUTHEN_METHODS %}
|
||||
<li><a class="dropdown-item" href="{% url 'start_new_otop' %}">Authenticator app</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'start_new_otop' %}">{% if 'TOTP' in RENAME_METHODS.keys %}{{ RENAME_METHODS.TOTP }}{% else %}Authenticator app{% endif %}</a></li>
|
||||
{% endif %}
|
||||
{% if not 'Email' in UNALLOWED_AUTHEN_METHODS %}
|
||||
<li><a class="dropdown-item" href="{% url 'start_email' %}">Email Token</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'start_email' %}">{% if 'Email' in RENAME_METHODS.keys %}{{ RENAME_METHODS.Email }}{% else %}Email Token{% endif %}</a></li>
|
||||
{% endif %}
|
||||
{% if not 'U2F' in UNALLOWED_AUTHEN_METHODS %}
|
||||
<li><a class="dropdown-item" href="{% url 'start_u2f' %}">Security Key</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'start_u2f' %}">{% if 'U2F' in RENAME_METHODS.keys %}{{ RENAME_METHODS.U2F }}{% else %}Security Key{% endif %}</a></li>
|
||||
{% endif %}
|
||||
{% if not 'FIDO2' in UNALLOWED_AUTHEN_METHODS %}
|
||||
<li><a class="dropdown-item" href="{% url 'start_fido2' %}">FIDO2 Security Key</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'start_fido2' %}">{% if 'FIDO2' in RENAME_METHODS.keys %}{{ RENAME_METHODS.FIDO2 }}{% else %}FIDO2 Security Key{% endif %}</a></li>
|
||||
{% endif %}
|
||||
{% if not 'Trusted_Devices' in UNALLOWED_AUTHEN_METHODS %}
|
||||
<li><a class="dropdown-item" href="{% url 'start_td' %}">Trusted Device</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'start_td' %}">{% if 'Trusted_Devices' in RENAME_METHODS.keys %}{{ RENAME_METHODS.Trusted_Devices }}{% else %}Trusted Device{% endif %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
@@ -86,11 +86,11 @@
|
||||
{% for key in keys %}
|
||||
<tr>
|
||||
|
||||
<td>{{ key.key_type }}</td>
|
||||
<td>{{ key.name }}</td>
|
||||
<td>{{ key.added_on }}</td>
|
||||
<td>{{ key.expires }}</td>
|
||||
<td>{% if key.expires %}{{ key.expires }}{% else %}N/A{% endif %}</td>
|
||||
<td>{% if key.device %}{{ key.device }}{% endif %}</td>
|
||||
<td>{{ key.last_used }}</td>
|
||||
<td>{% if key.last_used %}{{ key.last_used }}{% else %}Never{% endif %}</td>
|
||||
{% if key.key_type in HIDE_DISABLE %}
|
||||
<td>{% if key.enabled %}On{% else %} Off{% endif %}</td>
|
||||
{% else %}
|
||||
@@ -106,11 +106,11 @@
|
||||
{% if "RECOVERY" not in UNALLOWED_AUTHEN_METHODS %}
|
||||
<tr>
|
||||
|
||||
<td>RECOVERY</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>{{ recovery.name }}</td>
|
||||
<td>{{ recovery.added_on }}</td>
|
||||
<td>N/A</td>
|
||||
<td>N/A</td>
|
||||
<td>{% if recovery.last_used %}{{ recovery.last_used }}{% else %}Never{% endif %}</td>
|
||||
<td>On</td>
|
||||
<td><a href="{% url 'manage_recovery_codes' %}"> <span class="fa fa-wrench fa-solid fa-wrench bi bi-wrench-fill"></span></a></td>
|
||||
</tr>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{% extends "mfa_auth_base.html" %}
|
||||
{% block content %}
|
||||
<br/>
|
||||
<br/>
|
||||
<div class='container'>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
|
||||
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2 offset-2 col-8">
|
||||
<div class="panel panel-default card">
|
||||
<div class="panel-heading card-header">
|
||||
<strong> Select Second Verification Method</strong>
|
||||
@@ -15,11 +14,11 @@
|
||||
{% for method in request.session.mfa_methods %}
|
||||
|
||||
<li><a href="{% url "mfa_goto" method %}">
|
||||
{% if method == "TOTP" %}Authenticator App
|
||||
{% elif method == "Email" %}Send OTP by Email
|
||||
{% elif method == "U2F" %}Secure Key
|
||||
{% elif method == "FIDO2" %}FIDO2 Secure Key
|
||||
{% elif method == "RECOVERY" %}Recovery Code
|
||||
{% if method == "TOTP" %}{% if 'TOTP' in RENAME_METHODS %}{{ RENAME_METHODS.TOTP }}{% else %}Authenticator App{% endif %}
|
||||
{% elif method == "Email" %}{% if 'Email' in RENAME_METHODS %}{{ RENAME_METHODS.Email }}{% else %}Send OTP by Email{% endif %}
|
||||
{% elif method == "U2F" %}{% if 'U2F' in RENAME_METHODS %}{{ RENAME_METHODS.U2F }}{% else %}Secure Key{% endif %}
|
||||
{% elif method == "FIDO2" %}{% if 'FIDO2' in RENAME_METHODS %}{{ RENAME_METHODS.FIDO2 }}{% else %}FIDO2 Secure Key{% endif %}
|
||||
{% elif method == "RECOVERY" %}{% if 'RECOVERY' in RENAME_METHODS %}{{ RENAME_METHODS.RECOVERY }}{% else %}Recovery Code{% endif %}
|
||||
{% endif %}
|
||||
</a> </li>
|
||||
{% endfor %}
|
||||
|
||||
13
mfa/views.py
13
mfa/views.py
@@ -1,3 +1,5 @@
|
||||
import importlib
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponse,HttpResponseRedirect
|
||||
from .models import *
|
||||
@@ -16,13 +18,15 @@ from user_agents import parse
|
||||
def index(request):
|
||||
keys=[]
|
||||
context={"keys":User_Keys.objects.filter(username=request.user.username),"UNALLOWED_AUTHEN_METHODS":settings.MFA_UNALLOWED_METHODS
|
||||
,"HIDE_DISABLE":getattr(settings,"MFA_HIDE_DISABLE",[])}
|
||||
,"HIDE_DISABLE":getattr(settings,"MFA_HIDE_DISABLE",[]),'RENAME_METHODS':getattr(settings,'MFA_RENAME_METHODS',{})}
|
||||
for k in context["keys"]:
|
||||
if k.key_type =="Trusted Device" :
|
||||
k.name = getattr(settings,'MFA_RENAME_METHODS',{}).get(k.key_type,k.key_type)
|
||||
if k.key_type =="Trusted Device":
|
||||
setattr(k,"device",parse(k.properties.get("user_agent","-----")))
|
||||
elif k.key_type == "FIDO2":
|
||||
setattr(k,"device",k.properties.get("type","----"))
|
||||
elif k.key_type == "RECOVERY":
|
||||
context["recovery"] = k
|
||||
continue
|
||||
keys.append(k)
|
||||
context["keys"]=keys
|
||||
@@ -42,10 +46,13 @@ def verify(request,username):
|
||||
|
||||
if len(methods)==1:
|
||||
return HttpResponseRedirect(reverse(methods[0].lower()+"_auth"))
|
||||
if getattr(settings,"MFA_ALWAYS_GO_TO_LAST_METHOD",False):
|
||||
keys = keys.exclude(last_used__isnull=True).order_by("last_used")
|
||||
return HttpResponseRedirect(reverse(keys[0].key_type.lower() + "_auth"))
|
||||
return show_methods(request)
|
||||
|
||||
def show_methods(request):
|
||||
return render(request,"select_mfa_method.html", {})
|
||||
return render(request,"select_mfa_method.html", {'RENAME_METHODS':getattr(settings,'MFA_RENAME_METHODS',{})})
|
||||
|
||||
def reset_cookie(request):
|
||||
response=HttpResponseRedirect(settings.LOGIN_URL)
|
||||
|
||||
Reference in New Issue
Block a user