Skip to content

Commit 03f1e1d

Browse files
authored
Pull in opr #842 - 2-factor auth (#86)
* docs: release date and block fixes * i18n: added Chinese-Simple translation * Update messages.po change language from 'zh_Hans_CN' to 'zh_CN' * rename nl_NL/LC_MESSAGES/messages.po and zh_Hans_CN/LC_MESSAGES/messages.po * Security two factor authentication feature * supporting two factor authentication: * Support Mail, SMS, or Google Authenticator second factor authentication. * Ability to change second factor authentication to existing users * Provide rescue mail in case of lost phone * update docs with two factor authentication changes * updating requirements, authors * adding two_factor test * improving tests coverage * fix double import and unused import, revert get_user * fix missing setup.py install_requires * fix TestMail (remove __init_) * formatting * more formatting * too many blank lines * formatting forms.py * signals line length * twofactor formatting * utils formatting * update twilio client import * missing import * blueprint line length (twofactor) * line too long/import/authors inadv. deleted * conftest.py allow nulls in sqlalchemy * Spelling, Update Functions and Tests Python 3.7 Support request.json->request.get_json update tests to use hash_password pep8 compliance Update dependencies for tests move from pyenchant to msgcheck * Update docs/configuration.rst Co-Authored-By: malware-watch <[email protected]> * consistent two-factor * .gitignore .venv/ * fixes. passlib.totp, if not request.is_json * translation stubs for new messages * Make two-factor login more JSON friendly * feature - merge in two factor auth. These changes are mostly docs and cleanup. * remove pyqrcode, onetimepass from install requires check imports if TWO_FACTOR is True * Minor doc fixes. Increase sizes of examples for 2FA phone and secret. * whitespace * feature - merge in two factor auth. These changes are mostly docs and cleanup. * Fix formatting.
1 parent a1f27a0 commit 03f1e1d

32 files changed

+1489
-64
lines changed

.gitignore

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pip-log.txt
2828

2929
#Virtualenv
3030
env/
31+
.venv/
3132

3233
#Editor temporaries
3334
*~
@@ -45,8 +46,11 @@ Session.vim
4546

4647
.eggs/README.txt
4748

48-
# Idea
49-
.idea/
50-
5149
# Mac
5250
.DS_Store
51+
52+
# Pycharm files
53+
.idea/
54+
55+
# VScode
56+
.vscode/

AUTHORS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,6 @@ Walt Askew
4646
John Paraskevopoulos
4747
Chris Wagner
4848
Eric Regnier
49+
Gal Stainfeld
50+
Ivan Piskunov
51+
Tyler Baur

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Released TBD
1919
- (:pr:`73`) Fix get_user for various DBs (jwag956).
2020
This is a more complete fix than in opr #633.
2121
- (:pr:`78`) Add formal openapi API spec (jwag956).
22+
- (:pr:`86`) Add Two-factor authentication (opr #842) (baurt).
2223

2324
Version 3.1.0
2425
-------------

docs/api.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ Utils
9898

9999
.. autofunction:: flask_security.utils.transform_url
100100

101+
.. autoclass:: flask_security.utils.SmsSenderBaseClass
102+
:members: send_sms
103+
104+
.. autoclass:: flask_security.utils.SmsSenderFactory
105+
:members: createSender
106+
101107
Signals
102108
-------
103109
See the `Flask documentation on signals`_ for information on how to use these
@@ -142,5 +148,14 @@ sends the following signals.
142148
Sent when a user requests a password reset. In addition to the app (which is
143149
the sender), it is passed `user` and `token` arguments.
144150

151+
.. data:: user_two_factored
152+
153+
Sent when a user performs two-factor authentication login on the site. In
154+
addition to the app (which is the sender), it is passed `user` argument
155+
156+
.. data:: two_factor_method_changed
157+
158+
Sent when two-factor is used and user logs in. In addition to the app
159+
(which is the sender), it is passed `user` argument.
145160

146161
.. _Flask documentation on signals: http://flask.pocoo.org/docs/signals/

docs/configuration.rst

Lines changed: 105 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ Core
6363
to ``MAIL_DEFAULT_SENDER`` if
6464
Flask-Mail is used otherwise
6565
``no-reply@localhost``.
66+
``SECURITY_TWO_FACTOR_RESCUE_MAIL`` Specifies the email address users send
67+
mail to when they can't complete the
68+
two-factor authentication login.
69+
Defaults to ``no-reply@localhost``.
6670
``SECURITY_TOKEN_AUTHENTICATION_KEY`` Specifies the query string parameter to
6771
read when using token authentication.
6872
Defaults to ``auth_token``.
@@ -187,31 +191,45 @@ Template Paths
187191

188192
.. tabularcolumns:: |p{6.5cm}|p{8.5cm}|
189193

190-
======================================== =======================================
191-
``SECURITY_FORGOT_PASSWORD_TEMPLATE`` Specifies the path to the template for
192-
the forgot password page. Defaults to
193-
``security/forgot_password.html``.
194-
``SECURITY_LOGIN_USER_TEMPLATE`` Specifies the path to the template for
195-
the user login page. Defaults to
196-
``security/login_user.html``.
197-
``SECURITY_REGISTER_USER_TEMPLATE`` Specifies the path to the template for
198-
the user registration page. Defaults to
199-
``security/register_user.html``.
200-
``SECURITY_RESET_PASSWORD_TEMPLATE`` Specifies the path to the template for
201-
the reset password page. Defaults to
202-
``security/reset_password.html``.
203-
``SECURITY_CHANGE_PASSWORD_TEMPLATE`` Specifies the path to the template for
204-
the change password page. Defaults to
205-
``security/change_password.html``.
206-
``SECURITY_SEND_CONFIRMATION_TEMPLATE`` Specifies the path to the template for
207-
the resend confirmation instructions
208-
page. Defaults to
209-
``security/send_confirmation.html``.
210-
``SECURITY_SEND_LOGIN_TEMPLATE`` Specifies the path to the template for
211-
the send login instructions page for
212-
passwordless logins. Defaults to
213-
``security/send_login.html``.
214-
======================================== =======================================
194+
============================================== =======================================
195+
``SECURITY_FORGOT_PASSWORD_TEMPLATE`` Specifies the path to the template for
196+
the forgot password page. Defaults to
197+
``security/forgot_password.html``.
198+
``SECURITY_LOGIN_USER_TEMPLATE`` Specifies the path to the template for
199+
the user login page. Defaults to
200+
``security/login_user.html``.
201+
``SECURITY_REGISTER_USER_TEMPLATE`` Specifies the path to the template for
202+
the user registration page. Defaults to
203+
``security/register_user.html``.
204+
``SECURITY_RESET_PASSWORD_TEMPLATE`` Specifies the path to the template for
205+
the reset password page. Defaults to
206+
``security/reset_password.html``.
207+
``SECURITY_CHANGE_PASSWORD_TEMPLATE`` Specifies the path to the template for
208+
the change password page. Defaults to
209+
``security/change_password.html``.
210+
``SECURITY_SEND_CONFIRMATION_TEMPLATE`` Specifies the path to the template for
211+
the resend confirmation instructions
212+
page. Defaults to
213+
``security/send_confirmation.html``.
214+
``SECURITY_SEND_LOGIN_TEMPLATE`` Specifies the path to the template for
215+
the send login instructions page for
216+
passwordless logins. Defaults to
217+
``security/send_login.html``.
218+
``SECURITY_TWO_FACTOR_VERIFY_CODE_TEMPLATE`` Specifies the path to the template for
219+
the verify code page for the two-factor
220+
authentication process. Defaults to
221+
``security/two_factor_verify_code.html``.
222+
223+
``SECURITY_TWO_FACTOR_CHOOSE_METHOD_TEMPLATE`` Specifies the path to the template for
224+
the choose method page for the two
225+
factor authentication process. Defaults
226+
to ``security/two_factor_choose_method.html``
227+
``SECURITY_TWO_FACTOR_CHANGE_METHOD_TEMPLATE`` Specifies the path to the template for
228+
the change method page for the two
229+
factor authentication process. Defaults
230+
to ``security/two_factor_change_method_password_confirmation.html``.
231+
232+
============================================== =======================================
215233

216234

217235
Feature Flags
@@ -251,6 +269,15 @@ Feature Flags
251269
change password endpoint. The URL for this endpoint is
252270
specified by the ``SECURITY_CHANGE_URL`` configuration
253271
option. Defaults to ``False``.
272+
``SECURITY_TWO_FACTOR`` Specifies if Flask-Security should enable the
273+
two-factor login feature. If set to ``True``, in
274+
addition to their passwords, users will be required to
275+
enter a code that is sent to them. The added feature
276+
includes the ability to send it either via email, sms
277+
message, or Google Authenticator. Default time of
278+
validity is 30 seconds in Google Authenticator and up
279+
to 60 seconds if sent by mail or sms.
280+
Defaults to ``False``.
254281
========================= ======================================================
255282

256283
Email
@@ -286,6 +313,12 @@ Email
286313
``SECURITY_EMAIL_HTML`` Sends email as HTML using
287314
``*.html`` template. Defaults
288315
to ``True``.
316+
``SECURITY_EMAIL_SUBJECT_TWO_FACTOR`` Sets the subject for the two
317+
factor feature. Defaults to
318+
``Two-factor Login``
319+
``SECURITY_EMAIL_SUBJECT_TWO_FACTOR_RESCUE`` Sets the subject for the two
320+
factor help function. Defaults
321+
to ``Two-factor Rescue``
289322
================================================= ==============================
290323

291324
Miscellaneous
@@ -327,6 +360,28 @@ Miscellaneous
327360
enabled. Always pluralized the
328361
time unit for this value.
329362
Defaults to ``1 days``.
363+
``SECURITY_TWO_FACTOR_GOOGLE_AUTH_VALIDITY`` Specifies the number of time
364+
windows user has before the token
365+
generated for him using google
366+
authenticator is valid. time
367+
windows specifies the amount of
368+
time, which is 30 seconds for each
369+
window. Default to 0, which is up
370+
to 30 seconds.
371+
``SECURITY_TWO_FACTOR_MAIL_VALIDITY`` Specifies the number of time
372+
windows user has before the token
373+
sent to him using mail is valid.
374+
time windows specifies the amount
375+
of time, which is 30 seconds for
376+
each window. Default to 1, which
377+
is up to 60 seconds.
378+
``SECURITY_TWO_FACTOR_SMS_VALIDITY`` Specifies the number of time
379+
windows user has before the token
380+
sent to him using sms is valid.
381+
time windows specifies the amount
382+
of time, which is 30 seconds for
383+
each window. Default to 5, which
384+
is up to 3 minutes. .
330385
``SECURITY_LOGIN_WITHOUT_CONFIRMATION`` Specifies if a user may login
331386
before confirming their email when
332387
the value of
@@ -352,6 +407,24 @@ Miscellaneous
352407
``SECURITY_DEFAULT_REMEMBER_ME`` Specifies the default "remember
353408
me" value used when logging in
354409
a user. Defaults to ``False``.
410+
``SECURITY_TWO_FACTOR_ENABLED_METHODS`` Specifies the default enabled
411+
methods for two-factor
412+
authentication. defaults to
413+
``['mail', 'google_authenticator',
414+
'sms']`` which are the only
415+
supported method at the moment.
416+
``SECURITY_TWO_FACTOR_URI_SERVICE_NAME`` Specifies the name of the service
417+
or application that the user is
418+
authenticating to. Defaults to
419+
``service_name``
420+
``SECURITY_TWO_FACTOR_SMS_SERVICE`` Specifies the name of the sms
421+
service provider. Defaults to
422+
``Dummy`` which does nothing.
423+
``SECURITY_TWO_FACTOR_SMS_SERVICE_CONFIG`` Specifies a dictionary of basic
424+
configurations needed for use of a
425+
sms service. Defaults to
426+
``{'ACCOUNT_ID': NONE, 'AUTH_TOKEN
427+
':NONE, 'PHONE_NUMBER': NONE}``
355428
``SECURITY_DATETIME_FACTORY`` Specifies the default datetime
356429
factory. Defaults to
357430
``datetime.datetime.utcnow``.
@@ -396,5 +469,12 @@ The default messages and error levels can be found in ``core.py``.
396469
* ``SECURITY_MSG_PASSWORD_RESET_REQUEST``
397470
* ``SECURITY_MSG_REFRESH``
398471
* ``SECURITY_MSG_RETYPE_PASSWORD_MISMATCH``
472+
* ``SECURITY_MSG_TWO_FACTOR_INVALID_TOKEN``
473+
* ``SECURITY_MSG_TWO_FACTOR_LOGIN_SUCCESSFUL``
474+
* ``SECURITY_MSG_TWO_FACTOR_CHANGE_METHOD_SUCCESSFUL``
475+
* ``SECURITY_MSG_TWO_FACTOR_PASSWORD_CONFIRMATION_DONE``
476+
* ``SECURITY_MSG_TWO_FACTOR_PASSWORD_CONFIRMATION_NEEDED``
477+
* ``SECURITY_MSG_TWO_FACTOR_PERMISSION_DENIED``
478+
* ``SECURITY_MSG_TWO_FACTOR_METHOD_NOT_AVAILABLE``
399479
* ``SECURITY_MSG_UNAUTHORIZED``
400480
* ``SECURITY_MSG_USER_DOES_NOT_EXIST``

docs/contents.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Contents
99
quickstart
1010
models
1111
customizing
12+
two_factor_configurations
1213
api
1314
changelog
1415
authors

docs/customizing.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ following is a list of view templates:
2121
* `security/change_password.html`
2222
* `security/send_confirmation.html`
2323
* `security/send_login.html`
24+
* `security/two_factor_change_method_password_confirmation.html`
25+
* `security/two_factor_choose_method.html`
26+
* `security/two_factor_verify_code.html`
2427

2528
Overriding these templates is simple:
2629

@@ -61,6 +64,8 @@ The following is a list of all the available context processor decorators:
6164
* ``change_password_context_processor``: Change password view
6265
* ``send_confirmation_context_processor``: Send confirmation view
6366
* ``send_login_context_processor``: Send login view
67+
* ``two_factor_setup_context_processor``: Two factor setup view
68+
* ``two_factor_token_validation_context_processor``: Two factor token validation view
6469

6570

6671
Forms
@@ -103,7 +108,10 @@ The following is a list of all the available form overrides:
103108
* ``change_password_form``: Change password form
104109
* ``send_confirmation_form``: Send confirmation form
105110
* ``passwordless_login_form``: Passwordless login form
106-
111+
* ``two_factor_verify_code_form``: Two-factor code form
112+
* ``two_factor_setup_form``: Two-factor setup form
113+
* ``two_factor_change_method_verify_password_form``: Two-factor password form
114+
* ``two_factor_rescue_form``: Two-factor help user form
107115

108116
Emails
109117
------
@@ -124,6 +132,10 @@ The following is a list of email templates:
124132
* `security/email/reset_notice.txt`
125133
* `security/email/welcome.html`
126134
* `security/email/welcome.txt`
135+
* `security/email/two_factor_instructions.html`
136+
* `security/email/two_factor_instructions.txt`
137+
* `security/email/two_factor_rescue.html`
138+
* `security/email/two_factor_rescue.txt`
127139

128140
Overriding these templates is simple:
129141

docs/features.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ Thus if the user changes his or her password their existing authentication token
6161
will become invalid. A new token will need to be retrieved using the user's new
6262
password.
6363

64+
Two-factor Authentication (experimental)
65+
----------------------------------------
66+
Two-factor authentication is enabled by generating time-based one time passwords
67+
(Tokens). The tokens are generated using the users totp secret, which is unique
68+
per user, and is generated both on first login, and when changing the two-factor
69+
method.(Doing this causes the previous totp secret to become invalid) The token
70+
is provided by one of 3 methods - email, sms (service is not provided), or
71+
Google Authenticator. By default, tokens provided by google authenticator are
72+
valid for 30 seconds, tokens sent by mail for up to 1 minute and tokens sent by
73+
sms for up to 3 minutes. The QR code used to supply Google Authenticator with
74+
the secret is generated using the PyQRCode library.
75+
This feature is marked experimental meaning that backwards incompatible changes
76+
might occur during minor releases. While the feature is operational, it has these
77+
known limitations:
78+
79+
* Limited and incomplete JSON support
80+
* Incomplete i18n support
81+
* Not enough documentation to use w/o looking at code
6482

6583
Email Confirmation
6684
------------------
@@ -118,6 +136,8 @@ JSON is supported for the following operations:
118136
* Confirmation requests
119137
* Forgot password requests
120138
* Passwordless login requests
139+
* Two-factor login requests
140+
* Change two-factor method requests
121141

122142
In addition, Single-Page-Applications (like those built with Vue, Angular, and
123143
React) are supported via customizable redirect links.
@@ -137,3 +157,5 @@ Run ``flask --help`` and look for users and roles.
137157
.. _documentation on this topic: http://packages.python.org/Flask-Principal/#granular-resource-protection
138158
.. _passlib: http://packages.python.org/passlib/
139159
.. _bcrypt: https://en.wikipedia.org/wiki/Bcrypt
160+
.. _onetimepass: https://pypi.python.org/pypi/onetimepass/
161+
.. _PyQRCode: https://pypi.python.org/pypi/PyQRCode/

docs/index.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ Flask application. They include:
1111
5. Token based authentication
1212
6. Token based account activation (optional)
1313
7. Token based password recovery / resetting (optional)
14-
8. User registration (optional)
15-
9. Login tracking (optional)
16-
10. JSON/Ajax Support
14+
8. Two-factor authentication (optional)
15+
9. User registration (optional)
16+
10. Login tracking (optional)
17+
11. JSON/Ajax Support
1718

1819
Many of these features are made possible by integrating various Flask extensions
1920
and libraries. They include:
@@ -24,6 +25,8 @@ and libraries. They include:
2425
4. `Flask-WTF <http://packages.python.org/Flask-WTF/>`_
2526
5. `itsdangerous <http://packages.python.org/itsdangerous/>`_
2627
6. `passlib <http://packages.python.org/passlib/>`_
28+
7. `onetimepass <https://pypi.python.org/pypi/onetimepass/>`_
29+
8. `PyQRCode <https://pypi.python.org/pypi/PyQRCode/>`_
2730

2831
Additionally, it assumes you'll be using a common library for your database
2932
connections and model definitions. Flask-Security supports the following Flask

docs/models.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ your `User` and `Role` model should include the following fields:
1515
* ``password``
1616
* ``active``
1717

18+
1819
**Role**
1920

2021
* ``id``
@@ -74,3 +75,17 @@ serializable object:
7475
'name': self.name,
7576
'email': self.email
7677
}
78+
79+
Two_Factor
80+
^^^^^^^^^^
81+
82+
If you enable two-factor by setting your application's `TWO_FACTOR`
83+
configuration value to `True`, your `User` model will require the following
84+
additional fields:
85+
86+
* ``totp_secret``
87+
* ``two_factor_primary_method``
88+
89+
If you include 'sms' in SECURITY_TWO_FACTOR_ENABLED_METHOD, your `User` model
90+
will require the following additional field:
91+
* ``phone_number``

0 commit comments

Comments
 (0)