How To: Create a Flask API with JWT-Based Authentication

How To: Create a Flask API with JWT-Based Authentication (Overview)

Photo by Matt Howard on Unsplash

This tutorial series provides step-by-step instructions and in-depth explanations to guide you through the process of creating a robust, production-quality REST API. The toolstack consists of Flask, Flask-RESTx, SQLAlchemy, pyjwt, tox and other packages. Code quality is a major focus, with considerable time dedicated to testing (using pytest), logging and tools such as coverage, flake8 and mypy. The tutorial concludes by creating a process that continuously integrates (with tox, travis/circle CI, coveralls) and deploys the API (with either Github or Azure DevOps to Heroku).

Part 1: Project Setup and Environment Configuration

Part 1: Project Setup and Environment Configuration

In Part 1, the core concepts of REST and JWTs are introduced, project dependencies are described and installed, and the project is fully configured for prod/dev environments. The flask server and CLI are demonstrated to ensure the setup was performed correctly before moving on to Part 2.

Part 2: Database Models, Migrations and JWT Setup

Part 2: Database Models, Migrations and JWT Setup

Part 2 covers the basics of SQLAlchemy, the Flask-SQLAlchemy extension, and the Flask-Migrate extension. The process of creating a new database table to store user information by defining a class and “registering” it with SQLAlchemy is demonstrated. Next, setting up a system that manages changes to a database schema is thoroughly explained and demonstrated. After initializing the database, functions to encode and decode JSON Web Tokens (JWTs) are created. This section concludes with an introduction to pytest fixtures and examples of several test cases that verify the ability to encode/decode JWTs issued by our API.

Part 3: API Configuration and User Registration

Part 3: API Configuration and User Registration

Part 3 explains how to initialize the Flask-RESTx extension and how API routes/endpoints are defined. In order to create an endpoint for new user registration, the modules and classes available in Flask-RESTx for parsing and validating request data are explored and demonstrated. Additionally, the process for serializing Python objects in order to send them in an HTTP response is covered. After implementing the user registration API endpoint, test cases are created and executed to verify the registration process is working correctly.

Part 4: JWT Authentication, Decorators and Blacklisting Tokens

Part 4: JWT Authentication, Decorators and Blacklisting Tokens

Part 4 completes the user authorization API by implementing login, logout and user verification API endpoints. The process to create a custom decorator that only allows access to users with a valid JWT is covered in-depth. How to send an HTTP request for a protected resource that includes a JWT is demonstrated with both Swagger UI and command-line tools. A new class/database model is introduced to create a token blacklist, to ensure that JWTs cannot be used after the user has logged out. Test cases are created and executed for all API endpoints covering successful and failed attempts to login/logout/retrieve user info.

Part 5: RESTful Resources and Advanced Request Parsing

Part 5: RESTful Resources and Advanced Request Parsing

Part 5 is dedicated to implementing a RESTful resource (a collection of ‘widgets’) with API endpoints that allow users to perform CRUD actions. In order to allow users to create a new widget, several advanced techniques for parsing request data are covered. Specifically, two custom ‘types’ are created since the built-in types provided by Flask-RESTx cannot fulfill our requirements. Finally, the custom request parser is integrated with the collection endpoint for the Widget API.

Part 6: Pagination, HATEOAS and Parameterized Testing

Part 6: Pagination, HATEOAS and Parameterized Testing

Part 6 completes the implementation of the Widget API. Since one of the requirements is to allow users to retrieve a paginated list of widgets, advanced techniques for serializing objects to JSON are demonstrated. Both the widget API model and the pagination API model are complex, requiring the use of several new classes from the Flask-RESTx fields module. The update and delete processes are implemented next and unit tests for all endpoint/request type combination are created and executed.