From ab632e107d9020da13138c5e6c6849130ccfd68e Mon Sep 17 00:00:00 2001 From: deflax Date: Fri, 5 Apr 2024 18:05:27 +0300 Subject: [PATCH] show otp secret --- src/forest/auth/routes.py | 10 ++++++---- src/forest/models.py | 3 +++ src/forest/requirements.txt | 2 +- src/forest/templates/auth/already_confirmed.html | 5 ++--- src/forest/templates/auth/qrcode.html | 3 +++ 5 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 src/forest/templates/auth/qrcode.html diff --git a/src/forest/auth/routes.py b/src/forest/auth/routes.py index 4d347dd..cefc5ca 100644 --- a/src/forest/auth/routes.py +++ b/src/forest/auth/routes.py @@ -1,5 +1,6 @@ from flask import render_template, redirect, request, url_for, flash, session, abort, current_app from flask_login import login_required, login_user, logout_user, current_user +from markupsafe import Markup, escape from . import auth from .forms import LoginForm, TwoFAForm, RegistrationForm, ChangePasswordForm, PasswordResetRequestForm, PasswordResetForm @@ -60,7 +61,6 @@ def login(): session['memberberry'] = form.remember_me.data return redirect(url_for('auth.twofactor')) - #print('remember: ' + str(form.remember_me.data)) login_user(user, form.remember_me.data) previp = user.last_ip if request.headers.getlist("X-Forwarded-For"): @@ -71,7 +71,6 @@ def login(): db.session.add(user) db.session.commit() send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip ) - #flash('Last Login: {} from {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"), previp)) flash('Last Login: {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"))) return redirect(request.args.get('next') or url_for('panel.dashboard')) else: @@ -126,8 +125,11 @@ def qrcode(): url = pyqrcode.create(current_user.get_totp_uri()) stream = BytesIO() url.svg(stream, scale=6) - return stream.getvalue(), 200, { - 'Content-Type': 'image/svg+xml', + svg_secret = Markup(stream.getvalue().decode('utf-8')) + otp_secret = current_user.get_otp_secret() + # since this page contains the sensitive qrcode, make sure the browser + # does not cache it + return render_template('auth/qrcode.html', svg=svg_secret, otp=otp_secret), 200, { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0'} diff --git a/src/forest/models.py b/src/forest/models.py index 48cc675..c4ac321 100644 --- a/src/forest/models.py +++ b/src/forest/models.py @@ -120,6 +120,9 @@ class User(db.Model, UserMixin): def get_totp_uri(self): return 'otpauth://totp/DataPanel:{0}?secret={1}&issuer=datapanel'.format(self.email, self.otp_secret) + def get_otp_secret(self): + return self.otp_secret + def verify_totp(self, token): return onetimepass.valid_totp(token, self.otp_secret) diff --git a/src/forest/requirements.txt b/src/forest/requirements.txt index 88e467b..14ea6ac 100644 --- a/src/forest/requirements.txt +++ b/src/forest/requirements.txt @@ -23,4 +23,4 @@ Werkzeug email_validator iso3166 psycopg2-binary -alembic \ No newline at end of file +alembic diff --git a/src/forest/templates/auth/already_confirmed.html b/src/forest/templates/auth/already_confirmed.html index 1f7b742..2776e8c 100644 --- a/src/forest/templates/auth/already_confirmed.html +++ b/src/forest/templates/auth/already_confirmed.html @@ -5,12 +5,11 @@ {% block page_content %} diff --git a/src/forest/templates/auth/qrcode.html b/src/forest/templates/auth/qrcode.html new file mode 100644 index 0000000..0927b25 --- /dev/null +++ b/src/forest/templates/auth/qrcode.html @@ -0,0 +1,3 @@ +{{ svg }} + +{{ otp }}