Flask JWT - Sample

Page content

Flask & JWT

getting your hands dirty with Flask and JWT

Source

with some modifications by myself …

Environment

Test under macOS & OpenBSD, Poetry installed and working

Script

build virtual env

export app="app100"
export FLASK_APP="${app}/app"
poetry new ${app}
cd ${app}

set python 3.10

poetry env use $(which python3.10)
gsed -i "s/python = \"^3.*$/python = \"^3.10\"/" pyproject.toml
poetry lock

add packages

wget -4 -O requirements.txt https://raw.githubusercontent.com/GrahamMorbyDev/jwt-flask/master/requirements.txt
echo "marshmallow-sqlalchemy" >> requirements.txt
poetry add $(awk -F '==' '!/sha256/{print $1}' requirements.txt |tr '\n' ' ')
wget -4 -O ${app}/app.py https://raw.githubusercontent.com/GrahamMorbyDev/jwt-flask/master/app.py
poetry shell

create db

flask db_create
flask db_seed

build startup script

cat << EOF >run.sh
#!/usr/bin/env bash
export FLASK_APP="${app}/app"
poetry run flask run
exit 0
EOF
chmod 700 run.sh

run it

./run.sh

http://localhost:5000

Reverse Proxy Nginx

put a reverse Proxy in Front of the Application and you’re ready to test it

your.public.url.conf

#
# HTTPS Server your.public.url
#
server {

    listen        443 ssl;
    listen        [::]:443 ssl;
    server_name   your.public.url;

    access_log    /var/log/nginx/your.public.url.log main;
    error_log     /var/log/nginx/your.public.url-error.log;

    ssl_certificate_key         /path/to/your/private.key.pem;
    ssl_certificate             /path/to/your/full.chain.pem;

    location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_redirect off;
      proxy_buffering off;
      proxy_pass http://127.0.0.1:5000/;
    }

}

Test the Application

Login

Request Root

https your.public.url

failed

HTTP/1.1 401 UNAUTHORIZED
Connection: keep-alive
Content-Length: 39
Content-Type: application/json
Server: nginx

{
    "msg": "Missing Authorization Header"
}

Post Request to /login

https --form POST your.public.url/login email=admin@admin.com password=admin

sucess

HTTP/1.1 200 OK
Cache-Control: No-Store
Connection: keep-alive
Content-Length: 332
Content-Type: application/json
Date: Mon, 02 Jan 2023 20:30:19 GMT
Server: nginx

{
    "access_token": "eyJhbGciOiJIUzI1NiI-->8--snip--8<--TYZEUPNrBExi-h1FoiTA",
    "message": "Login Successful"
}

Test with Token

https your.public.url Authorization:"Bearer eyJhbGciOiJIUzI1NiI-->8--snip--8<--TYZEUPNrBExi-h1FoiTA"

sucess

HTTP/1.1 200 OK
Cache-Control: No-Store
Connection: keep-alive
Content-Length: 27
Content-Type: application/json
Date: Mon, 02 Jan 2023 20:32:35 GMT
Server: nginx

{
    "message": "Hello Flask!"
}

sha256: 64c0da7ee275d71fa31bda66f54f3caba8e46fc1f8458b389ffa004763178f9d