Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time-based One Time Passwords #256

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
documentation and cleaned up comments
jasonehines committed Jan 15, 2019

Verified

This commit was signed with the committer’s verified signature.
jasonehines Jason Hines
commit 39bc0bf833439a55043d53109f2db35b95de32e3
11 changes: 11 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
@@ -71,3 +71,14 @@ These tokens are used in the following places:
:no-undoc-members:

.. seealso:: :ref:`Customizing the TokenManager <CustomizingManagers>`.

--------

.. _TOTPManager:

TOTPManager class
-----------------

The TOTPManager generates and verifies Time-based One Time Passwords.

.. autoclass:: flask_user.totp_manager.TOTPManager
33 changes: 33 additions & 0 deletions docs/source/api_forms.rst
Original file line number Diff line number Diff line change
@@ -27,6 +27,17 @@ ChangeUsernameForm

--------

.. _DisableTOTPForm:

DisableTOTPForm
---------------

.. autoclass:: flask_user.forms.DisableTOTPForm
:no-undoc-members:
:no-inherited-members:

--------

.. _EditUserProfileForm:

EditUserProfileForm
@@ -38,6 +49,17 @@ EditUserProfileForm

--------

.. _EnableTOTPForm:

EnableTOTPForm
--------------

.. autoclass:: flask_user.forms.EnableTOTPForm
:no-undoc-members:
:no-inherited-members:

--------

.. _ForgotPasswordForm:

ForgotPasswordForm
@@ -101,3 +123,14 @@ ResetPasswordForm
.. autoclass:: flask_user.forms.ResetPasswordForm
:no-undoc-members:
:no-inherited-members:

--------

.. _VerifyTOTPTokenForm:

VerifyTOTPTokenForm
-------------------

.. autoclass:: flask_user.forms.VerifyTOTPTokenForm
:no-undoc-members:
:no-inherited-members:
12 changes: 9 additions & 3 deletions docs/source/base_templates.rst
Original file line number Diff line number Diff line change
@@ -19,8 +19,9 @@ Public forms are forms that do not require a logged-in user:
* ``templates/flask_user/login.html``,
* ``templates/flask_user/login_or_register.html``,
* ``templates/flask_user/register.html``,
* ``templates/flask_user/request_email_confirmation.html``, and
* ``templates/flask_user/reset_password.html``.
* ``templates/flask_user/request_email_confirmation.html``,
* ``templates/flask_user/reset_password.html``, and
* ``tempates/flask_user/verify_totp_token.html``.

Public forms extend the template file ``templates/flask_user/_public_base.html``,
which by default extends the template file ``templates/base.html``.
@@ -36,7 +37,9 @@ create the ``templates/flask_user/_public_base.html`` file in your application's
Member forms are forms that require a logged-in user:

* ``templates/flask_user/change_password.html``,
* ``templates/flask_user/change_username.html``, and
* ``templates/flask_user/change_username.html``,
* ``tempates/flask_user/disable_totp.html``,
* ``tempates/flask_user/enable_totp.html``, and
* ``templates/flask_user/manage_emails.html``.

Member forms extend the template file ``templates/flask_user/_authorized_base.html``,
@@ -57,6 +60,8 @@ The following template files reside in the ``templates`` directory::
flask_user/_authorized_base.html # extends base.html
flask_user/change_password.html # extends flask_user/_authorized_base.html
flask_user/change_username.html # extends flask_user/_authorized_base.html
flask_user/disable_totp.html # extends flask_user/_authorized_base.html
flask_user/enable_totp.html # extends flask_user/_authorized_base.html
flask_user/manage_emails.html # extends flask_user/_authorized_base.html

flask_user/_public_base.html # extends base.html
@@ -66,3 +71,4 @@ The following template files reside in the ``templates`` directory::
flask_user/register.html # extends flask_user/_public_base.html
flask_user/request_email_confirmation.html # extends flask_user/_public_base.html
flask_user/reset_password.html # extends flask_user/_public_base.html
flask_user/verify_totp_token.html # extends flask_user/_public_base.html
2 changes: 1 addition & 1 deletion flask_user/totp_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""This module implements the TOTPManager for Flask-User.
It uses onetimepass to generate URI and verify OTP tokens.
It generates the users URI and uses onetimepass to verify TOTP tokens.
"""

# Adapted from https://blog.miguelgrinberg.com/post/two-factor-authentication-with-flask
12 changes: 5 additions & 7 deletions flask_user/user_manager__views.py
Original file line number Diff line number Diff line change
@@ -401,7 +401,6 @@ def login_view(self):
safe_next_url = self.make_safe_url(login_form.next.data)
remember_me = login_form.remember_me.data
return redirect(url_for('user.verify_totp_token') +'?next='+quote(safe_next_url) + '&remember_me=' + str(remember_me))
#return self.verify_totp_token_view(safe_next_url, remember_me)
else:
# Log user in
safe_next_url = self.make_safe_url(login_form.next.data)
@@ -453,7 +452,6 @@ def refresh_login_view(self):
safe_next_url = self.make_safe_url(login_form.next.data)
remember_me = login_form.remember_me.data
return redirect(url_for('user.verify_totp_token') +'?next='+quote(safe_next_url) + '&remember_me=' + str(remember_me))
#return self.verify_totp_token_view(safe_next_url, remember_me)
else:
# Log user in
safe_next_url = self.make_safe_url(login_form.next.data)
@@ -668,10 +666,10 @@ def reset_password_view(self, token):
return render_template(self.USER_RESET_PASSWORD_TEMPLATE, form=form)



# Require a fresh login to ensure that it is the user
@fresh_login_required
def enable_totp_view(self):
""" Display QR code and require validation."""
""" Display QR code and require validation of TOTP token."""

# Generate a new secret if it was never verified
if current_user.totp_secret is None and not current_user.totp_verified:
@@ -704,10 +702,10 @@ def enable_totp_view(self):
return render_template(self.USER_ENABLE_TOTP_TEMPLATE, form=form)



# Require a fresh login to ensure that it is the user
@fresh_login_required
def disable_totp_view(self):
""" Disable Time-based One Time Password for user """
""" Disable Time-based One Time Password for user."""
print("Fresh Login: " + str(login_fresh()))

form = self.DisableTOTPTokenFormClass(request.form)
@@ -729,7 +727,7 @@ def disable_totp_view(self):


def verify_totp_token_view(self):
""" Verify TOTP Token """
""" Verify TOTP Token."""

# Get the user_id from the session and get user from the db
totp_user_id = session['totp_user_id']