Flask Security
Flask Security
Release 1.7.4
Matt Wright
Contents
Contents
ii
Flask-Security allows you to quickly add common security mechanisms to your Flask application. They include:
1. Session based authentication
2. Role management
3. Password encryption
4. Basic HTTP authentication
5. Token based authentication
6. Token based account activation (optional)
7. Token based password recovery / resetting (optional)
8. User registration (optional)
9. Login tracking (optional)
10. JSON/Ajax Support
Many of these features are made possible by integrating various Flask extensions and libraries. They include:
1. Flask-Login
2. Flask-Mail
3. Flask-Principal
4. Flask-Script
5. Flask-WTF
6. itsdangerous
7. passlib
Additionally, it assumes youll be using a common library for your database connections and model definitions. FlaskSecurity supports the following Flask extensions out of the box for data persistence:
1. Flask-SQLAlchemy
2. Flask-MongoEngine
3. Flask-Peewee
Contents
Contents
CHAPTER 1
Contents
1.1 Features
Flask-Security allows you to quickly add common security mechanisms to your Flask application. They include:
Chapter 1. Contents
1.2 Configuration
The following configuration values are used by Flask-Security:
1.2.1 Core
Specifies the name for the Flask-Security blueprint. Defaults
to security.
SECURITY_URL_PREFIX
Specifies the URL prefix for the Flask-Security blueprint.
Defaults to None.
SECURITY_FLASH_MESSAGES
Specifies whether or not to flash messages during security
procedures. Defaults to True.
SECURITY_PASSWORD_HASH
Specifies the password hash algorithm to use when encrypting and decrypting passwords. Recommended values
for production systems are bcrypt, sha512_crypt, or
pbkdf2_sha512. Defaults to plaintext.
SECURITY_PASSWORD_SALT
Specifies the HMAC salt. This is only used if the password
hash type is set to something other than plain text. Defaults
to None.
SECURITY_EMAIL_SENDER
Specifies the email address to send emails as. Defaults to
no-reply@localhost.
SECURITY_TOKEN_AUTHENTICATION_KEYSpecifies the query sting parameter to read when using token
authentication. Defaults to auth_token.
SECURITY_TOKEN_AUTHENTICATION_HEADER
Specifies the HTTP header to read when using token authentication. Defaults to Authentication-Token.
SECURITY_DEFAULT_HTTP_AUTH_REALM Specifies the default authentication realm when using basic
HTTP auth. Defaults to Login Required
SECURITY_BLUEPRINT_NAME
1.2. Configuration
SECURITY_POST_LOGOUT_VIEW
SECURITY_CONFIRM_ERROR_VIEW
SECURITY_POST_REGISTER_VIEW
SECURITY_POST_CONFIRM_VIEW
SECURITY_POST_RESET_VIEW
SECURITY_POST_CHANGE_VIEW
SECURITY_UNAUTHORIZED_VIEW
Chapter 1. Contents
SECURITY_REGISTERABLE
SECURITY_RECOVERABLE
SECURITY_TRACKABLE
SECURITY_PASSWORDLESS
SECURITY_CHANGEABLE
1.2. Configuration
1.2.5 Email
Sets the subject for the confirmation email. Defaults to
Welcome
SECURITY_EMAIL_SUBJECT_PASSWORDLESS
Sets the subject for the passwordless feature. Defaults to
Login instructions
SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE
Sets subject for the password notice. Defaults to Your
password has been reset
SECURITY_EMAIL_SUBJECT_PASSWORD_RESET
Sets the subject for the password reset email. Defaults to
Password reset instructions
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE
Sets the subject for the password change notice. Defaults to
Your password has been changed
SECURITY_EMAIL_SUBJECT_CONFIRM
Sets the subject for the email confirmation message. Defaults
to Please confirm your email
SECURITY_EMAIL_SUBJECT_REGISTER
1.2.6 Miscellaneous
Specifies whether registration email is sent. Defaults to
True.
SECURITY_SEND_PASSWORD_CHANGE_EMAIL
Specifies whether password change email is sent. Defaults to
True.
SECURITY_SEND_PASSWORD_RESET_NOTICE_EMAIL
Specifies whether password reset notice email is sent. Defaults to True.
SECURITY_CONFIRM_EMAIL_WITHIN
Specifies the amount of time a user has before their confirmation link expires. Always pluralized the time unit for this
value. Defaults to 5 days.
SECURITY_RESET_PASSWORD_WITHIN
Specifies the amount of time a user has before their password
reset link expires. Always pluralized the time unit for this
value. Defaults to 5 days.
SECURITY_LOGIN_WITHIN
Specifies the amount of time a user has before a login link expires. This is only used when the passwordless login feature
is enabled. Always pluralized the time unit for this value.
Defaults to 1 days.
SECURITY_LOGIN_WITHOUT_CONFIRMATION
Specifies if a user may login before confirming their email
when the value of SECURITY_CONFIRMABLE is set to
True. Defaults to False.
SECURITY_CONFIRM_SALT
Specifies the salt value when generating confirmation
links/tokens. Defaults to confirm-salt.
SECURITY_RESET_SALT
Specifies the salt value when generating password reset
links/tokens. Defaults to reset-salt.
SECURITY_LOGIN_SALT
Specifies the salt value when generating login links/tokens.
Defaults to login-salt.
SECURITY_REMEMBER_SALT
Specifies the salt value when generating remember tokens.
Remember tokens are used instead of user IDs as it is more
secure. Defaults to remember-salt.
SECURITY_DEFAULT_REMEMBER_ME
Specifies the default remember me value used when logging in a user. Defaults to False.
SECURITY_SEND_REGISTER_EMAIL
Chapter 1. Contents
1.2.7 Messages
The following are the messages Flask-Security uses. They are tuples; the first element is the message and the second
element is the error level.
The default messages and error levels can be found in core.py.
SECURITY_MSG_ALREADY_CONFIRMED
SECURITY_MSG_CONFIRMATION_EXPIRED
SECURITY_MSG_CONFIRMATION_REQUEST
SECURITY_MSG_CONFIRMATION_REQUIRED
SECURITY_MSG_CONFIRM_REGISTRATION
SECURITY_MSG_DISABLED_ACCOUNT
SECURITY_MSG_EMAIL_ALREADY_ASSOCIATED
SECURITY_MSG_EMAIL_CONFIRMED
SECURITY_MSG_EMAIL_NOT_PROVIDED
SECURITY_MSG_INVALID_CONFIRMATION_TOKEN
SECURITY_MSG_INVALID_EMAIL_ADDRESS
SECURITY_MSG_INVALID_LOGIN_TOKEN
SECURITY_MSG_INVALID_PASSWORD
SECURITY_MSG_INVALID_REDIRECT
SECURITY_MSG_INVALID_RESET_PASSWORD_TOKEN
SECURITY_MSG_LOGIN
SECURITY_MSG_LOGIN_EMAIL_SENT
SECURITY_MSG_LOGIN_EXPIRED
SECURITY_MSG_PASSWORDLESS_LOGIN_SUCCESSFUL
SECURITY_MSG_PASSWORD_CHANGE
SECURITY_MSG_PASSWORD_INVALID_LENGTH
SECURITY_MSG_PASSWORD_IS_THE_SAME
SECURITY_MSG_PASSWORD_MISMATCH
SECURITY_MSG_PASSWORD_NOT_PROVIDED
SECURITY_MSG_PASSWORD_NOT_SET
SECURITY_MSG_PASSWORD_RESET
SECURITY_MSG_PASSWORD_RESET_EXPIRED
SECURITY_MSG_PASSWORD_RESET_REQUEST
SECURITY_MSG_REFRESH
SECURITY_MSG_RETYPE_PASSWORD_MISMATCH
SECURITY_MSG_UNAUTHORIZED
SECURITY_MSG_USER_DOES_NOT_EXIST
1.2. Configuration
10
Chapter 1. Contents
11
password = db.StringField(max_length=255)
active = db.BooleanField(default=True)
confirmed_at = db.DateTimeField()
roles = db.ListField(db.ReferenceField(Role), default=[])
# Setup Flask-Security
user_datastore = MongoEngineUserDatastore(db, User, Role)
security = Security(app, user_datastore)
# Create a user to test with
@app.before_first_request
def create_user():
user_datastore.create_user(email='[email protected]', password='password')
# Views
@app.route('/')
@login_required
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
12
Chapter 1. Contents
description = TextField(null=True)
class User(db.Model, UserMixin):
email = TextField()
password = TextField()
active = BooleanField(default=True)
confirmed_at = DateTimeField(null=True)
class UserRoles(db.Model):
# Because peewee does not come with built-in many-to-many
# relationships, we need this intermediary class to link
# user to roles.
user = ForeignKeyField(User, related_name='roles')
role = ForeignKeyField(Role, related_name='users')
name = property(lambda self: self.role.name)
description = property(lambda self: self.role.description)
# Setup Flask-Security
user_datastore = PeeweeUserDatastore(db, User, Role, UserRoles)
security = Security(app, user_datastore)
# Create a user to test with
@app.before_first_request
def create_user():
for Model in (Role, User, UserRoles):
Model.drop_table(fail_silently=True)
Model.create_table(fail_silently=True)
user_datastore.create_user(email='[email protected]', password='password')
# Views
@app.route('/')
@login_required
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
13
To learn more about the various Flask-Mail settings to configure it to work with your particular email server configuration, please see the Flask-Mail documentation.
1.8 Models
Flask-Security assumes youll be using libraries such as SQLAlchemy, MongoEngine or Peewee to define a data model
that includes a User and Role model. The fields on your models must follow a particular convention depending on the
functionality your app requires. Aside from this, youre free to add any additional fields to your model(s) if you want.
At the bare minimum your User and Role model should include the following fields:
User
id
email
password
active
Role
id
name
description
14
Chapter 1. Contents
1.9.1 Views
Flask-Security is packaged with a default template for each view it presents to a user. Templates are located within a
subfolder named security. The following is a list of view templates:
security/forgot_password.html
security/login_user.html
security/register_user.html
security/reset_password.html
security/change_password.html
security/send_confirmation.html
security/send_login.html
Overriding these templates is simple:
1. Create a folder named security within your applications templates folder
2. Create a template with the same name for the template you wish to override
You can also specify custom template file paths in the configuration.
Each template is passed a template context object that includes the following, including the objects/values that are
passed to the template by the main Flask application context processor:
<template_name>_form: A form object for the view
security: The Flask-Security extension object
To add more values to the template context, you can specify a context processor for all views or a specific view. For
example:
security = Security(app, user_datastore)
# This processor is added to all templates
@security.context_processor
def security_context_processor():
return dict(hello="world")
# This processor is added to only the register view
@security.register_context_processor
def security_register_processor():
return dict(something="else")
15
1.9.2 Forms
All forms can be overridden. For each form used, you can specify a replacement class. This allows you to add extra
fields to the register form or override validators:
from flask_security.forms import RegisterForm
class ExtendedRegisterForm(RegisterForm):
first_name = TextField('First Name', [Required()])
last_name = TextField('Last Name', [Required()])
security = Security(app, user_datastore,
register_form=ExtendedRegisterForm)
For the register_form and confirm_register_form, each field is passed to the user model (as kwargs)
when a user is created. In the above case, the first_name and last_name fields are passed directly to the model,
so the model should look like:
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
first_name = db.Column(db.String(255))
last_name = db.Column(db.String(255))
1.9.3 Emails
Flask-Security is also packaged with a default template for each email that it may send. Templates are located within
the subfolder named security/email. The following is a list of email templates:
security/email/confirmation_instructions.html
security/email/confirmation_instructions.txt
16
Chapter 1. Contents
security/email/login_instructions.html
security/email/login_instructions.txt
security/email/reset_instructions.html
security/email/reset_instructions.txt
security/email/reset_notice.html
security/email/change_notice.txt
security/email/change_notice.html
security/email/reset_notice.txt
security/email/welcome.html
security/email/welcome.txt
Overriding these templates is simple:
1. Create a folder named security within your applications templates folder
2. Create a folder named email within the security folder
3. Create a template with the same name for the template you wish to override
Each template is passed a template context object that includes values for any links that are required in the
email. If you require more values in the templates, you can specify an email context processor with the
mail_context_processor decorator. For example:
security = Security(app, user_datastore)
# This processor is added to all emails
@security.mail_context_processor
def security_mail_processor():
return dict(hello="world")
17
1.10 API
1.10.1 Core
class flask_security.core.Security(app=None, datastore=None, **kwargs)
The Security class initializes the Flask-Security extension.
Parameters
app The application.
datastore An instance of a user datastore.
init_app(app,
datastore=None,
register_blueprint=True,
login_form=None,
confirm_register_form=None,
register_form=None,
forgot_password_form=None,
reset_password_form=None, change_password_form=None, send_confirmation_form=None,
passwordless_login_form=None)
Initializes the Flask-Security extension for the specified application and datastore implentation.
Parameters
app The application.
datastore An instance of a user datastore.
register_blueprint to register the Security blueprint or not.
flask_security.core.current_user
A proxy for the current user.
If there are only certain times you need to require that your user is logged in, you can do so with:
if not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
...which is essentially the code that this function adds to your views.
It can be convenient to globally turn off authentication when unit testing. To enable this, if the application
configuration variable LOGIN_DISABLED is set to True, this decorator will be ignored.
Parameters func (function) The view function to decorate.
flask_security.decorators.roles_required(*roles)
Decorator which specifies that a user must have all the specified roles. Example:
@app.route('/dashboard')
@roles_required('admin', 'editor')
def dashboard():
return 'Dashboard'
18
Chapter 1. Contents
The current user must have both the admin role and editor role in order to view the page.
Parameters args The required roles.
flask_security.decorators.roles_accepted(*roles)
Decorator which specifies that a user must have at least one of the specified roles. Example:
@app.route('/create_post')
@roles_accepted('editor', 'author')
def create_post():
return 'Create Post'
The current user must have either the editor role or author role in order to view the page.
Parameters args The possible roles.
flask_security.decorators.http_auth_required(realm)
Decorator that protects endpoints using Basic HTTP authentication. The username should be set to the users
email address.
Parameters realm optional realm name
flask_security.decorators.auth_token_required(fn)
Decorator that protects endpoints using token authentication. The token should be added to the request
by the client by using a query string variable with a name equal to the configuration value of SECURITY_TOKEN_AUTHENTICATION_KEY or in a request header named that of the configuration value of SECURITY_TOKEN_AUTHENTICATION_HEADER
1.10.4 Datastores
class flask_security.datastore.UserDatastore(user_model, role_model)
Abstracted user datastore.
Parameters
user_model A user model class definition
1.10. API
19
20
Chapter 1. Contents
add_role_to_user(user, role)
Adds a role to a user.
Parameters
user The user to manipulate
role The role to add to the user
create_role(**kwargs)
Creates and returns a new role from the given parameters.
create_user(**kwargs)
Creates and returns a new user from the given parameters.
deactivate_user(user)
Deactivates a specified user. Returns True if a change was made.
Parameters user The user to deactivate
delete_user(user)
Deletes the specified user.
Parameters user The user to delete
find_or_create_role(name, **kwargs)
Returns a role matching the given name or creates it with any additionally provided parameters.
remove_role_from_user(user, role)
Removes a role from a user.
Parameters
user The user to manipulate
role The role to remove from the user
toggle_active(user)
Toggles a users active status. Always returns True.
class flask_security.datastore.MongoEngineUserDatastore(db, user_model, role_model)
A MongoEngine datastore implementation for Flask-Security that assumes the use of the Flask-MongoEngine
extension.
activate_user(user)
Activates a specified user. Returns True if a change was made.
Parameters user The user to activate
add_role_to_user(user, role)
Adds a role to a user.
Parameters
user The user to manipulate
role The role to add to the user
create_role(**kwargs)
Creates and returns a new role from the given parameters.
create_user(**kwargs)
Creates and returns a new user from the given parameters.
deactivate_user(user)
Deactivates a specified user. Returns True if a change was made.
1.10. API
21
22
Chapter 1. Contents
remove_role_from_user(user, role)
Removes a role from a user.
Parameters
user The user to manipulate
role The role to remove from the user
toggle_active(user)
Toggles a users active status. Always returns True.
1.10.5 Utils
flask_security.utils.login_user(user, remember=None)
Performs the login routine.
Parameters
user The user to login
remember Flag specifying if the remember cookie should be set. Defaults to False
flask_security.utils.logout_user()
Logs out the current. This will also clean up the remember me cookie if it exists.
flask_security.utils.get_hmac(password)
Returns a Base64 encoded HMAC+SHA512 of the password signed with the salt specified by
SECURITY_PASSWORD_SALT.
Parameters password The password to sign
flask_security.utils.verify_password(password, password_hash)
Returns True if the password matches the supplied hash.
Parameters
password A plaintext password to verify
password_hash The expected hash value of the password (usually from your database)
flask_security.utils.verify_and_update_password(password, user)
Returns True if the password is valid for the specified user. Additionally, the hashed password in the database
is updated if the hashing algorithm happens to have changed.
Parameters
password A plaintext password to verify
user The user to verify against
flask_security.utils.encrypt_password(password)
Encrypts the specified plaintext password using the configured encryption options.
Parameters password The plaintext password to encrypt
flask_security.utils.url_for_security(endpoint, **values)
Return a URL for the security blueprint
Parameters
endpoint the endpoint of the URL (name of the function)
values the variable arguments of the URL rule
1.10. API
23
_external if set to True, an absolute URL is generated. Server address can be changed
via SERVER_NAME configuration variable which defaults to localhost.
_anchor if provided this is added as anchor to the URL.
_method if provided this explicitly specifies an HTTP method.
flask_security.utils.get_within_delta(key, app=None)
Get a timedelta object from the application configuration following the internal convention of:
<Amount of Units> <Type of Units>
Parameters
key The config value key without the SECURITY_ prefix
app Optional application to inspect. Defaults to Flasks current_app
flask_security.utils.send_mail(subject, recipient, template, **context)
Send an email via the Flask-Mail extension.
Parameters
subject Email subject
recipient Email recipient
template The name of the email template
context The context to render the template with
flask_security.utils.get_token_status(token, serializer, max_age=None)
Get the status of a token.
Parameters
token The token to check
serializer The name of the seriailzer. Can be one of the following: confirm,
login, reset
max_age The name of the max age config option.
CONFIRM_EMAIL, LOGIN, RESET_PASSWORD
1.10.6 Signals
See the Flask documentation on signals for information on how to use these signals in your code.
See the documentation for the signals provided by the Flask-Login and Flask-Principal extensions. In addition to those
signals, Flask-Security sends the following signals.
user_registered
Sent when a user registers on the site. It is passed a dict with the user and confirm_token, the user being logged
in and the (if so configured) the confirmation token issued.
user_confirmed
Sent when a user is confirmed. It is passed user, which is the user being confirmed.
24
Chapter 1. Contents
confirm_instructions_sent
Sent when a user requests confirmation instructions. It is passed the user.
login_instructions_sent
Sent when passwordless login is used and user logs in. It is passed a dict with the user and login_token, the user
being logged in and the (if so configured) the login token issued.
password_reset
Sent when a user completes a password reset. It is passed the user.
password_changed
Sent when a user completes a password change. It is passed the user.
reset_password_instructions_sent
Sent when a user requests a password reset. It is passed a dict with the user and token, the user being logged in
and the (if so configured) the reset token issued.
All signals are also passed a app keyword argument, which is the current application.
25
26
Chapter 1. Contents
27
28
Chapter 1. Contents
29
30
Chapter 1. Contents
Index
activate_user() (flask_security.datastore.MongoEngineUserDatastore
deactivate_user() (flask_security.datastore.MongoEngineUserDatastore
method), 21
method), 21
activate_user() (flask_security.datastore.PeeweeUserDatastore
deactivate_user() (flask_security.datastore.PeeweeUserDatastore
method), 22
method), 22
activate_user() (flask_security.datastore.SQLAlchemyUserDatastore
deactivate_user() (flask_security.datastore.SQLAlchemyUserDatastore
method), 20
method), 21
activate_user() (flask_security.datastore.UserDatastore deactivate_user() (flask_security.datastore.UserDatastore
method), 20
method), 20
add_role_to_user() (flask_security.datastore.MongoEngineUserDatastore
delete_user() (flask_security.datastore.MongoEngineUserDatastore
method), 21
method), 22
add_role_to_user() (flask_security.datastore.PeeweeUserDatastore
delete_user() (flask_security.datastore.PeeweeUserDatastore
method), 22
method), 22
add_role_to_user() (flask_security.datastore.SQLAlchemyUserDatastore
delete_user() (flask_security.datastore.SQLAlchemyUserDatastore
method), 20
method), 21
add_role_to_user() (flask_security.datastore.UserDatastore delete_user()
(flask_security.datastore.UserDatastore
method), 20
method), 20
AnonymousUser (class in flask_security.core), 19
auth_token_required()
(in
module E
flask_security.decorators), 19
encrypt_password() (in module flask_security.utils), 23
P
password_changed (built-in variable), 25
password_reset (built-in variable), 25
PeeweeUserDatastore (class in flask_security.datastore),
22
R
remove_role_from_user()
(flask_security.datastore.MongoEngineUserDatastore
method), 22
remove_role_from_user()
(flask_security.datastore.PeeweeUserDatastore
method), 22
remove_role_from_user()
(flask_security.datastore.SQLAlchemyUserDatastore
method), 21
remove_role_from_user()
(flask_security.datastore.UserDatastore
method), 20
reset_password_instructions_sent (built-in variable), 25
RoleMixin (class in flask_security.core), 19
roles_accepted() (in module flask_security.decorators), 19
roles_required() (in module flask_security.decorators), 18
S
Security (class in flask_security.core), 18
send_mail() (in module flask_security.utils), 24
32
Index