- Notifications
You must be signed in to change notification settings - Fork2
A (very) basic Flask REST API example using JWT Authentication
License
Toxe/python-flask-rest-jwt
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This is a simple Python REST API server using Flask and JWT (JSON Web Tokens). Itdoes not use a database or other persistent storage, instead it reads its data on startup fromdata.json and provides some simple database functions for data manipulation and queries. All changes are lost on server shutdown.
The JWT authentication supports access and refresh tokens and token revoking by using an in-memory blacklist.
- Python 3
- Poetry
$ poetry install$ poetry shellFLASK_APP=mainFLASK_ENV=development
{"python.linting.pylintArgs": ["--load-plugins","pylint-flask" ]}Example user and ship data is stored indata.json.
$ flask routes --sort ruleEndpoint Methods Rule------------------------- ------- -----------------------api.get_ships GET /api/shipsapi.create_ship POST /api/shipsapi.get_ship GET /api/ships/<int:id>api.update_ship PUT /api/ships/<int:id>api.delete_ship DELETE /api/ships/<int:id>api.get_users GET /api/usersapi.create_user POST /api/usersapi.get_user GET /api/users/<int:id>api.update_user PUT /api/users/<int:id>api.delete_user DELETE /api/users/<int:id>auth.login POST /auth/loginauth.logout_access_token DELETE /auth/logoutauth.logout_refresh_token DELETE /auth/logout2auth.refresh POST /auth/refreshstatic GET /static/<path:filename>flask runRun either of:
pytestpython3 -m pytest$ curl -i http://localhost:5000/auth/login -X POST -d '{"username":"user", "password":"password"}' -H "Content-Type: application/json"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 568Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 12:56:25 GMT{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDczODUsIm5iZiI6MTU4OTU0NzM4NSwianRpIjoiMDE5NmJkMjAtZGMxOC00NTI0LWEzM2UtNWEzYTZiNGMxZTQ2IiwiZXhwIjoxNTg5NTQ4Mjg1LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.7Jeg7_Yv22vzKAM6ZfOgp5JQjEGAJLWB_k6qDpfx5HU", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDczODUsIm5iZiI6MTU4OTU0NzM4NSwianRpIjoiMmFhZDQxNTEtMDFmNi00YzM4LWFiYjctZWE2M2YyYjhlMjE3IiwiZXhwIjoxNTkyMTM5Mzg1LCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.SazEtt-odtprlo2eD8XiE90chQm87PfYt7UyMj5rvVk"}$ curl -i http://localhost:5000/auth/refresh -X POST -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDczODUsIm5iZiI6MTU4OTU0NzM4NSwianRpIjoiMmFhZDQxNTEtMDFmNi00YzM4LWFiYjctZWE2M2YyYjhlMjE3IiwiZXhwIjoxNTkyMTM5Mzg1LCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.SazEtt-odtprlo2eD8XiE90chQm87PfYt7UyMj5rvVk"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 293Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 12:57:56 GMT{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc0NzYsIm5iZiI6MTU4OTU0NzQ3NiwianRpIjoiNWE1Mzg0MGUtYjZmNS00ZTFkLTg3MGMtYzViNDliYmVkOGQzIiwiZXhwIjoxNTg5NTQ4Mzc2LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.4j4jonxmnAP1hFkJSCryIkKWOrMtJU02BqUIBUukpKA"}$ curl -i http://localhost:5000/auth/logout -X DELETE -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk2MTc4NzIsIm5iZiI6MTU4OTYxNzg3MiwianRpIjoiYzUwNDlkMmEtZWIyZS00M2I1LWIzNjgtMTJjYWFiMjA3ZTJjIiwiZXhwIjoxNTg5NjE4NzcyLCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.XoQtFc-a9ak4ON8TQ6rKYzz8IZWlYCeTZph4fomX-tw"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 44Server: Werkzeug/1.0.1 Python/3.8.2Date: Sat, 16 May 2020 08:32:18 GMT{ "message": "Successfully logged out."}$ curl -i http://localhost:5000/auth/logout2 -X DELETE -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk2MTc4NzIsIm5iZiI6MTU4OTYxNzg3MiwianRpIjoiYzA2YTA2NWEtMmJiYS00ZTJlLTliZTctY2Y0YWM4MWUwZDA2IiwiZXhwIjoxNTkyMjA5ODcyLCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.XsZ1cHcFhA60k4z87-bbuHBkRmWD6hKAXifzFq2NjOw"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 44Server: Werkzeug/1.0.1 Python/3.8.2Date: Sat, 16 May 2020 08:34:18 GMT{ "message": "Successfully logged out."}This will not return stored passwords.
$ curl -i http://localhost:5000/api/usersHTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 89Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 12:58:30 GMT[ { "id": 1, "name": "user" }, { "id": 2, "name": "guest" }]This will not return the user password.
$ curl -i http://localhost:5000/api/users/1HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 33Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 12:58:52 GMT{ "id": 1, "name": "user"}$ curl -i http://localhost:5000/api/users -X POST -d '{"name":"new user", "password":"secret"}' -H "Content-Type: application/json"HTTP/1.0 201 CREATEDContent-Type: application/jsonContent-Length: 37Location: http://localhost:5000/api/users/3Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 12:59:19 GMT{ "id": 3, "name": "new user"}Login required and can only change own data.
$ curl -i http://localhost:5000/api/users/3 -X PUT -d '{"name":"fancy new name", "password":"more secret"}' -H "Content-Type: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc3MDYsIm5iZiI6MTU4OTU0NzcwNiwianRpIjoiOTJjYTdhMTItY2Q4Yi00ZWJjLThlMWEtMjU1N2EwMGYwY2Y0IiwiZXhwIjoxNTg5NTQ4NjA2LCJpZGVudGl0eSI6MywiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.FLFRjkTAzpeT-ZOUsZmWegy5cn-EHM8EeC3Tskuu4Uc"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 43Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:02:09 GMT{ "id": 3, "name": "fancy new name"}Login required and can only delete the current user.
$ curl -i http://localhost:5000/api/users/3 -X DELETE -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc3MDYsIm5iZiI6MTU4OTU0NzcwNiwianRpIjoiOTJjYTdhMTItY2Q4Yi00ZWJjLThlMWEtMjU1N2EwMGYwY2Y0IiwiZXhwIjoxNTg5NTQ4NjA2LCJpZGVudGl0eSI6MywiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.FLFRjkTAzpeT-ZOUsZmWegy5cn-EHM8EeC3Tskuu4Uc"HTTP/1.0 204 NO CONTENTContent-Type: text/html; charset=utf-8Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:02:30 GMT$ curl -i http://localhost:5000/api/shipsHTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 4984Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:03:08 GMT[ { "affiliation": "Rebel Alliance", "category": "Starfighters", "crew": 1, "id": 1, "length": 13, "manufacturer": "Incom Corporation", "model": "T-65 X-Wing", "roles": [ "Space Superiority Starfighter", "Escort" ], "ship_class": "Starfighter" }, {"id": 2, ...}, {"id": 3, ...}, {"id": 4, ...}, {"id": 5, ...}, {"id": 6, ...}, {"id": 7, ...}, {"id": 8, ...}, {"id": 9, ...}, {"id": 10, ...}, {"id": 11, ...}, {"id": 12, ...}, {"id": 13, ...}, {"id": 14, ...}, {"id": 15, ...}]$ curl -i http://localhost:5000/api/ships/2HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 267Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:06:32 GMT{ "affiliation": "Empire", "category": "Starfighters", "crew": 1, "id": 2, "length": 7, "manufacturer": "Sienar Fleet Systems", "model": "TIE/LN Starfighter", "roles": [ "Space Superiority Starfighter" ], "ship_class": "Starfighter"}Login required.
$ curl -i http://localhost:5000/api/ships -X POST -d '{"ship_class":"Star Destroyer", "model":"Imperial I-class Star Destroyer", "affiliation":"Empire", "category":"Capital Ships", "crew":37085, "length":1600, "manufacturer":"Kuat Drive Yards", "roles":["Destroyer","Carrier","Military Transport","Command Ship"]}' -H "Content-Type: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc0NzYsIm5iZiI6MTU4OTU0NzQ3NiwianRpIjoiNWE1Mzg0MGUtYjZmNS00ZTFkLTg3MGMtYzViNDliYmVkOGQzIiwiZXhwIjoxNTg5NTQ4Mzc2LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.4j4jonxmnAP1hFkJSCryIkKWOrMtJU02BqUIBUukpKA"HTTP/1.0 201 CREATEDContent-Type: application/jsonContent-Length: 332Location: http://localhost:5000/api/ships/16Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:07:38 GMT{ "affiliation": "Empire", "category": "Capital Ships", "crew": 37085, "id": 16, "length": 1600, "manufacturer": "Kuat Drive Yards", "model": "Imperial I-class Star Destroyer", "roles": [ "Destroyer", "Carrier", "Military Transport", "Command Ship" ], "ship_class": "Star Destroyer"}Login required.
$ curl -i http://localhost:5000/api/ships/16 -X PUT -d '{"ship_class":"Star Destroyer", "model":"Imperial II-class Star Destroyer", "affiliation":"Empire", "category":"Capital Ships", "crew":37050, "length":1600, "manufacturer":"Kuat Drive Yards", "roles":["Destroyer","Carrier","Military Transport","Command Ship"]}' -H "Content-Type: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc0NzYsIm5iZiI6MTU4OTU0NzQ3NiwianRpIjoiNWE1Mzg0MGUtYjZmNS00ZTFkLTg3MGMtYzViNDliYmVkOGQzIiwiZXhwIjoxNTg5NTQ4Mzc2LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.4j4jonxmnAP1hFkJSCryIkKWOrMtJU02BqUIBUukpKA"HTTP/1.0 200 OKContent-Type: application/jsonContent-Length: 333Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:07:56 GMT{ "affiliation": "Empire", "category": "Capital Ships", "crew": 37050, "id": 16, "length": 1600, "manufacturer": "Kuat Drive Yards", "model": "Imperial II-class Star Destroyer", "roles": [ "Destroyer", "Carrier", "Military Transport", "Command Ship" ], "ship_class": "Star Destroyer"}Login required.
$ curl -i -i http://localhost:5000/api/ships/16 -X DELETE -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk1NDc0NzYsIm5iZiI6MTU4OTU0NzQ3NiwianRpIjoiNWE1Mzg0MGUtYjZmNS00ZTFkLTg3MGMtYzViNDliYmVkOGQzIiwiZXhwIjoxNTg5NTQ4Mzc2LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.4j4jonxmnAP1hFkJSCryIkKWOrMtJU02BqUIBUukpKA"HTTP/1.0 204 NO CONTENTContent-Type: text/html; charset=utf-8Server: Werkzeug/1.0.1 Python/3.8.2Date: Fri, 15 May 2020 13:08:25 GMTAbout
A (very) basic Flask REST API example using JWT Authentication
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.