Lesson 1
Creating a Basic Login Endpoint
Creating a Basic Login Endpoint

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.

Initial Setup

Before we dive into building the login endpoint, let's set up our application and mock database.

Python
1from 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.

Introducing Marshmallow for Data Validation

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:

Python
1from 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.

Creating the Login Endpoint

Now, let's create the /login endpoint in our Flask application. This is where users will send their login credentials.

Python
1from flask import request, jsonify 2 3# Define a route to receive login credentials 4@app.route('/login', methods=['POST']) 5def login():
Validating Incoming Login Data

To validate the incoming data from the request we will use the LoginSchema we previously defined.

Python
1# 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
Extracting and Authenticating User

We can now extract the username and password from the validated data and check for the given username in our database.

Python
1# 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)
Checking Credentials and Responding

Finally, once we know the user exists, we check if the given password matches with the one in the database. Then respond accordingly.

Python
1# 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
Accessing the Login Endpoint

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:

JSON
1{ "message": "Login successful" }

However, if the client provides incorrect credentials, they will receive a 401 Unauthorized response indicating a bad username or password:

JSON
1{ "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:

JSON
1{ "error": "Validation error details here" }
Summary and Next Steps

In this lesson, we learned to create a basic login endpoint using Flask by covering how to:

  • Validate data to ensure login credentials are well-formed.
  • Create a /login endpoint to accept, validate, and authenticate user credentials.
  • Handle errors with appropriate responses for validation failures and incorrect login attempts.

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!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.