Compare commits
1 Commits
passwordle
...
v2.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a154cfa34 |
@@ -1,7 +1,8 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## 2.2.0 (Not released)
|
## 2.2.0
|
||||||
* Added: MFA_REDIRECT_AFTER_REGISTRATION settings parameter
|
* Added: MFA_REDIRECT_AFTER_REGISTRATION settings parameter
|
||||||
|
* Fixed: Deprecation error for NULBooleanField
|
||||||
|
|
||||||
## 2.1.2
|
## 2.1.2
|
||||||
* Fixed: Getting timestamp on Python 3.7 as ("%s") is raising an exception
|
* Fixed: Getting timestamp on Python 3.7 as ("%s") is raising an exception
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
## 2.1.1
|
## 2.1.1
|
||||||
* Fixed: FIDO2 version in requirments.txt file.
|
* Fixed: FIDO2 version in requirements.txt file.
|
||||||
|
|
||||||
## 2.1.0
|
## 2.1.0
|
||||||
* Added Support for Touch ID for Mac OSx and iOS 14 on Safari
|
* Added Support for Touch ID for Mac OSx and iOS 14 on Safari
|
||||||
|
|||||||
@@ -28,7 +28,3 @@ def create_session(request,username):
|
|||||||
def logoutView(request):
|
def logoutView(request):
|
||||||
logout(request)
|
logout(request)
|
||||||
return render(request,"logout.html",{})
|
return render(request,"logout.html",{})
|
||||||
|
|
||||||
def register(request):
|
|
||||||
if request.method == "GET":
|
|
||||||
return
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<!-- Custom styles for this template-->
|
<!-- Custom styles for this template-->
|
||||||
<link href="{% static 'css/sb-admin.css'%}" rel="stylesheet">
|
<link href="{% static 'css/sb-admin.css'%}" rel="stylesheet">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-dark">
|
<body class="bg-dark">
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
{% if invalid %}
|
{% if invalid %}
|
||||||
<div class="alert alert-danger">Invalid Username or password</div>
|
<div class="alert alert-danger">Invalid Username or password</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<form action="{% url 'login' %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
@@ -35,9 +37,14 @@
|
|||||||
<label for="inputUsername">Username</label>
|
<label for="inputUsername">Username</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-label-group">
|
||||||
|
<input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required="required">
|
||||||
|
<label for="inputPassword">Password</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-primary btn-block" type="submit">Login</button>
|
||||||
<button class="btn btn-primary btn-block" type="button" onclick="authen()">Login</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,7 +56,7 @@
|
|||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
<!-- Core plugin JavaScript-->
|
||||||
<script src="{% static 'vendor/jquery-easing/jquery.easing.min.js'%}"></script>
|
<script src="{% static 'vendor/jquery-easing/jquery.easing.min.js'%}"></script>
|
||||||
{% include 'FIDO2/login.html' %}
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ def start(request):
|
|||||||
"""Start Registeration a new FIDO Token"""
|
"""Start Registeration a new FIDO Token"""
|
||||||
context = csrf(request)
|
context = csrf(request)
|
||||||
context.update(get_redirect_url())
|
context.update(get_redirect_url())
|
||||||
context["mfa_invoke"] = True
|
|
||||||
return render(request, "FIDO2/Add.html", context)
|
return render(request, "FIDO2/Add.html", context)
|
||||||
|
|
||||||
|
|
||||||
@@ -98,8 +97,8 @@ def auth(request):
|
|||||||
|
|
||||||
def authenticate_begin(request):
|
def authenticate_begin(request):
|
||||||
server = getServer()
|
server = getServer()
|
||||||
#credentials = getUserCredentials(request.session.get("base_username", request.user.username))
|
credentials = getUserCredentials(request.session.get("base_username", request.user.username))
|
||||||
auth_data, state = server.authenticate_begin()
|
auth_data, state = server.authenticate_begin(credentials)
|
||||||
request.session['fido_state'] = state
|
request.session['fido_state'] = state
|
||||||
return HttpResponse(cbor.encode(auth_data), content_type = "application/octet-stream")
|
return HttpResponse(cbor.encode(auth_data), content_type = "application/octet-stream")
|
||||||
|
|
||||||
@@ -108,7 +107,7 @@ def authenticate_begin(request):
|
|||||||
def authenticate_complete(request):
|
def authenticate_complete(request):
|
||||||
try:
|
try:
|
||||||
credentials = []
|
credentials = []
|
||||||
username = request.session.get("base_username", request.POST.get("username",request.user.username))
|
username = request.session.get("base_username", request.user.username)
|
||||||
server = getServer()
|
server = getServer()
|
||||||
credentials = getUserCredentials(username)
|
credentials = getUserCredentials(username)
|
||||||
data = cbor.decode(request.body)
|
data = cbor.decode(request.body)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__="2.2.0b1"
|
__version__="2.2.0"
|
||||||
|
|||||||
18
mfa/migrations/0011_auto_20210530_0622.py
Normal file
18
mfa/migrations/0011_auto_20210530_0622.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2 on 2021-05-30 06:22
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mfa', '0010_auto_20201110_0557'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user_keys',
|
||||||
|
name='owned_by_enterprise',
|
||||||
|
field=models.BooleanField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -15,7 +15,7 @@ class User_Keys(models.Model):
|
|||||||
enabled=models.BooleanField(default=True)
|
enabled=models.BooleanField(default=True)
|
||||||
expires=models.DateTimeField(null=True,default=None,blank=True)
|
expires=models.DateTimeField(null=True,default=None,blank=True)
|
||||||
last_used=models.DateTimeField(null=True,default=None,blank=True)
|
last_used=models.DateTimeField(null=True,default=None,blank=True)
|
||||||
owned_by_enterprise=models.NullBooleanField(default=None,null=True,blank=True)
|
owned_by_enterprise=models.BooleanField(default=None,null=True,blank=True)
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||||
if self.key_type == "Trusted Device" and self.properties.get("signature","") == "":
|
if self.key_type == "Trusted Device" and self.properties.get("signature","") == "":
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
{% load static %}
|
|
||||||
<script type="application/javascript" src="{% static 'mfa/js/cbor.js' %}"></script>
|
|
||||||
<script type="application/javascript" src="{% static 'mfa/js/ua-parser.min.js' %}"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
function authen()
|
|
||||||
{
|
|
||||||
fetch('{% url 'fido2_begin_auth' %}', {
|
|
||||||
method: 'GET',
|
|
||||||
}).then(function(response) {
|
|
||||||
if(response.ok) return response.arrayBuffer();
|
|
||||||
throw new Error('No credential available to authenticate!');
|
|
||||||
}).then(CBOR.decode).then(function(options) {
|
|
||||||
console.log(options)
|
|
||||||
return navigator.credentials.get(options);
|
|
||||||
}).then(function(assertion) {
|
|
||||||
res=CBOR.encode({
|
|
||||||
"credentialId": new Uint8Array(assertion.rawId),
|
|
||||||
"authenticatorData": new Uint8Array(assertion.response.authenticatorData),
|
|
||||||
"clientDataJSON": new Uint8Array(assertion.response.clientDataJSON),
|
|
||||||
"signature": new Uint8Array(assertion.response.signature)
|
|
||||||
});
|
|
||||||
|
|
||||||
return fetch('{% url 'fido2_complete_auth' %}', {
|
|
||||||
|
|
||||||
method: 'POST',
|
|
||||||
headers: {'Content-Type': 'application/cbor'},
|
|
||||||
body:res,
|
|
||||||
|
|
||||||
}).then(function (response) {if (response.ok) return res = response.json()}).then(function (res) {
|
|
||||||
if (res.status=="OK")
|
|
||||||
{
|
|
||||||
$("#msgdiv").addClass("alert alert-success").removeClass("alert-danger")
|
|
||||||
$("#msgdiv").html("Verified....please wait")
|
|
||||||
{% if mode == "auth" %}
|
|
||||||
window.location.href=res.redirect;
|
|
||||||
{% elif mode == "recheck" %}
|
|
||||||
mfa_success_function();
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#msgdiv").addClass("alert alert-danger").removeClass("alert-success")
|
|
||||||
$("#msgdiv").html("Verification Failed as " + res.message + ", <a href='javascript:void(0)' onclick='authen())'> try again</a> or <a href='javascript:void(0)' onclick='history.back()'> Go Back</a>")
|
|
||||||
|
|
||||||
{% if mode == "auth" %}
|
|
||||||
|
|
||||||
{% elif mode == "recheck" %}
|
|
||||||
|
|
||||||
mfa_failed_function();
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
$(document).ready(function () {
|
|
||||||
if (location.protocol != 'https:') {
|
|
||||||
$("#main_paragraph").addClass("alert alert-danger")
|
|
||||||
$("#main_paragraph").html("FIDO2 must work under secure context")
|
|
||||||
} else {
|
|
||||||
{% if mfa_invoke %}
|
|
||||||
ua=new UAParser().getResult()
|
|
||||||
if (ua.browser.name == "Safari")
|
|
||||||
$("#res").html("<button class='btn btn-success' onclick='authen()'>Authenticate...</button>")
|
|
||||||
else
|
|
||||||
authen()
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{% include 'FIDO2/fido2_auth.html' %}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
{% load static %}
|
||||||
|
<script type="application/javascript" src="{% static 'mfa/js/cbor.js' %}"></script>
|
||||||
|
<script type="application/javascript" src="{% static 'mfa/js/ua-parser.min.js' %}"></script>
|
||||||
<div class="row">
|
<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">
|
||||||
@@ -45,4 +47,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include 'FIDO2/fido2_auth.html' %}
|
<script type="text/javascript">
|
||||||
|
function authen()
|
||||||
|
{
|
||||||
|
fetch('{% url 'fido2_begin_auth' %}', {
|
||||||
|
method: 'GET',
|
||||||
|
}).then(function(response) {
|
||||||
|
if(response.ok) return response.arrayBuffer();
|
||||||
|
throw new Error('No credential available to authenticate!');
|
||||||
|
}).then(CBOR.decode).then(function(options) {
|
||||||
|
console.log(options)
|
||||||
|
return navigator.credentials.get(options);
|
||||||
|
}).then(function(assertion) {
|
||||||
|
res=CBOR.encode({
|
||||||
|
"credentialId": new Uint8Array(assertion.rawId),
|
||||||
|
"authenticatorData": new Uint8Array(assertion.response.authenticatorData),
|
||||||
|
"clientDataJSON": new Uint8Array(assertion.response.clientDataJSON),
|
||||||
|
"signature": new Uint8Array(assertion.response.signature)
|
||||||
|
});
|
||||||
|
|
||||||
|
return fetch('{% url 'fido2_complete_auth' %}', {
|
||||||
|
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/cbor'},
|
||||||
|
body:res,
|
||||||
|
|
||||||
|
}).then(function (response) {if (response.ok) return res = response.json()}).then(function (res) {
|
||||||
|
if (res.status=="OK")
|
||||||
|
{
|
||||||
|
$("#msgdiv").addClass("alert alert-success").removeClass("alert-danger")
|
||||||
|
$("#msgdiv").html("Verified....please wait")
|
||||||
|
{% if mode == "auth" %}
|
||||||
|
window.location.href=res.redirect;
|
||||||
|
{% elif mode == "recheck" %}
|
||||||
|
mfa_success_function();
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#msgdiv").addClass("alert alert-danger").removeClass("alert-success")
|
||||||
|
$("#msgdiv").html("Verification Failed as " + res.message + ", <a href='javascript:void(0)' onclick='authen())'> try again</a> or <a href='javascript:void(0)' onclick='history.back()'> Go Back</a>")
|
||||||
|
|
||||||
|
{% if mode == "auth" %}
|
||||||
|
|
||||||
|
{% elif mode == "recheck" %}
|
||||||
|
|
||||||
|
mfa_failed_function();
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
$(document).ready(function () {
|
||||||
|
if (location.protocol != 'https:') {
|
||||||
|
$("#main_paragraph").addClass("alert alert-danger")
|
||||||
|
$("#main_paragraph").html("FIDO2 must work under secure context")
|
||||||
|
} else {
|
||||||
|
ua=new UAParser().getResult()
|
||||||
|
if (ua.browser.name == "Safari")
|
||||||
|
$("#res").html("<button class='btn btn-success' onclick='authen()'>Authenticate...</button>")
|
||||||
|
else
|
||||||
|
authen()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
6
setup.py
6
setup.py
@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='django-mfa2',
|
name='django-mfa2',
|
||||||
version='2.2.0b2 ',
|
version='2.2.0',
|
||||||
description='Allows user to add 2FA to their accounts',
|
description='Allows user to add 2FA to their accounts',
|
||||||
long_description=open("README.md").read(),
|
long_description=open("README.md").read(),
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
@@ -31,12 +31,14 @@ setup(
|
|||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
zip_safe=False, # because we're including static files
|
zip_safe=False, # because we're including static files
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"Environment :: Web Environment",
|
"Environment :: Web Environment",
|
||||||
"Framework :: Django",
|
"Framework :: Django",
|
||||||
"Framework :: Django :: 2.0",
|
"Framework :: Django :: 2.0",
|
||||||
"Framework :: Django :: 2.1",
|
"Framework :: Django :: 2.1",
|
||||||
"Framework :: Django :: 2.2",
|
"Framework :: Django :: 2.2",
|
||||||
|
"Framework :: Django :: 3.0",
|
||||||
|
"Framework :: Django :: 3.1",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
|
|||||||
Reference in New Issue
Block a user