Python and Flask-Security: Adding Security Features to Your Flask App

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Installing Flask-Security
  4. Configuring Flask-Security
  5. Adding User Registration
  6. Creating Login Functionality
  7. Protecting Routes
  8. Conclusion

Introduction

In this tutorial, you will learn how to enhance the security features of your Flask application using Flask-Security. Flask-Security is a powerful extension that provides a quick and easy way to add authentication, authorization, and other security features to your Flask web application.

By the end of this tutorial, you will be able to:

  • Install and configure Flask-Security in your Flask app.
  • Implement user registration and login functionality.
  • Protect certain routes in your application based on user roles and permissions.

Before we get started, make sure you have a basic understanding of Python and Flask. It is also recommended to have Python and Flask installed on your machine.

Prerequisites

To follow along with this tutorial, you need to have the following prerequisites:

  • Python installed on your machine
  • Flask framework installed (you can install it using pip install flask)

Installing Flask-Security

Flask-Security can be installed using pip. Open your terminal or command prompt and run the following command: bash pip install Flask-Security

Configuring Flask-Security

To use Flask-Security in your Flask app, you need to configure it with some basic settings. Create a new file called config.py in your project directory and add the following code: ```python # config.py

# Flask-Security config
SECRET_KEY = 'your-secret-key-goes-here'
SECURITY_PASSWORD_SALT = 'your-password-salt-goes-here'
``` Make sure to replace `'your-secret-key-goes-here'` and `'your-password-salt-goes-here'` with your actual secret key and password salt. These values should be kept secret and unique for your application.

Adding User Registration

To add user registration functionality to your Flask app, you need to create a registration form and handle the form submission. Here’s an example of how you can achieve this:

  1. Create a new file called forms.py in your project directory with the following code:
     # forms.py
    	
     from flask_wtf import FlaskForm
     from wtforms import StringField, PasswordField
     from wtforms.validators import DataRequired, Email
    	
     class RegistrationForm(FlaskForm):
         email = StringField('Email', validators=[DataRequired(), Email()])
         password = PasswordField('Password', validators=[DataRequired()])
    
  2. In your main Flask application file (e.g., app.py), import the necessary modules and add the following code:
     # app.py
    	
     from flask import Flask, render_template, redirect, url_for
     from flask_security import Security, SQLAlchemyUserDatastore, login_required
     from flask_wtf.csrf import CSRFProtect
     from flask_wtf.csrf import CSRFError
    	
     from forms import RegistrationForm
     from models import db, User, Role
    	
     app = Flask(__name__)
     app.config.from_pyfile('config.py')
     csrf = CSRFProtect(app)
     db.init_app(app)
    	
     user_datastore = SQLAlchemyUserDatastore(db, User, Role)
     security = Security(app, user_datastore)
    	
     @app.route('/')
     def home():
         return 'Welcome to the Flask App'
    	
     @app.route('/register', methods=['GET', 'POST'])
     def register():
         form = RegistrationForm()
         if form.validate_on_submit():
             user = user_datastore.create_user(email=form.email.data, password=form.password.data)
             db.session.commit()
             return redirect(url_for('home'))
         return render_template('register.html', form=form)
    
  3. Create a template file called register.html in a new folder called templates. Add the following code to the register.html file:
    	
     <!-- templates/register.html -->
    	
     {% extends 'base.html' %}
    	
     {% block content %}
       <h1>Register</h1>
       <form method="POST" action="{{ url_for('register') }}">
         {{ form.csrf_token }}
         {{ form.email.label }} {{ form.email() }}<br><br>
         {{ form.password.label }} {{ form.password() }}<br><br>
         <input type="submit" value="Register">
       </form>
     {% endblock %}
    	
    

    You can now run your Flask app using flask run command and visit http://localhost:5000/register to see the registration form.

Creating Login Functionality

To add login functionality to your Flask app, you need to create a login form and handle the login submission. Here’s an example of how you can achieve this:

  1. Create a new file called forms.py in your project directory with the following code:
     # forms.py
    	
     from flask_wtf import FlaskForm
     from wtforms import StringField, PasswordField
     from wtforms.validators import DataRequired
    	
     class LoginForm(FlaskForm):
         email = StringField('Email', validators=[DataRequired()])
         password = PasswordField('Password', validators=[DataRequired()])
    
  2. In your main Flask application file (e.g., app.py), import the necessary modules and add the following code:
     # app.py
    	
     from flask import Flask, render_template, redirect, url_for
     from flask_security import Security, SQLAlchemyUserDatastore, login_required
     from flask_wtf.csrf import CSRFProtect
     from flask_wtf.csrf import CSRFError
    	
     from forms import LoginForm
     from models import db, User, Role
    	
     app = Flask(__name__)
     app.config.from_pyfile('config.py')
     csrf = CSRFProtect(app)
     db.init_app(app)
    	
     user_datastore = SQLAlchemyUserDatastore(db, User, Role)
     security = Security(app, user_datastore)
    	
     @app.route('/')
     def home():
         return 'Welcome to the Flask App'
    	
     @app.route('/login', methods=['GET', 'POST'])
     def login():
         form = LoginForm()
         if form.validate_on_submit():
             user = user_datastore.get_user(email=form.email.data)
             if user and user_datastore.verify_password(form.password.data, user.password):
                 return redirect(url_for('home'))
         return render_template('login.html', form=form)
    
  3. Create a template file called login.html in the templates folder. Add the following code to the login.html file:
    	
     <!-- templates/login.html -->
    	
     {% extends 'base.html' %}
    	
     {% block content %}
       <h1>Login</h1>
       <form method="POST" action="{{ url_for('login') }}">
         {{ form.csrf_token }}
         {{ form.email.label }} {{ form.email() }}<br><br>
         {{ form.password.label }} {{ form.password() }}<br><br>
         <input type="submit" value="Login">
       </form>
     {% endblock %}
    	
    

    You can now run your Flask app using flask run command and visit http://localhost:5000/login to see the login form.

Protecting Routes

Flask-Security provides a convenient way to protect certain routes in your Flask app based on user roles and permissions. Here’s an example of how you can achieve this:

  1. In your app.py file, add the following code after the import statements:
     # app.py
    	
     # Existing code...
    	
     @app.route('/protected')
     @login_required
     def protected():
         return 'You are in a protected route! Only authenticated users can access this.'
    	
     @app.errorhandler(CSRFError)
     def handle_csrf_error(e):
         return 'CSRF token missing or incorrect.', 400
    	
     if __name__ == '__main__':
         app.run()
    
  2. Update the home route in your app.py file as follows:
     # app.py
    	
     @app.route('/')
     @login_required
     def home():
         return 'Welcome to the Flask App'
    

    Now, if you try to access the home route http://localhost:5000/, you will be redirected to the login page first. After successfully logging in, you will be able to access the protected route at http://localhost:5000/protected.

Conclusion

In this tutorial, you learned how to enhance the security features of your Flask application using Flask-Security. You installed and configured Flask-Security, added user registration and login functionality, and protected specific routes based on user authentication. Flask-Security provides a convenient way to implement authentication and authorization in Flask web applications, making it easier to develop secure applications.

You can further explore Flask-Security’s documentation to discover additional features and customization options to create even more secure web applications.

Remember to keep your secret key and passwords unique and secure. Happy coding!