Skip to content

An example serverless web application using Flask and AWS Cognito with JSON Web Tokens (JWT) to protect specific routes, powered by API Gateway and Lambda

License

Notifications You must be signed in to change notification settings

mblackgeo/flask-cognito-jwt-example

Repository files navigation

Flask - AWS Cognito integration example

An example serverless web application using Flask and AWS Cognito with JSON Web Tokens (JWT) to protect specific routes, powered by API Gateway and Lambda.

Architecture

A high level overview of how the application works is as follows. The Flask application includes a number of blueprints:

  • home: a simple homepage that includes a login link.
  • auth: login, post-login, and logout routes.
  • private: routes that are only accessible after a user has logged in. If a user is not logged in these routes automatically redirect to the Cognito hosted UI.

When accessing the /login route, a user is redirected to the Cognito hosted UI. After successful authentication with the user pool, a JWT is returned to the app through the /postlogin endpoint which is stored in a httponly cookie; this cookie is valid for 30 mins and used to authorise access to any routes that are protected with the @auth_required decorator. The app itself uses flask-cognito-lib for the heaving lifting of validating JWTs and protecting specific routes.

For the deployment side, CDK python code is provided in /deploy. The CDK stacks will deploy the Flask application as a docker container to Lambda, with API Gateway in front. A Cognito User Pool is created along with a User Pool Client for the Flask application.

Getting started

Prequisites:

Setup as follows:

# setup the python environment with poetry
make install

# Populate the .env file the required parameters
cp .env.example .env
vi .env

# deploy the infra (Cognito, API Gateway, Lambda)
cd deploy
cdk deploy --all

# Populate AWS_COGNITO user pool parameters after deploying
# Obtain these values from the Systems Manager Parameter Store
vi .env

# run locally using Workzeug
make local  # or go to the AWS API Gateway URL

# check other useful commands
make help

The Makefile includes helpful commands for setting up a development environment, get started by installing the package into a new virtual environment and setting up pre-commit with make install. Run make help to see additional available commands (e.g. linting, testing, docker, and so on).

The application can be run locally through docker (make docker-build && make docker-run) or from the installed virtualenv with make local. The app should launched at http://localhost:5000 and a login link should redirect you to the Cognito hosted UI to sign up / sign in. Once logged in, a cookie will store the JWT and you will be redirected to the /private page. You may also view details of the JWT at the /token endpoint.

Development

  • Pytest is used for the functional tests of the application (see /tests).
  • Code is linted using flake8
  • Code formatting is validated using Black
  • pre-commit is used to run these checks locally before files are pushed to git
  • The Github Actions pipeline also runs these checks and tests

TODO

  • CORS
  • Serverless deployment with AWS CDK
  • Logout route should also hit the revoke Cognito endpoint
  • Handle JWT authenticated routes in local development (i.e. no Cognito) -> Set AWS_COGNITO_DISABLED to True
  • Populate parameters from SSM at runtime rather than deploy time

Credits

This project was inspired by the blog post Integrating Cognito with Flask by Martin Campbell.

About

An example serverless web application using Flask and AWS Cognito with JSON Web Tokens (JWT) to protect specific routes, powered by API Gateway and Lambda

Resources

License

Stars

Watchers

Forks