Skip to content

Commit 07a0e95

Browse files
Merge pull request #55 from raj-patra/flask-examples
Add Flask/jwt-authentication
2 parents e7b0c43 + d7ebdc8 commit 07a0e95

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

Flask/jwt-authentication/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## JWT Authentication in Flask
2+
3+
* What is JWT?
4+
5+
> JSON Web Token is a proposed Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key.
6+
7+
* How is it used?
8+
9+
> Generally when an user logs in a webpage, the client requests a JWT token based on the user credentials.
10+
11+
> The Server generates the token and sends it back to the client.
12+
13+
> The Client then uses this token to request any resource from the API.
14+
15+
> Without the token the Server marks all requests to protected routes as unauthorized.
16+
17+
* How can the client send the token for each request?
18+
19+
> The Recommended practice is to use the `Authorization` header while requesting the resource.
20+
21+
> Example: `Authorization: Bearer <token_here>`
22+
23+
24+
### Usage
25+
```
26+
SERVER SIDE
27+
28+
# Install the necessary packages
29+
pip install -r requirements.txt
30+
31+
# Run the flask app
32+
python app.py
33+
```
34+
35+
```
36+
CLIENT SIDE
37+
38+
headers = {
39+
"Authorization": "Bearer "+token
40+
}
41+
42+
axios.get(protected_url, headers=headers)
43+
.then(data => {
44+
console.log(data);
45+
})
46+
.catch(error => {
47+
console.log(error);
48+
})
49+
```

Flask/jwt-authentication/app.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""
2+
Flask Example - JWT Autentication in Flask
3+
Level - Intermediate
4+
Author - [Raj Patra](https:github.com/raj-patra)
5+
"""
6+
7+
# Importing flask module in the project is mandatory
8+
# An object of Flask class is our WSGI application.
9+
from flask import Flask, request
10+
11+
# Flask-RESTful is an extension for Flask that adds support for quickly building REST APIs.
12+
from flask_cors import CORS
13+
from config import Config
14+
15+
"""JSON Web Token is a proposed Internet standard for creating data with optional
16+
signature and/or optional encryption whose payload holds JSON.
17+
18+
The tokens are signed either using a private secret or a public/private key."""
19+
import jwt
20+
21+
# Flask constructor takes the name of current module (__name__) as argument.
22+
app = Flask(__name__)
23+
24+
# It is always a good practice to load the app configuration from a different file.
25+
app.config.from_object(Config())
26+
27+
# Enabling CORS allows our API to be used from all hosts.
28+
cors = CORS(app, resources={r"/*": {"origins": "*"}})
29+
30+
# This function whitelists certain functions from auth checking process.
31+
# It assigns an attribute `_no_auth` which will be checked prior to auth validation.
32+
def exclude_from_auth(func):
33+
func._no_auth = True
34+
return func
35+
36+
# The before_request decorator makes sure the encolsed function
37+
# is called before every request. Pretty handy to check for authentication.
38+
@app.before_request
39+
def check_auth():
40+
# Try-Catch can be used to trigger an exception incase
41+
# the request signature fails to validate (Unauthorizer)
42+
try:
43+
# If a valid endpoint is requested
44+
if request.endpoint in app.view_functions:
45+
# If `_no_auth` attribute does not exist
46+
if not hasattr(app.view_functions[request.endpoint], '_no_auth'):
47+
token = request.headers.get('Authorization').split(" ")[1]
48+
"""
49+
Common Practice of Sending JWT Token in a request
50+
51+
Headers:
52+
Authorization: Bearer <token>
53+
54+
"""
55+
jwt.decode(token, key=app.config["SECRET_KEY"], algorithms=["HS256"])
56+
# If decoding completes with no error we can proceed to
57+
# provide access to the resource
58+
else:
59+
return {"message": "Requested enpoint does not exist"}, 404
60+
except Exception as e:
61+
# If exception occurs it would be if the signature decode fails
62+
print(str(e))
63+
return {"message": "Unauthorized Request"}, 401
64+
65+
66+
# Since index routes is generally not a protected route
67+
# we can add exclude_from_auth decorater
68+
@app.route('/', methods=["GET", "POST"])
69+
@exclude_from_auth
70+
def index():
71+
if request.method == 'GET':
72+
return {"message": "Welcome to Demo-Flask-App"}, 200
73+
74+
75+
# This route would take JWT as Authorization Header to work
76+
@app.route("/hello/<user_name>")
77+
def say_hello(user_name: str = None):
78+
if user_name:
79+
return f"Hello, {user_name}"
80+
else:
81+
return 'Please provide a name "/hello/\{user_name\}"'
82+
83+
84+
# Example: How to send JWT token to Client which can be used by client to request other resources
85+
# This route can be used to create JWT tokens for a user in session
86+
@app.route("/signup", methods=["POST"])
87+
def signup():
88+
body = request.json
89+
body["token"] = jwt.encode(body, key=app.config["SECRET_KEY"], algorithm="HS256")
90+
return body
91+
92+
93+
if __name__ == '__main__':
94+
app.run(use_reloader=True)

Flask/jwt-authentication/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
class Config(object):
3+
DEBUG = True
4+
TESTING = False
5+
CORS_HEADERS = 'Content-Type'
6+
SECRET_KEY = "H3110 W0r1D"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Flask
2+
Flask-Cors
3+
jwt

0 commit comments

Comments
 (0)