Welcome to our first lesson on authentication with Flask!
Today, we'll learn how to build a simple login system for our web application. This lesson is foundational because login systems are crucial for almost any web app that handles user data or personalized experiences.
By the end of this unit, you'll be able to create an endpoint that accepts login credentials, validates them, and responds accordingly.
Before we dive into building the login endpoint, let's set up our application and mock database.
Python1from flask import Flask, request, jsonify 2 3# Initialize a Flask app instance 4app = Flask(__name__) 5 6# Mock database of users 7database = [ 8 {"id": 1, "username": "cosmo", "password": "space-corgi"} 9]
This code initializes a Flask app and creates a mock dataset that we'll use for authentication.
To ensure the login credentials are in the correct format, we'll use Marshmallow to help us validate and deserialize input data.
Let's create a simple schema for our login data with username
and password
:
Python1from marshmallow import Schema, fields, ValidationError 2from marshmallow.validate import Length 3 4# Define a schema for the login data 5class LoginSchema(Schema): 6 username = fields.Str(required=True, validate=Length(min=1)) 7 password = fields.Str(required=True, validate=Length(min=1)) 8 9# Create an instance of LoginSchema 10login_schema = LoginSchema()
In this schema, we define username
and password
as required string fields, and use Length(min=1)
to ensure both fields are not empty.
Now, let's create the /login
endpoint in our Flask application. This is where users will send their login credentials.
Python1from flask import request, jsonify 2 3# Define a route to receive login credentials 4@app.route('/login', methods=['POST']) 5def login():
To validate the incoming data from the request we will use the LoginSchema
we previously defined.
Python1# Define a route to receive login credentials 2@app.route('/login', methods=['POST']) 3def login(): 4 try: 5 # Validate and deserialize the input data according to the schema 6 data = login_schema.load(request.get_json()) 7 except ValidationError as err: 8 # If validation fails, return an error message and a 400 status code 9 return jsonify(error=err.messages), 400
We can now extract the username
and password
from the validated data and check for the given username in our database.
Python1# Define a route to receive login credentials 2@app.route('/login', methods=['POST']) 3def login(): 4 try: 5 # Validate and deserialize the input data according to the schema 6 data = login_schema.load(request.get_json()) 7 except ValidationError as err: 8 # If validation fails, return an error message and a 400 status code 9 return jsonify(error=err.messages), 400 10 11 # Extract username and password from the validated data 12 username = data['username'] 13 password = data['password'] 14 15 # Find the user in the mock database 16 user = next((user for user in database if user["username"] == username), None)
Finally, once we know the user exists, we check if the given password matches with the one in the database. Then respond accordingly.
Python1# Define a route to receive login credentials 2@app.route('/login', methods=['POST']) 3def login(): 4 try: 5 # Validate and deserialize the input data according to the schema 6 data = login_schema.load(request.get_json()) 7 except ValidationError as err: 8 # If validation fails, return an error message and a 400 status code 9 return jsonify(error=err.messages), 400 10 11 # Extract username and password from the validated data 12 username = data['username'] 13 password = data['password'] 14 15 # Find the user in the mock database 16 user = next((user for user in database if user["username"] == username), None) 17 18 # Check if the user exists and if the password matches 19 if user and user["password"] == password: 20 # Login successful 21 return jsonify(message="Login successful"), 200 22 else: 23 # Return an error if the user does not exist or the password is incorrect 24 return jsonify(error="Bad username or password"), 401
When the client sends a POST request to /login
with correct credentials, they should receive a 200 OK
response with a message indicating a successful login:
JSON1{ "message": "Login successful" }
However, if the client provides incorrect credentials, they will receive a 401 Unauthorized
response indicating a bad username or password:
JSON1{ "error": "Bad username or password" }
Additionally, if the request fails validation, such as missing required fields, the client will receive a 400 Bad Request
response with error details:
JSON1{ "error": "Validation error details here" }
In this lesson, we learned to create a basic login endpoint using Flask by covering how to:
/login
endpoint to accept, validate, and authenticate user credentials.Next, you'll put this knowledge into practice by creating and testing your own login endpoint. In upcoming lessons, we'll explore JWT (JSON Web Token) authentication to further secure our application. Stay tuned and continue practicing!