Flask JWT Example

Here is just a quick post today. I needed a quick and dirty example for a proof of concept I was thinking about and figured I may as well post about it.

Here is just a quick post today. I needed a quick and dirty example for a proof of concept I was thinking about and figured I may as well post about it.

Python is my default go to language when I am thinking about projects.  "How can I build that with Python?" I often think when an idea comes to mind.  I am working on a little proof of concept project and needed a quick API, so I always head over to the Flask framework as it is easy to get up and running.

Here is an example of implementing JWT encoding and decoding of tokens for authentication.

Head over to my github repo to download and play with it:

Create a virtualenv, then pip install -r requirements.txt to get the tools we will be using.  

GitHub - BitsofJeremy/flask_jwt_example
Contribute to BitsofJeremy/flask_jwt_example development by creating an account on GitHub.

How the encoding and decoding work

Open a Python REPL in the directory.  For this part we will just encode and decode a UUID.

Module imports.

import jwt
from datetime import datetime, timedelta
import uuid # for public id

There needs to be an app SECRET_KEY to hash up our data.

SECRET_KEY = 'test'

Here is our data we would like to pass secretly.

public_id = str(uuid.uuid4())

Encode our token with data claim, 30 minute expiration, SECRET_KEY, and algorithm.

token = jwt.encode({'public_id': public_id,'exp' : datetime.utcnow() + timedelta(minutes = 30)}, SECRET_KEY, algorithm='HS256')

Decode the token to get the data out.

data = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])

Example in the Python REPL

>>> import jwt
>>> from datetime import datetime, timedelta
>>> import uuid # for public id
>>> 
>>> SECRET_KEY = 'test'
>>> public_id = str(uuid.uuid4())
>>> 
>>> public_id
'33d97101-896a-4cf6-ba80-a2cef3a6cb0d'
>>> token = jwt.encode({'public_id': public_id,'exp' : datetime.utcnow() + timedelta(minutes = 30)}, SECRET_KEY, algorithm='HS256')
>>> 
>>> token
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwdWJsaWNfaWQiOiIzM2Q5NzEwMS04OTZhLTRjZjYtYmE4MC1hMmNlZjNhNmNiMGQiLCJleHAiOjE2MTkzMTAzOTd9.E_zuFQs35E8P7LKrPQyQC9YtrIxSvDQn8WvvDPR367U'
>>> data = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
>>> data
{'public_id': '33d97101-896a-4cf6-ba80-a2cef3a6cb0d', 'exp': 1619310397}
>>> public_id == data['public_id']
True
>>> 

Using this we can create simple auth for our web apps.

Example hitting the endpoints from the command line with HTTPie

Open a terminal and fire up the app.

source venv/bin/activate
pip install -r requirements.txt
python app.py

 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 206-073-131

Now open another terminal and try the following commands:

POST to create a new user

http -f POST http://localhost:5000/signup name=test email=test@email.com password=1234

example:


(venv) test@computer flask_jwt_example % http -f POST http://localhost:5000/signup name=test email=test@email.com password=1234
HTTP/1.0 201 CREATED
Content-Length: 24
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Apr 2021 00:21:30 GMT
Server: Werkzeug/1.0.1 Python/3.9.4

Successfully registered.

POST a login

http -f POST http://localhost:5000/login email=test@email.com password=1234

example:

(venv) test@computer flask_jwt_example % http -f POST http://localhost:5000/login email=test@email.com password=1234
HTTP/1.0 201 CREATED
Content-Length: 191
Content-Type: application/json
Date: Sun, 25 Apr 2021 00:21:41 GMT
Server: Werkzeug/1.0.1 Python/3.9.4

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwdWJsaWNfaWQiOiJiODE1OTNmMC00ZDg4LTRkNmItOWMyNC04ZmU0M2VkOWNmZjAiLCJleHAiOjE2MTkzMTE5MDF9._SSCOe0yU5msxAPqZh0q-nKJ_WXIu-dLYWRNTu3cuAM"
}

Copy the token between the quotes.  The GET the user endpoint

http http://localhost:5000/user x-access-token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwdWJsaWNfaWQiOiJiODE1OTNmMC00ZDg4LTRkNmItOWMyNC04ZmU0M2VkOWNmZjAiLCJleHAiOjE2MTkzMTE5MDF9._SSCOe0yU5msxAPqZh0q-nKJ_WXIu-dLYWRNTu3cuAM

example:

(venv) test@computer flask_jwt_example % http http://localhost:5000/user x-access-token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwdWJsaWNfaWQiOiJiODE1OTNmMC00ZDg4LTRkNmItOWMyNC04ZmU0M2VkOWNmZjAiLCJleHAiOjE2MTkzMTE5MDF9._SSCOe0yU5msxAPqZh0q-nKJ_WXIu-dLYWRNTu3cuAM
HTTP/1.0 200 OK
Content-Length: 160
Content-Type: application/json
Date: Sun, 25 Apr 2021 00:21:57 GMT
Server: Werkzeug/1.0.1 Python/3.9.4

{
    "users": [
        {
            "email": "test@email.com",
            "name": "test",
            "public_id": "b81593f0-4d88-4d6b-9c24-8fe43ed9cff0"
        }
    ]
}

Hope this helps someone in the future for simple proof of concepts.