From b7835d189ffdabdf5137d6bbcaa1c56ad2f356a4 Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Tue, 25 Apr 2023 14:27:52 -0600 Subject: [PATCH 1/9] enroll sms factor endpoint created --- .../templates/mfa/enroll_factor_details.html | 2 +- python-django-mfa-example/mfa/urls.py | 1 + python-django-mfa-example/mfa/views.py | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html index 39ad1f0..abb4f53 100644 --- a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html +++ b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html @@ -47,7 +47,7 @@

Enterprise Ready

Enroll SMS Factor

-
+
Date: Tue, 25 Apr 2023 16:19:32 -0600 Subject: [PATCH 2/9] enroll totp factor endpoint created --- .../templates/mfa/enroll_factor_details.html | 63 ++++++++++++++++--- python-django-mfa-example/mfa/urls.py | 1 + python-django-mfa-example/mfa/views.py | 20 ++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html index abb4f53..9726e3d 100644 --- a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html +++ b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html @@ -54,8 +54,8 @@

Enroll SMS Factor

placeholder="Phone Number" required>
-
@@ -64,8 +64,7 @@

Enroll SMS Factor

Enroll TOTP Factor

- - {% csrf_token %} +
Enroll TOTP Factor placeholder="User Email" required>
-
- +
@@ -88,7 +87,57 @@

Enroll TOTP Factor

- + + + \ No newline at end of file diff --git a/python-django-mfa-example/mfa/urls.py b/python-django-mfa-example/mfa/urls.py index 6cd84f1..fcba05d 100644 --- a/python-django-mfa-example/mfa/urls.py +++ b/python-django-mfa-example/mfa/urls.py @@ -11,6 +11,7 @@ ), path("enroll_factor", views.enroll_factor, name="enroll_factor"), path("enroll_sms_factor", views.enroll_sms_factor, name="enroll_sms_factor"), + path("enroll_totp_factor", views.enroll_totp_factor, name="enroll_totp_factor"), path("factor_detail", views.factor_detail, name="factor_detail"), path("challenge_factor", views.challenge_factor, name="challenge_factor"), path("verify_factor", views.verify_factor, name="verify_factor"), diff --git a/python-django-mfa-example/mfa/views.py b/python-django-mfa-example/mfa/views.py index 3b394ec..cbcd8e6 100644 --- a/python-django-mfa-example/mfa/views.py +++ b/python-django-mfa-example/mfa/views.py @@ -3,6 +3,8 @@ from django.conf import settings from django.shortcuts import redirect, render from django.views.decorators.csrf import csrf_exempt +import json +from django.http import JsonResponse workos.api_key = os.getenv("WORKOS_API_KEY") @@ -88,6 +90,24 @@ def enroll_sms_factor(request): return redirect("list_factors") +@csrf_exempt +def enroll_totp_factor(request): + request_data = request.body + json_data = json.loads(request.body.decode('utf-8')) + + totp_type = json_data['type'] + totp_issuer = json_data['issuer'] + totp_user = json_data['user'] + + print(totp_issuer) + print(totp_user) + print(totp_type) + + + response_data = {'message': 'Success'} + return JsonResponse(response_data, status=200) + + def factor_detail(request): factorId = request.GET["id"] for factor in request.session["factor_list"]: From a2589f41a053a4fb058e299766ffe9b64548882f Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Tue, 25 Apr 2023 16:30:17 -0600 Subject: [PATCH 3/9] enroll totp factor --- python-django-mfa-example/mfa/views.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/python-django-mfa-example/mfa/views.py b/python-django-mfa-example/mfa/views.py index cbcd8e6..8b74d92 100644 --- a/python-django-mfa-example/mfa/views.py +++ b/python-django-mfa-example/mfa/views.py @@ -92,17 +92,24 @@ def enroll_sms_factor(request): @csrf_exempt def enroll_totp_factor(request): - request_data = request.body - json_data = json.loads(request.body.decode('utf-8')) + data = json.loads(request.body.decode('utf-8')) - totp_type = json_data['type'] - totp_issuer = json_data['issuer'] - totp_user = json_data['user'] + type = data['type'] + issuer = data['issuer'] + user = data['user'] - print(totp_issuer) - print(totp_user) - print(totp_type) + new_factor = workos.client.mfa.enroll_factor( + type=type, + totp_issuer=issuer, + totp_user=user + ) + + if request.session.get("factor_list"): + request.session["factor_list"].append(new_factor) + else: + request.session["factor_list"] = [new_factor] + print(new_factor) response_data = {'message': 'Success'} return JsonResponse(response_data, status=200) From 51e5a6ee7499815a1e896333770957cf4b3d2e2f Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Tue, 25 Apr 2023 16:55:40 -0600 Subject: [PATCH 4/9] totp factor detaqils updated --- .../templates/mfa/enroll_factor_details.html | 20 ++++++--- .../mfa/templates/mfa/factor_detail.html | 7 --- python-django-mfa-example/mfa/views.py | 43 +------------------ 3 files changed, 16 insertions(+), 54 deletions(-) diff --git a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html index 9726e3d..1185826 100644 --- a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html +++ b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html @@ -51,7 +51,7 @@

Enroll SMS Factor

+ placeholder="Phone Number">
+ class="button button-outline button-sm" disabled>Enroll New Factor
@@ -132,8 +132,16 @@

Enroll TOTP Factor

user: totpUser.value, }) }) - .then(response => response.json()) - .then(response => console.log(response)) + .then(response => response.text()) + .then(qr_code => { + overlay.style.display = "block" + modal.innerHTML = ` +

Scan the QR code

+

Use the authenticator app to scan the QR code. After you scan the code, click 'Continue'.

+ qr_code + Continue + ` + }) }) closeModalBtn.addEventListener("click", function() { overlay.style.display = "none" diff --git a/python-django-mfa-example/mfa/templates/mfa/factor_detail.html b/python-django-mfa-example/mfa/templates/mfa/factor_detail.html index 92e2277..f471585 100644 --- a/python-django-mfa-example/mfa/templates/mfa/factor_detail.html +++ b/python-django-mfa-example/mfa/templates/mfa/factor_detail.html @@ -64,13 +64,6 @@

Factor Details

  • Created At: {{factor.created_at}}
  • Updated At: {{factor.updated_at}}
  • - - - {% if factor.type == 'totp' %} -
    - qr_code -
    - {% endif %} diff --git a/python-django-mfa-example/mfa/views.py b/python-django-mfa-example/mfa/views.py index 8b74d92..389438e 100644 --- a/python-django-mfa-example/mfa/views.py +++ b/python-django-mfa-example/mfa/views.py @@ -4,7 +4,7 @@ from django.shortcuts import redirect, render from django.views.decorators.csrf import csrf_exempt import json -from django.http import JsonResponse +from django.http import HttpResponse workos.api_key = os.getenv("WORKOS_API_KEY") @@ -40,38 +40,6 @@ def enroll_factor_details(request): return render(request, "mfa/enroll_factor_details.html") -@csrf_exempt -def enroll_factor(request): - factor_type = request.POST["type"] - - if factor_type == "sms": - factor_type = "sms" - phone_number = request.POST["phone_number"] - new_factor = workos.client.mfa.enroll_factor( - type=factor_type, phone_number=phone_number - ) - if request.session.get("factor_list"): - request.session["factor_list"].append(new_factor) - else: - request.session["factor_list"] = [new_factor] - - if factor_type == "totp": - factor_type = "totp" - totp_issuer = request.POST["totp_issuer"] - totp_user = request.POST["totp_user"] - new_factor = workos.client.mfa.enroll_factor( - type=factor_type, totp_issuer=totp_issuer, totp_user=totp_user - ) - if request.session.get("factor_list") != None: - new_session_list = request.session["factor_list"] - new_session_list.append(new_factor) - request.session["factor_list"] = new_session_list - else: - request.session["factor_list"] = [new_factor] - - return redirect("list_factors") - - @csrf_exempt def enroll_sms_factor(request): factor_type = request.POST["type"] @@ -109,10 +77,7 @@ def enroll_totp_factor(request): else: request.session["factor_list"] = [new_factor] - print(new_factor) - - response_data = {'message': 'Success'} - return JsonResponse(response_data, status=200) + return HttpResponse(new_factor['totp']['qr_code']) def factor_detail(request): @@ -125,9 +90,6 @@ def factor_detail(request): if factor["type"] == "sms": phone_number = factor["sms"]["phone_number"] - if factor["type"] == "totp": - request.session["current_factor_qr"] = factor["totp"]["qr_code"] - request.session["current_factor"] = fullFactor["id"] request.session["current_factor_type"] = fullFactor["type"] @@ -137,7 +99,6 @@ def factor_detail(request): { "factor": fullFactor, "phone_number": phone_number, - "qr_code": request.session["current_factor_qr"], }, ) From ed96ccd8587feabc78359e68b52e5f88f6a5b34f Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Tue, 25 Apr 2023 16:56:02 -0600 Subject: [PATCH 5/9] enroll factor url removed --- python-django-mfa-example/mfa/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python-django-mfa-example/mfa/urls.py b/python-django-mfa-example/mfa/urls.py index fcba05d..a0eccd8 100644 --- a/python-django-mfa-example/mfa/urls.py +++ b/python-django-mfa-example/mfa/urls.py @@ -9,7 +9,6 @@ views.enroll_factor_details, name="enroll_factor_details", ), - path("enroll_factor", views.enroll_factor, name="enroll_factor"), path("enroll_sms_factor", views.enroll_sms_factor, name="enroll_sms_factor"), path("enroll_totp_factor", views.enroll_totp_factor, name="enroll_totp_factor"), path("factor_detail", views.factor_detail, name="factor_detail"), From cebeaba6deeb993b472962b48d744a7108f752c3 Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Wed, 26 Apr 2023 11:17:12 -0600 Subject: [PATCH 6/9] styles update --- .../mfa/static/css/login.css | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/python-django-mfa-example/mfa/static/css/login.css b/python-django-mfa-example/mfa/static/css/login.css index c24833f..4a3c4d8 100644 --- a/python-django-mfa-example/mfa/static/css/login.css +++ b/python-django-mfa-example/mfa/static/css/login.css @@ -122,7 +122,6 @@ h1 { align-items: center; position: relative; bottom: 10%; - /* background-color: #f9f9fb; */ } .logged_in_div_left { @@ -204,8 +203,7 @@ div.text_box { background-color: #f9f9fb; height: 60px; padding: 15px 30px 15px 30px; - - z-index: 1000; + z-index: 998; } .logged_in_nav p { @@ -274,15 +272,6 @@ pre.prettyprint { margin-bottom: 20px; } -.qr_div { - align-self: center; - padding-top: 15px; -} - -.qr_code { - width: 7vw; - max-width: 100px; -} ul { list-style-type: none; @@ -320,4 +309,44 @@ li.even { .mt-20 { margin-top: 20px; +} + +.overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0,0,0,0.5); + z-index: 999; +} + +.modal { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: #fff; + padding: 25px; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0,0,0,0.5); + z-index: 1000; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.qr_code_instructions { + width: 300px; +} + +.qr_code { + width: 300px; + margin: 25px; +} + +button:disabled { + opacity: 0.5; + pointer-events: none; } \ No newline at end of file From 606f326b0f03bd5edec7d2676c98538f668992fb Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Wed, 26 Apr 2023 12:19:54 -0600 Subject: [PATCH 7/9] remove logo border --- python-django-mfa-example/mfa/static/css/login.css | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python-django-mfa-example/mfa/static/css/login.css b/python-django-mfa-example/mfa/static/css/login.css index 4a3c4d8..2d9a3bf 100644 --- a/python-django-mfa-example/mfa/static/css/login.css +++ b/python-django-mfa-example/mfa/static/css/login.css @@ -214,12 +214,6 @@ div.text_box { .logged_in_nav img { height: 50px; - border-radius: 50%; - border: 2px solid #2f2e2e; -} - -.logged_in_nav img:hover { - border: 2px solid #555555; } .nav-item { From 8b721480fff9e50dd01ae94d903e77d8c5420ae0 Mon Sep 17 00:00:00 2001 From: Edita Ignot Date: Wed, 3 May 2023 12:18:35 -0600 Subject: [PATCH 8/9] save session --- python-django-mfa-example/mfa/views.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/python-django-mfa-example/mfa/views.py b/python-django-mfa-example/mfa/views.py index 389438e..a4b2985 100644 --- a/python-django-mfa-example/mfa/views.py +++ b/python-django-mfa-example/mfa/views.py @@ -55,16 +55,18 @@ def enroll_sms_factor(request): else: request.session["factor_list"] = [new_factor] + request.session.save() + return redirect("list_factors") @csrf_exempt def enroll_totp_factor(request): - data = json.loads(request.body.decode('utf-8')) + data = json.loads(request.body.decode("utf-8")) - type = data['type'] - issuer = data['issuer'] - user = data['user'] + type = data["type"] + issuer = data["issuer"] + user = data["user"] new_factor = workos.client.mfa.enroll_factor( type=type, @@ -77,7 +79,9 @@ def enroll_totp_factor(request): else: request.session["factor_list"] = [new_factor] - return HttpResponse(new_factor['totp']['qr_code']) + request.session.save() + + return HttpResponse(new_factor["totp"]["qr_code"]) def factor_detail(request): From 9628191587d9021afc2f37be2c176e5319e30d7e Mon Sep 17 00:00:00 2001 From: Adam Wolfman Date: Thu, 4 May 2023 10:23:53 -0600 Subject: [PATCH 9/9] Update logo on templates --- .../mfa/templates/mfa/challenge_factor.html | 6 ++---- .../mfa/templates/mfa/enroll_factor_details.html | 5 +---- .../mfa/templates/mfa/factor_detail.html | 5 +---- .../mfa/templates/mfa/list_factors.html | 2 +- .../mfa/templates/mfa/verify_factor.html | 5 +---- 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/python-django-mfa-example/mfa/templates/mfa/challenge_factor.html b/python-django-mfa-example/mfa/templates/mfa/challenge_factor.html index 2a8b8d2..24e3100 100644 --- a/python-django-mfa-example/mfa/templates/mfa/challenge_factor.html +++ b/python-django-mfa-example/mfa/templates/mfa/challenge_factor.html @@ -10,11 +10,9 @@
    - workos logo -
    -
    -

    WorkOS

    + workos logo
    +
    diff --git a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html index 1185826..dfa554d 100644 --- a/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html +++ b/python-django-mfa-example/mfa/templates/mfa/enroll_factor_details.html @@ -10,10 +10,7 @@
    - workos logo -
    -
    -

    WorkOS

    + workos logo
    diff --git a/python-django-mfa-example/mfa/templates/mfa/factor_detail.html b/python-django-mfa-example/mfa/templates/mfa/factor_detail.html index f471585..b4641db 100644 --- a/python-django-mfa-example/mfa/templates/mfa/factor_detail.html +++ b/python-django-mfa-example/mfa/templates/mfa/factor_detail.html @@ -11,10 +11,7 @@
    - workos logo -
    -
    -

    WorkOS

    + workos logo
    diff --git a/python-django-mfa-example/mfa/templates/mfa/list_factors.html b/python-django-mfa-example/mfa/templates/mfa/list_factors.html index 1ae9b3c..a91cb90 100644 --- a/python-django-mfa-example/mfa/templates/mfa/list_factors.html +++ b/python-django-mfa-example/mfa/templates/mfa/list_factors.html @@ -11,7 +11,7 @@
    - workos logo + workos logo
    diff --git a/python-django-mfa-example/mfa/templates/mfa/verify_factor.html b/python-django-mfa-example/mfa/templates/mfa/verify_factor.html index 76b7c10..c4004bf 100644 --- a/python-django-mfa-example/mfa/templates/mfa/verify_factor.html +++ b/python-django-mfa-example/mfa/templates/mfa/verify_factor.html @@ -10,10 +10,7 @@
    - workos logo -
    -
    -

    WorkOS

    + workos logo