Creating JWT Authentication in REST API in Flask


JSON Web Token is a string which is sent in HTTP request from the browser to the server to validate authenticity of the client. The browser stores the JWT and includes the token with every request in the header.
Now we will create app.py file.

app.py

#import necessary library
from flask import Flask, request
from flask_restful import Resource, Api, reqparse
from security import authenticate, identity
from flask_jwt import JWT, jwt_required, current_identity

#configuring your application
app = Flask(__name__)
app.secret_key = 'secret'

#Creating our Api
api = Api(app)

jwt = JWT(app, authenticate, identity)

JWT creates a new endpoint that is /auth.
We send username and password and jwt calls authenticate method and matches the password, if matches return user (returns jwt token) we can send this token to the next request we make. Afterwards, if a subsequent request has a token with it, jwt calls the identity function , then get the userid i.e. gets correct user that jwt token represents.
We will also make a User.py file that would represent the users.

User.py

class User(object):
    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

For the authenticate and identity methods for jwt authentication, we would create a security.py file.
security.py

from werkzeug.security import safe_str_cmp
from user import User
#users is the in-memory table of our registered users
users = [
    User(1, 'bob', 'asdf'),
    User(2, 'user2', 'abcxyz'),
]

#username_table would give the id, username, password from the userid_mapping, so we do not have to iterate over the users again and again
username_table = {u.username: u for u in users}
#userid_table is the userid mapping
userid_table = {u.id: u for u in users}

def authenticate(username, password):
    #None is the default value i.e if there is no username like the given.
    user = username_table.get(username, None)
    if user and safe_str_cmp(user.password, password):
        return user 

#Identity function takes in the payload (payload is the contents of the jwt token)
def identity(payload):
    #extract the user id from that payload
    userid = payload['identity']
    #retrieve the user which matches this userid
    return userid_table.get(userid, None)

Now we will complete the app.py file to add method that are GET and POST and would make the GET method authenticated.

from flask import Flask, request
from flask_restful import Resource, Api, reqparse
from security import authenticate, identity
from flask_jwt import JWT, jwt_required, current_identity
app = Flask(__name__)
app.secret_key = 'secret'
api = Api(app)
jwt = JWT(app, authenticate, identity)
#initializing an empty list of items
items = []

#api works with resources and a resource must be a class and inherits from the class Resource
class Item(Resource):
    #creating a parser for taking in the price argument
    parser = reqparse.RequestParser()
    parser.add_argument('price',
        type = float,
        required = True,
        help = "This field cannot be left blank!"
    )

    #we have to authenticate before calling get method. @jwt_required() is a decorator
    @jwt_required()
    #Creating a get method to get an item after authenticating with jwt token
    def get(self, name):
        #The filter() method constructs an iterator for which a function 
returns true.
        item = next(filter(lambda x: x['name'] == name,items), None)
        return {'item': item}, 200 if item else 404
        #if there is item then 200 else 404 status code

    def post(self, name):
        if next(filter(lambda x: x['name'] == name, items), None):
            return {'message': "An item with name '{}' already exists.".format(name)},400
        #taking in the input price argument from the parser
        data = Item.parser.parse_args()
        item = {'name': name, 'price':data['price']}
        items.append(item)
        return item, 201 

#Adding the resource to out api
api.add_resource(Item, '/item/<string:name>')

#The below code will run our app.
app.run(port=5000, debug=True)

Testing our Api endpoints with Api testing tool -POSTMAN
Running our app.py file in command prompt:
Capture0
Go to POSTMAN and create an POST request of /auth.
Add a header of Content Type of application/json
Capture1-1
In the body, select raw and type in the password and username.
Capture2.1
After hitting Send, an access token will be generated. Copy that token.
Creating a Post request of the item and adding the item1 to our item list.
Also add the same header of the Content type.
Capture3
In the body, type in the price of the item1 to be inserted.
Capture4
Creating a GET request which would get the item of the specified name (In our case- item1).
In the headers, add a Authentication header and type in β€œjwt” with the access token that we copied in the /auth endpoint.
Hit send and you will get the item1 you just inserted above using the GET request.
Capture5

The major application of JWT is providing security to you web applications.It can be used as an authentication system for web applications to securely transfer information over the web.

Question

Which decorator is used to make a method jwt authenticated?

@jwt_required
@jwt.user_claims_loader
@jwt_refresh_token_required
@jwt.user_identity_loader
@jwt_required is the decorator used to make a method JWT authenticated.

With this article at OpenGenus, you must have the complete idea of Creating JWT Authentication in REST API in Flask. Enjoy.