Flask - Role Based Access Control
Last Updated :
25 Mar, 2025
Role-Based Access Control (RBAC) is a security mechanism that restricts user access based on their roles within an application. Instead of assigning permissions to individual users, RBAC groups users into roles and each role has specific permissions.
For example, in a Flask app, we might have roles like admin, editor and user, where:
- Admin can manage users and settings.
- Editor can create and edit content.
- User can only view content.
This approach improves security, simplifies permission management and ensures users only access what they need.
Note: For storing users' details we are going to use flask-sqlalchemy and db-browser for performing database actions. we can find detailed tutorial here.
Installing Packages
To learn how to create and set-up flask app, refer to- Create Flask App
After creating a Flask app, we need to install modules required in this project, to install them execute this command in the terminal-
pip install flask flask-security flask-sqlalchemy flask-login email-validator
It will install these packages:
- Flask: A lightweight web framework for building web applications.
- Flask-Security: Adds authentication and role management features.
- Flask-SQLAlchemy: Integrates SQLAlchemy for easy database operations.
- Flask-Login: Manages user sessions and handles login/logout.
- email-validator: Validates email addresses for correct formatting.
File Structure
The file structure of this project aftre completion will look like this-
File StructureImporting Modules and Setting Configurations
Configurations are key-value settings that control the app's behavior, such as database connections, security settings and session management. These settings are stored in app.config and help customize the application's functionality. The configurations used in our app are-
- app.config['SECRET_KEY'] = 'your_secret_key'- A secret key used for securely signing session cookies and protecting against attacks like CSRF.
- app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' - Defines the database location, here using SQLite (users.db) for storing user data.
- login_manager.login_view = 'login' - Specifies the route where users should be redirected if they try to access a protected page without logging in.Â
Python
from flask import Flask, render_template, redirect, url_for, request
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, login_user, logout_user, current_user
from flask_security import Security, SQLAlchemySessionUserDatastore, roles_accepted, UserMixin, RoleMixin
import uuid
app = Flask(__name__)
# --- Configuration ---
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///g4g.sqlite3" # Path to the SQLite database
app.config['SECRET_KEY'] = 'MY_SECRET' # Secret key for session management
# --- Initialize Database ---
db = SQLAlchemy(app)
Create Database Models
This part defines our database models. We create two models—User and Role—with a many-to-many relationship via an association table. The fs_uniquifier is a required field for Flask-Security.
Python
# ---------------- Association Table for User Roles ----------------
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)
# ---------------- Database Models ----------------
class User(db.Model, UserMixin):
__tablename__ = 'user'
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
email = db.Column(db.String(255), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False, server_default='')
active = db.Column(db.Boolean(), default=True)
fs_uniquifier = db.Column(db.String(255), unique=True, nullable=False, default=lambda: uuid.uuid4().hex)
# Relationship with roles
roles = db.relationship('Role', secondary=roles_users, backref='roled')
class Role(db.Model, RoleMixin):
__tablename__ = 'role'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
Explanation
- Association Table: roles_users is a helper table to create a many-to-many relationship between User and Role.
- User Model: Contains user details including email, password, activation status and a unique identifier (fs_uniquifier) for security. It also relates to roles.
- Role Model: Defines roles with a unique ID and name.
Defining Routes
In this section, we define all the routes for our application, such as home, signup, signin, logout and role-protected pages. The routes use Flask-Security decorators to restrict access based on user roles.
Python
# Flask-Security Setup
user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)
security = Security(app, user_datastore)
# Routes
# Home route renders index.html
@app.route('/')
def index():
return render_template("index.html")
# Signup route for user registration
@app.route('/signup', methods=['GET', 'POST'])
def signup():
msg = ""
if request.method == 'POST':
user = User.query.filter_by(email=request.form['email']).first()
if user:
msg = "User already exists"
return render_template("signup.html", msg=msg)
user = User(email=request.form['email'], password=request.form['password'])
role = Role.query.filter_by(id=int(request.form['options'])).first()
if role:
user.roles.append(role)
else:
msg = "Invalid role selection"
return render_template("signup.html", msg=msg)
db.session.add(user)
db.session.commit()
login_user(user)
return redirect(url_for('index'))
return render_template("signup.html", msg=msg)
# Signin route for user login
@app.route('/signin', methods=['GET', 'POST'])
def signin():
msg = ""
if request.method == 'POST':
user = User.query.filter_by(email=request.form['email']).first()
if user:
if user.password == request.form['password']:
login_user(user)
return redirect(url_for('index'))
else:
msg = "Wrong password"
else:
msg = "User doesn't exist"
return render_template("signin.html", msg=msg)
return render_template("signin.html", msg=msg)
# Logout route to end the session
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
# Teachers route (Accessible to Admin only)
@app.route('/teachers')
@roles_accepted('Admin')
def teachers():
teachers_list = []
role_teachers = db.session.query(roles_users).filter_by(role_id=2).all()
for teacher in role_teachers:
user = User.query.filter_by(id=teacher.user_id).first()
if user:
teachers_list.append(user)
return render_template("teachers.html", teachers=teachers_list)
# Staff route (Accessible to Admin and Teacher)
@app.route('/staff')
@roles_accepted('Admin', 'Teacher')
def staff():
staff_list = []
role_staff = db.session.query(roles_users).filter_by(role_id=3).all()
for s in role_staff:
user = User.query.filter_by(id=s.user_id).first()
if user:
staff_list.append(user)
return render_template("staff.html", staff=staff_list)
# Students route (Accessible to Admin, Teacher, and Staff)
@app.route('/students')
@roles_accepted('Admin', 'Teacher', 'Staff')
def students():
students_list = []
role_students = db.session.query(roles_users).filter_by(role_id=4).all()
for s in role_students:
user = User.query.filter_by(id=s.user_id).first()
if user:
students_list.append(user)
return render_template("students.html", students=students_list)
# My Details route (Accessible to all roles)
@app.route('/mydetails')
@roles_accepted('Admin', 'Teacher', 'Staff', 'Student')
def mydetails():
return render_template("mydetails.html")
Explanation
- Flask-Security Setup: Initializes Flask-Security with the user datastore connecting the User and Role models.
- Home (/): Displays the index page with navigation links.
- Signup (/signup): Handles user registration and role assignment.
- Signin (/signin): Authenticates users based on email and password.
- Logout (/logout): Logs out the user.
- Protected Routes: (/teachers, /staff, /students, /mydetails) Use the @roles_accepted decorator to restrict access based on roles.
Creating Roles
We have tables but we still don't have roles created. We have to create those roles (Admin, Teacher, Staff, Student). Keep in mind that the id for Admin role must be 1, for Teacher: 2, Staff: 3 and Student: 4.
Create a new file "create_roles" in the same folder as app.py and add the below code. Remember to execute this file after the db creation.
Python
from app import Role, db, app
def create_roles():
with app.app_context():
admin = Role(id=1, name='Admin')
teacher = Role(id=2, name='Teacher')
staff = Role(id=3, name='Staff')
student = Role(id=4, name='Student')
db.session.add(admin)
db.session.add(teacher)
db.session.add(staff)
db.session.add(student)
db.session.commit()
print("Roles created successfully!")
if __name__ == '__main__':
create_roles()
Explanation
- app.app_context(): The code is wrapped in with app.app_context(): to ensure Flask’s application context is active for database operations.
- Role Insertion: Predefined roles are created with specific IDs and added to the database.
- Commit: Changes are committed and a success message is printed.
Appliaction Entry Point
The following lines of code will be responsible fr creating the databse and running the app in debug mode, if the database already exists then it simply connects the app to it
Python
# --- Application Entry Point ---
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
Creating HTML files
Create the following html files in the templates folder
index.html
The index.html file uses the Jinja2 templating engine. The current_user variable stores the logged-in user's details. {% if current_user.is_authenticated %} checks if a user is logged in and displays their email ({{ current_user.email }}). Since users can have multiple roles, a loop iterates through them. If no user is logged in, the {% else %} block runs.
HTML
<!-- index.html -->
<!-- links to the pages -->
<a href="/teachers">View all Teachers</a> (Access: Admin)<br><br>
<a href="/staff">View all Staff</a> (Access: Admin, Teacher)<br><br>
<a href="/students">View all Students</a> (Access: Admin, Teacher, Staff)<br><br>
<a href="/mydetails">View My Details</a> (Access: Admin, Teacher, Staff, Student)
<br><br>
<!-- Show only if user is logged in -->
{% if current_user.is_authenticated %}
<!-- Show current users email -->
<b>Current user</b>: {{current_user.email}}
<!-- Current users roles -->
| <b>Role</b>: {% for role in current_user.roles%}
{{role.name}}
{% endfor %} <br><br>
<!-- link for logging out -->
<a href="/logout">Logout</a>
<!-- Show if user is not logged in -->
{% else %}
<a href="/signup">Sign up</a> | <a href="/signin">Sign in</a>
{% endif %}
<br><br>
Output:
index.htmlsignup.html page
The form's action is #, reloading the current page on submission. It uses the POST method to create a new database entry with fields for email, password and role selection via radio buttons. Jinja2's {% if %} checks if a user is logged in—if not, the form is shown; otherwise, a logged-in message appears.
HTML
<!-- signup.html -->
<h2>Sign up</h2>
<!-- Show only if user is logged in -->
{% if current_user.is_authenticated %}
You are already logged in.
<!-- Show if user is NOT logged in -->
{% else %}
{{ msg }}<br>
<!-- Form for signup -->
<form action="#" method="POST" id="signup-form">
<label>Email Address </label>
<input type="text" name="email" required /><br><br>
<label>Password </label>
<input type="password" name="password" required/><br><br>
<!-- Options to choose role -->
<!-- Give the role ids in the value -->
<input type="radio" name="options" id="option1" value=1 required> Admin </input>
<input type="radio" name="options" id="option2" value=2> Teacher </input>
<input type="radio" name="options" id="option3" value=3> Staff </input>
<input type="radio" name="options" id="option3" value=4> Student </input><br>
<br>
<button type="submit">Submit</button><br><br>
<!-- Link for signin -->
<span>Already have an account?</span>
<a href="/signin">Sign in</a>
</form>
<!-- End the if block -->
{% endif %}
Output:
signup.htmlsignin.html
Similar to the signup page, check if a user is already logged in, if not then render the form asking for email and password. The form method should be POST.
HTML
<!-- signin.html -->
<h2>Sign in</h2>
<!-- Show only if user is logged in -->
{% if current_user.is_authenticated %}
You are already logged in.
<!-- Show if user is NOT logged in -->
{% else %}
<!-- msg that was passed while rendering template -->
{{ msg }}<br>
<form action="#" method="POST" id="signin-form">
<label>Email Address </label>
<input type="text" name="email" required /><br><br>
<label>Password </label>
<input type="password" name="password" required/><br><br>
<input class="btn btn-primary" type="submit" value="Submit"><br><br>
<span>Don't have an account?</span>
<a href="/signup">Sign up</a>
</form>
{% endif %}
Output:
signin.htmlteachers.html
The teachers passed in the render_template is a list of objects, containing all the columns of the user table, so we're using Python for loop in jinja2 to show the elements in the list in HTML ordered list tag.
HTML
<!-- teachers.html -->
<h3>Teachers</h3>
<!-- list that shows all teachers' email -->
<ol>
{% for teacher in teachers %}
<li>
{{teacher.email}}
</li>
{% endfor %}
</ol>
Output:
teachers.htmlstaff.html
In this file, we are iterating all the staff and extracting their email IDs.
HTML
<! staff.html -->
<h3>Staff</h3>
<ol>
{% for staf in staff %}
<li>
{{staf.email}}
</li>
{% endfor %}
</ol>
Output:
staff.htmlstudent.html
Iterating all the students and extracting their email IDs.
HTML
<!-- students.html -->
<h3>Students</h3>
<ol>
{% for student in students %}
<li>
{{student.email}}
</li>
{% endfor %}
</ol>
Output:
studen.htmlmydetails.html
Similar to the index page, to show the role use a for loop from Jinja2, because a user can more than one role i.e., current_user.roles is a list of roles that were queried from the database.
HTML
<!-- mydetails.html -->
<h3>My Details</h3><br>
<b>My email</b>: {{current_user.email}}
| <b>Role</b>: {% for role in current_user.roles%}
{{role.name}}
{% endfor %} <br><br>
Output:
details.htmlRunning and Testing the Application
To correctly run the app we need to follow these step:
Step 1: First run the following command in the terminal.
python app.py
It will start the app and create the database "g4g" in instance folder.
Step 2: Then stop the app using CTRL + C and run the create_roles.py file using command-
python create_roles.py
This will create the roles in the database "g4g".
Step 3: Then again run the main flask app using command-
python app.py
Go to:
http://127.0.0.1:5000
Output
To demonstrate the working of app, sign up as a new user "geek" in student role.
Snapshot after signin
Similar Reads
Flask Tutorial
Flask is a lightweight and powerful web framework for Python. Itâs often called a "micro-framework" because it provides the essentials for web development without unnecessary complexity. Unlike Django, which comes with built-in features like authentication and an admin panel, Flask keeps things mini
8 min read
Flask Setup & Installation
Flask Quick Start
Flask - (Creating first simple application)
Building a webpage using python.There are many modules or frameworks which allow building your webpage using python like a bottle, Django, Flask, etc. But the real popular ones are Flask and Django. Django is easy to use as compared to Flask but Flask provides you with the versatility to program wit
6 min read
How to Run a Flask Application
After successfully creating a Flask app, we can run it on the development server using the Flask CLI or by running the Python script. Simply execute one of the following commands in the terminal:flask --app app_name runpython app_nameFile StructureHere, we are using the following folder and file.Dem
4 min read
Flask App Routing
App Routing means mapping the URLs to a specific function that will handle the logic for that URL. Modern web frameworks use more meaningful URLs to help users remember the URLs and make navigation simpler. Example: In our application, the URL ("/") is associated with the root URL. So if our site's
3 min read
Flask - HTTP Method
In this article, we will learn how to handle HTTP methods, such as GET and POST in Flask using Python. Before starting let's understand the basic terminologies:GET: to request data from the server.POST: to submit data to be processed to the server.PUT: replaces the entire resource with new data. If
5 min read
Flask - Variable Rule
Flask variable rules allow us to create dynamic URLs by defining variable parts within the route. This makes it possible to capture values from the URL and pass them to view functions.Variable RulesA variable rule is defined using <variable-name> within the route.The captured variable is autom
3 min read
Redirecting to URL in Flask
Flask is a backend server that is built entirely using Python. It is a  framework that consists of Python packages and modules. It is lightweight which makes developing backend applications quicker with its features. In this article, we will learn to redirect a URL in the Flask web application. Redi
3 min read
Python Flask - Redirect and Errors
We'll discuss redirects and errors with Python Flask in this article. A redirect is used in the Flask class to send the user to a particular URL with the status code. conversely, this status code additionally identifies the issue. When we access a website, our browser sends a request to the server,
4 min read
How to Change Port in Flask app
In this article, we will learn to change the port of a Flask application. The default port for the Flask application is 5000. So we can access our application at the below URL. http://127.0.0.1:5000/ We may want to change the port may be because the default port is already occupied. To do that we ju
1 min read
Changing Host IP Address in Flask
By default, Flask runs on 127.0.0.1:5000, which means it can only be accessed from the same machine. However, we may want to access our Flask app from other devices on the same network or even from the internet. To do this, we need to change the host IP address.Changing the IP address in a Flask app
2 min read
Serve Templates and Static Files in Flask
Flask Rendering Templates
Flask is a lightweight Python web framework that enables developers to build web applications easily. One of its key features is template rendering, which allows dynamic content generation using Jinja2 templating. In this guide, we'll explore how to render templates in Flask.Setting up FlaskSetting
6 min read
CSRF Protection in Flask
Cross-Site Request Forgery (CSRF) is a security vulnerability where an attacker tricks a user into unknowingly submitting a request to a web application in which they are authenticated. This can lead to unauthorized actions being performed on behalf of the user, such as changing account settings or
3 min read
Template Inheritance in Flask
Template inheritance is a powerful feature in Jinja, the templating engine used in Flask. It allows us to define a common structure for web pages, such as headers, footers, and navigation bars, in a base template. This prevents redundant code and makes managing multiple pages easier.Prerequisite - F
2 min read
Placeholders in jinja2 Template - Python
Web pages use HTML for the things that users see or interact with. But how do we show things from an external source or a controlling programming language like Python? To achieve this templating engine like Jinja2 is used. Jinja2 is a templating engine in which placeholders in the template allow wri
5 min read
How to serve static files in Flask
In Flask, static files refer to files such as CSS, JavaScript, images, videos, and audio files that do not change dynamically. Flask provides a built-in way to serve these static files using the /static directory.This guide will show how to serve different types of static files in a Flask web applic
4 min read
Uploading and Downloading Files in Flask
This article will go over how to upload and download files using a Flask database using Python. Basically, we have a section for uploading files where we can upload files that will automatically save in our database. When we upload a file and submit it, a message stating that your file has been uplo
7 min read
How to Upload File in Python-Flask
File uploading is a typical task in web apps. Taking care of file upload in Flask is simple all we need is to have an HTML form with the encryption set to multipart/form information to publish the file into the URL. The server-side flask script brings the file from the request object utilizing the r
2 min read
Upload Multiple files with Flask
In online apps, uploading files is a common task. Simple HTML forms with encryption set to multipart/form information are all that is required to publish a file into a URL when using Flask for file upload. The file is obtained from the request object by the server-side flask script using the request
2 min read
Flask - Message Flashing
In this article, we will discuss Flask - Message Flashing. As we know best Graphical User Interface provides feedback to a user when users interact, as an example, we know that desktop applications use the messages box or JS for an alert purpose. generating like same informative message is easy to d
6 min read
Create Contact Us using WTForms in Flask
WTForms is a library designed to make the processing of forms easier to manage. It handles the data submitted by the browser very easily. In this article, we will discuss how to create a contact us form using WTForms. Advantages of WT-FORM:We don't have to worry about validators.Avoidance of Cross-S
3 min read
Sending Emails Using API in Flask-Mail
Python, being a powerful language donât need any external library to import and offers a native library to send emails- âSMTP libâ. âsmtplibâ creates a Simple Mail Transfer Protocol client session object which is used to send emails to any valid email id on the internet. This article revolves around
3 min read
User Registration, Login, and Logout in Flask
How to Add Authentication to App with Flask-Login
We can implement authentication, login/logout functionality in flask app using Flask-Login. In this article, we'll explore how to add authentication to a Flask app using Flask-Login.To get started, install Flask, Flask-Login, Flask-SQLAlchemy and Werkzeug using this command:pip install flask flask_s
6 min read
Add User and Display Current Username in Flask
This article covers adding users and displaying their usernames in Flask. After login, users are redirected to a profile page with a welcome message. User data is stored in MySQL for easy management via phpMyAdmin.Creating Templates for User InterfaceWe need three HTML files inside a templates folde
8 min read
Password Hashing with Bcrypt in Flask
In this article, we will use Password Hashing with Bcrypt in Flask using Python. Password hashing is the process of converting a plaintext password into a hashed or encrypted format that cannot be easily reverse-engineered to reveal the original password. Bcrypt is a popular hashing algorithm used t
2 min read
How to Store Username and Password in Flask
This article covers storing usernames and passwords in a Flask web app using MySQL. After logging in, users see a welcome message with their username.InstallationTo make our project we first create a virtual environment, to learn how to create and activate a virtual environment, refer to - Python vi
6 min read
Flask - Role Based Access Control
Role-Based Access Control (RBAC) is a security mechanism that restricts user access based on their roles within an application. Instead of assigning permissions to individual users, RBAC groups users into roles and each role has specific permissions.For example, in a Flask app, we might have roles l
9 min read
How to use Flask-Session in Python Flask
Sessions in Flask store user-specific data across requests, like login status, using cookies. Data is stored on the client side but signed with a secret key to ensure security. They help maintain user sessions without requiring constant authentication.This article demonstrates how to implement serve
4 min read
Flask Cookies
Cookies store user data in the browser as key-value pairs, allowing websites to remember logins, preferences, and other details. This helps improve the user experience by making the site more convenient and personalized.Make sure that flask is already installed on our system - Flask InstallationSett
4 min read
How to return a JSON response from a Flask API ?
Flask is one of the most widely used python micro-frameworks to design a REST API. In this article, we are going to learn how to create a simple REST API that returns a simple JSON object, with the help of a flask. Prerequisites: Introduction to REST API What is a REST API? REST stands for Represent
3 min read
Define and Access the Database in Flask
Flask SQLAlchemy Tutorial for Database
Flask doesnât have a built-in way to handle databases, so it relies on SQLAlchemy, a powerful library that makes working with databases easier. SQLAlchemy provides an Object Relational Mapper (ORM), allowing developers to interact with databases using Python code instead of raw SQL. This brings seve
7 min read
How to Build a Web App using Flask and SQLite in Python
Flask is a lightweight Python web framework with minimal dependencies. It lets you build applications using Python libraries as needed. In this article, we'll create a Flask app that takes user input through a form and displays it on another page using SQLite.Run the following commands to install Fl
3 min read
Sending Data from a Flask app to MongoDB Database
This article covers how we can configure a MongoDB database with a Flask app and store some data in the database after configuring it. Before directly moving to the configuration phase here is a short overview of all tools and software we will use. MongoDB is an open-source database that stores data
5 min read
Making a Flask app using a PostgreSQL database
The Postgres database can be accessed via one of two methods in Python. Installing PgAdmin4 is the first step because it offers a user interface for interacting with databases and another for using the psycopg2 connector. In this post, we'll concentrate on a different approach that lets us alter the
4 min read
Login and Registration Project in Flask using MySQL
Creating a user authentication system is a fundamental part of web applications. This guide will help you build a Login and Registration system using Flask and MySQL.Prerequisites - Basic knowledge of Python, MySQL Workbench, and Flask.To learn how to build login and registration in Flask, let's cre
6 min read
How to Execute Raw SQL in Flask - SQLAlchemy App
In a Flask application that uses SQLAlchemy, we usually interact with the database using Python objects and methods. However, there are times when we need to execute raw SQL queries directlyâfor example, to optimize performance, run complex queries, or perform database-specific operations.This guide
5 min read
Flask Deployment and Error Handling
Subdomain in Flask | Python
Prerequisite: Introduction to Flask In this article, we will learn how to setup subdomains in Flask. But first, let's go through the basic like what is DNS and subdomains. Domain Name System (DNS): The Domain Name System (DNS) is a hierarchical and decentralized naming system for computers, services
3 min read
Handling 404 Error in Flask
A 404 Error occurs when a page is not found. This can happen due to several reasons:The URL was changed, but the old links were not updated.The page was deleted from the website.The user mistyped the URL.To improve user experience, websites should have a custom error page instead of showing a generi
3 min read
Deploy Python Flask App on Heroku
Flask is a web application framework written in Python. Flask is based on the Werkzeug WSGI toolkit and Jinja2 template engine. Both are Pocco projects. This article revolves around how to deploy a flask app on Heroku. To demonstrate this, we are first going to create a sample application for a bett
2 min read
Deploy Machine Learning Model using Flask
In this article, we will build and deploy a Machine Learning model using Flask. We will train a Decision Tree Classifier on the Adult Income Dataset, preprocess the data, and evaluate model accuracy. After training, weâll save the model and create a Flask web application where users can input data a
7 min read
Python Flask Projects with Source Code (Beginners to Advanced)
Flask, a Python web application framework, was created by Armin Ronacher. Known for its lightweight and efficient nature, Flask is designed for quick starts and accommodates complex applications. It is based on the Werkzeug WSGI toolkit and Jinja2 template engine.In this article, weâve curated a lis
4 min read