From b9f06f8d9c3930d2d44fb5c4b128e0ae09d8176b Mon Sep 17 00:00:00 2001 From: Mohamed El-Kalioby Date: Thu, 20 Jun 2019 21:13:05 +0300 Subject: [PATCH] Adding Example app --- example/example/auth.py | 14 +- example/example/settings.py | 27 +- example/example/templates/base.html | 156 ++++ example/example/templates/home.html | 149 +--- example/example/templates/mfa_auth_base.html | 45 ++ .../templates/mfa_email_token_template.html | 2 + example/example/urls.py | 3 +- example/requiremnts.txt | 1 + .../static/mfa/css/bootstrap-toggle.min.css | 28 + example/static/mfa/js/bootstrap-toggle.min.js | 9 + example/static/mfa/js/cbor.js | 406 ++++++++++ example/static/mfa/js/qrious.min.js | 6 + example/static/mfa/js/u2f-api.js | 751 ++++++++++++++++++ mfa/Email.py | 7 +- mfa/totp.py | 2 +- mfa/urls.py | 84 +- mfa/views.py | 3 +- requirements.txt | 11 + 18 files changed, 1510 insertions(+), 194 deletions(-) create mode 100644 example/example/templates/base.html create mode 100644 example/example/templates/mfa_auth_base.html create mode 100644 example/example/templates/mfa_email_token_template.html create mode 100644 example/static/mfa/css/bootstrap-toggle.min.css create mode 100644 example/static/mfa/js/bootstrap-toggle.min.js create mode 100644 example/static/mfa/js/cbor.js create mode 100644 example/static/mfa/js/qrious.min.js create mode 100644 example/static/mfa/js/u2f-api.js create mode 100644 requirements.txt diff --git a/example/example/auth.py b/example/example/auth.py index 9bc0a47..afd587b 100644 --- a/example/example/auth.py +++ b/example/example/auth.py @@ -2,6 +2,7 @@ from django.shortcuts import render from django.http import HttpResponseRedirect from django.urls import reverse from django.contrib.auth import authenticate,login,logout +from django.contrib.auth.models import User def loginView(request): context={} if request.method=="POST": @@ -9,11 +10,20 @@ def loginView(request): password=request.POST["password"] user=authenticate(username=username,password=password) if user: - login(request,user) - return HttpResponseRedirect(reverse('home')) + from mfa.helpers import has_mfa + res = has_mfa(username = username, request = request) # has_mfa returns false or HttpResponseRedirect + if res: + return res + return create_session(request,user.username) context["invalid"]=True return render(request, "login.html", context) +def create_session(request,username): + user=User.objects.get(username=username) + user.backend='django.contrib.auth.backends.ModelBackend' + login(request, user) + return HttpResponseRedirect(reverse('home')) + def logoutView(request): logout(request) diff --git a/example/example/settings.py b/example/example/settings.py index 00f5028..98300ce 100644 --- a/example/example/settings.py +++ b/example/example/settings.py @@ -37,6 +37,8 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'mfa', + 'sslserver' ] MIDDLEWARE = [ @@ -120,4 +122,27 @@ USE_TZ = True STATIC_URL = '/static/' #STATIC_ROOT=(os.path.join(BASE_DIR,'static')) STATICFILES_DIRS=[os.path.join(BASE_DIR,'static')] -LOGIN_URL="/auth/login" \ No newline at end of file +LOGIN_URL="/auth/login" + +EMAIL_FROM='Test App' +EMAIL_HOST="smtp.gmail.com" +EMAIL_PORT=587 +EMAIL_HOST_USER="mkalioby@gmail.com" +EMAIL_HOST_PASSWORD='wanted85' +EMAIL_USE_TLS=True + + + +MFA_UNALLOWED_METHODS=() # Methods that shouldn't be allowed for the user +MFA_LOGIN_CALLBACK="example.auth.create_session" # A function that should be called by username to login the user in session +MFA_RECHECK=True # Allow random rechecking of the user +MFA_RECHECK_MIN=10 # Minimum interval in seconds +MFA_RECHECK_MAX=30 # Maximum in seconds +MFA_QUICKLOGIN=True # Allow quick login for returning users by provide only their 2FA +MFA_HIDE_DISABLE=('FIDO2',) # Can the user disable his key (Added in 1.2.0). + +TOKEN_ISSUER_NAME="PROJECT_NAME" #TOTP Issuer name + +U2F_APPID="https://localhost" #URL For U2F +FIDO_SERVER_ID=u"localhost" # Server rp id for FIDO2, it the full domain of your project +FIDO_SERVER_NAME=u"PROJECT_NAME" diff --git a/example/example/templates/base.html b/example/example/templates/base.html new file mode 100644 index 0000000..786d08b --- /dev/null +++ b/example/example/templates/base.html @@ -0,0 +1,156 @@ +{% load static %} + + + + + + + + + + + + SB Admin - Blank Page + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ + + {% block content %} + {% endblock %} + +
+ + + +
+
+ +
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + {% block head %} + {% endblock %} + + + diff --git a/example/example/templates/home.html b/example/example/templates/home.html index 52bfd5f..b76df9e 100644 --- a/example/example/templates/home.html +++ b/example/example/templates/home.html @@ -1,96 +1,6 @@ +{% extends 'base.html' %} {% load static %} - - - - - - - - - - - - SB Admin - Blank Page - - - - - - - - - - - - - - - - -
- - - - -
- +{% block content %}
@@ -106,57 +16,4 @@
- - - -
-
- -
-
- -
- - -
- - - - - - - - - - - - - - - - - - - - - - - + {% endblock %} \ No newline at end of file diff --git a/example/example/templates/mfa_auth_base.html b/example/example/templates/mfa_auth_base.html new file mode 100644 index 0000000..5c54b02 --- /dev/null +++ b/example/example/templates/mfa_auth_base.html @@ -0,0 +1,45 @@ +{% load static %} + + + + + + + + + + + + Login + + + + + + + + + + + + +
+ +
+ + + + + + + {% block head %} + {% endblock %} + + + diff --git a/example/example/templates/mfa_email_token_template.html b/example/example/templates/mfa_email_token_template.html new file mode 100644 index 0000000..d0133b9 --- /dev/null +++ b/example/example/templates/mfa_email_token_template.html @@ -0,0 +1,2 @@ +

Dear {{ user.username }}

+Your OTP is: {{ otp }} \ No newline at end of file diff --git a/example/example/urls.py b/example/example/urls.py index f6600d8..3691a81 100644 --- a/example/example/urls.py +++ b/example/example/urls.py @@ -14,10 +14,11 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path,re_path +from django.urls import path,re_path,include from . import views,auth urlpatterns = [ path('admin/', admin.site.urls), + path('mfa/', include('mfa.urls')), path('auth/login',auth.loginView,name="login"), path('auth/logout',auth.logoutView,name="logout"), diff --git a/example/requiremnts.txt b/example/requiremnts.txt index 144884d..9a1fda4 100644 --- a/example/requiremnts.txt +++ b/example/requiremnts.txt @@ -1 +1,2 @@ django==2.0 +django-sslserver diff --git a/example/static/mfa/css/bootstrap-toggle.min.css b/example/static/mfa/css/bootstrap-toggle.min.css new file mode 100644 index 0000000..0d42ed0 --- /dev/null +++ b/example/static/mfa/css/bootstrap-toggle.min.css @@ -0,0 +1,28 @@ +/*! ======================================================================== + * Bootstrap Toggle: bootstrap-toggle.css v2.2.0 + * http://www.bootstraptoggle.com + * ======================================================================== + * Copyright 2014 Min Hur, The New York Times Company + * Licensed under MIT + * ======================================================================== */ +.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px} +.toggle{position:relative;overflow:hidden} +.toggle input[type=checkbox]{display:none} +.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none} +.toggle.off .toggle-group{left:-100%} +.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0} +.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0} +.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px} +.toggle.btn{min-width:59px;min-height:34px} +.toggle-on.btn{padding-right:24px} +.toggle-off.btn{padding-left:24px} +.toggle.btn-lg{min-width:79px;min-height:45px} +.toggle-on.btn-lg{padding-right:31px} +.toggle-off.btn-lg{padding-left:31px} +.toggle-handle.btn-lg{width:40px} +.toggle.btn-sm{min-width:50px;min-height:30px} +.toggle-on.btn-sm{padding-right:20px} +.toggle-off.btn-sm{padding-left:20px} +.toggle.btn-xs{min-width:35px;min-height:22px} +.toggle-on.btn-xs{padding-right:12px} +.toggle-off.btn-xs{padding-left:12px} \ No newline at end of file diff --git a/example/static/mfa/js/bootstrap-toggle.min.js b/example/static/mfa/js/bootstrap-toggle.min.js new file mode 100644 index 0000000..3711320 --- /dev/null +++ b/example/static/mfa/js/bootstrap-toggle.min.js @@ -0,0 +1,9 @@ +/*! ======================================================================== + * Bootstrap Toggle: bootstrap-toggle.js v2.2.0 + * http://www.bootstraptoggle.com + * ======================================================================== + * Copyright 2014 Min Hur, The New York Times Company + * Licensed under MIT + * ======================================================================== */ ++function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('