AWS Cognito as Django authentication back-end for web site

Question:

My reading of Cognito is that it can be used in place of a local Django admin database to authenticate users of a website. However I am not finding any soup-to-nuts examples of a basic “Hello, World” app with a login screen that goes through Cognito. I would very much appreciate it if someone could post an article that shows, step-by-step, how to create a Hello World Django app and a Cognito user pool, and then how to replace the default authentication in Django with a call to AWS Cognito.

In particular I need to know how to gather the information from the Cognito admin site that is needed to set up a call to Cognito API to authenticate a user.

There are two cases to consider: App user login to App, and Admin login to django Admin URL of site. I assume that I would want to use Cognito for both cases, otherwise I am leaving a potential hole where the Admin URL is using a weaker login technology.

Current answers on AWS forums and StackExchange either say:

(1) It is a waste of time to use Cognito for authenticating a website, it is only for access to AWS resources

(2) It is not a waste of time. I am about to give up. I have gone as far as creating a sample Cognito user pool and user groups, and of scouring the web for proper examples of this use case. (None found, or I wouldn’t be writing.)

(3) https://github.com/capless/warrant, https://github.com/metametricsinc/django-warrant are two possible solution from the aws forums.

Asked By: Lars Ericson

||

Answers:

If you are reading this, you probably googled “aws cognito django” xD.

I just want to share what I did in order to get this thing to work:

  • Django-Warrant. Great aws cognito wrapper package.
  • Make sure to understand your current User model structure. If you use custom user model, don’t forget to map it using COGNITO_ATTR_MAPPING setting.
  • Change your authentication to support 3rd party connectivity. When you get from the client some Cognito token, convert it into your own token using oAuth/JWT/Session.

  • Rethink your login/register process. Do you want different registration? The django-warrant package supports it…

At the end of the day, this is a GREAT solution for fast authentication.

Answered By: Gal Silberman

To add to the accepted answer, there is a simple but very important extra step that I found was necessary to take to use django-warrant with Django 2.0:

The conditional in backend.py in the root package needs to be changed from:

    if DJANGO_VERSION[1] > 10

to:

    if DJANGO_VERSION[1] > 10 or DJANGO_VERSION[0] > 1:

Using django-warrant with Zappa and AWS Lambda:

The project I am working on also uses Zappa to enable the serverless deployment of my Django app to AWS Lambda. Although the above code fixed django-warrant for me when testing locally, after deploying the app to the Lambda environment, I had another significant issue stemming from some of django-warrant’s supporting packages – primarily related to python-jose-pycryptodome, which django-warrant uses during the authentication process. The issue showed itself in the form of a FileNotFound error related to the Crypto._SHA256 file. This error appears to have been caused because pycryptodome expects different files to be available in the Crypto package at runtime on Windows (which I am developing on) and Linux (the Lambda environment) respectively. I ended up solving this issue by downloading the Linux version of pycryptodome and merging its Crypto package with the Crypto package from the Windows version.

TLDR: If you want to use django-warrant with AWS Lambda and you are developing on a Windows machine, make sure to download the Linux version of pycryptodome and merge its Crypto package with the same from the Windows version.

Note: The versions of pycryptodome and python-jose (not python-jose-cryptodome) that I ended up using to achieve the above were 3.7.2 and 3.0.1 respectively.

Answered By: Isaac Doidge