Authorization and Authentication-Restrict access to protected routes with Python, Flask and Flask Login
Introduction
Authentication and authorization are two closely related but distinct concepts in the context of security and access control. In this article, we will go through authentication and authorization and their key differences. We will use Flask login to create a login-based application to restrict access to selected routes.
Authentication
Authentication refers to the process of verifying the identity of a user, application, or device. It involves establishing the authenticity of a user’s credentials, such as a username and password, or using other forms of authentication, such as biometric authentication or multi-factor authentication. Authentication ensures that the user or application is who they claim to be and helps prevent unauthorized access to resources.
Authorization
Authorization, on the other hand, refers to the process of granting or denying access to resources based on the authenticated identity of the user or application. It involves defining access control policies that specify what actions a user or application is allowed to perform on a resource, based on their identity and permissions. Authorization ensures that users or applications only have access to the resources they are authorized to access and helps enforce the principle of least privilege.
In summary, authentication is the process of verifying a user’s identity, while authorization is the process of granting or denying access to resources based on that identity. Authentication establishes who a user is, while authorization determines what they are allowed to do.
Flask Login
Time to do it yourself! Let’s look at authentication and authorization with Python and Flask. Create a new project directory for your application. Create a file called app.py and enter the following code:
# Import the Flask and Flask-Login libraries
from flask import Flask, render_template, request, session, redirect
from flask_login import LoginManager, UserMixin, login_user, logout_user, current_user, login_required
# Create a Flask app
app = Flask(__name__)
app.secret_key = '89798789jhvjhjg'
# Configure Flask-Login
login_manager = LoginManager()
login_manager.init_app(app)
# Define a User model
class User(UserMixin):
def __init__(self, username, password):
self.username = username
self.password = password
def get_id(self):
return self.username
@login_manager.user_loader
def load_user(user_id):
return user if user.get_id() == user_id else None
# Create a user
user = User('admin', 'password')
# Register the user with Flask-Login
login_manager.user_loader(load_user)
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect('/protected')
if request.method == 'POST':
# Get the username and password from the request
username = request.form['username']
password = request.form['password']
# Check if the username and password are valid
if user.username == username and user.password == password:
# Login the user
login_user(user)
return redirect('')
# Otherwise, show an error message
return render_template('login.html', error='Invalid username or password.')
# Render the login form for GET requests
return render_template('login.html')
# Define a route for the logout page
@app.route('/logout')
def logout():
# Logout the user
logout_user()
return redirect('/')
# Define a protected route
@app.route('/protected')
@login_required
def protected():
return render_template('protected.html')
# Run the app
if __name__ == '__main__':
app.run(debug=True)
This code will create a simple Flask app with two routes: a login page and a protected page. The login page will allow users to log in with a username and password. The protected page will only be accessible to logged-in users.
Let’s go through the main components and their functionalities:
Creating the Flask app:
- An instance of the Flask application is created.
- The
app.secret_key
attribute is set to a random value. This key is used for securely signing the session cookie.
Configuring Flask-Login:
- An instance of
LoginManager
is created. - The
init_app()
method is called with the Flask app instance to initialize Flask-Login.
Defining the User model:
- The
User
class is defined, which represents the user model. - The class inherits from
UserMixin
, which provides default implementations for some of the required methods by Flask-Login. - The
get_id()
method is defined, which returns the unique identifier for the user.
Implementing the user_loader callback:
- The
load_user
function is defined as the user_loader callback. - This function is responsible for loading the user object based on the user ID.
- It checks if the provided user ID matches the user’s ID and returns the user object or
None
accordingly.
Creating a user:
- An instance of the
User
class is created, representing a specific user. - This is just a sample user for demonstration purposes.
Registering the user with Flask-Login:
- The
load_user
function is registered as the user_loader callback for Flask-Login. - This tells Flask-Login how to load the user object based on the user ID.
Defining the login route:
- The
/login
route is defined with the@app.route
decorator. - It handles both GET and POST requests.
- GET requests render the login form, while POST requests process the form submission for user login.
Handling user authentication in the login route:
- If a POST request is received (i.e., form submission), it retrieves the username and password from the request data.
- It checks if the provided credentials match the user’s credentials.
- If the credentials match, the user is logged in using the
login_user
function, and the user is redirected to a protected page (/protected
).
Defining the logout route:
- The
/logout
route is defined to handle user logout. - It logs out the currently logged-in user using the
logout_user
function and redirects the user to the home page ('/login'
).
Defining the protected route:
- The
/protected
route is defined as a protected route that requires authentication. - The
@login_required
decorator ensures that only authenticated users can access this route. - If a user is authenticated, the protected page is rendered.
Running the Flask app:
- The app is run using
app.run()
with thedebug
mode enabled.
To use this code, you will need to have Python and Flask installed. Once you have installed Python and Flask, you can create a new directory and save the code above in a file called app.py
. Then, you can run the app with the following command:
python app.py
Once the app is running, you can visit the following URLs in your web browser:
http://localhost:5000/login
- This will load the login page.http://localhost:5000/protected
- This will redirect you to the login page if you are not logged in. If you are logged in, you will be able to view the protected route.
Test your application
Enter the username and password in the login page.
If you enter the incorrect credentials, you will see an error messge on the login page:
Error message :
Access the protected Route
Next, enter the correct credentials. Once you are successfully logged in, you can access the protected page:
That’s it! Your application has login and logout functionality now. Only admin users can access the protected route! Perfect!
All the code for this is available on Github:
That’s it for this article! Feel free to leave feedback or questions in the comments. If you found this an exciting read, leave some claps and follow! I love coffee, so feel free to buy me a coffee at https://paypal.me/pythoncodenemesis XD. Cheers!