DEV Community

Cover image for Json Web Tokens
Ezekiel
Ezekiel

Posted on

Json Web Tokens

⭐Contribute to source code


What are JWT's

JWT's represent a way to authorize clients without sharing sensitive information. There are some resources that the clients need to send that need some authentication of some sort.
For example in a blog application, The user needs to be logged in to create and publish a blog. JWT's can help to verify authentication to make sure that the request is valid.


JWT Sequence Diagram

  1. The User logs in to his account on the client
  2. The client sends the user's credential to the server to validate login
  3. Server validates login and sends token
  4. User performs an action that requireqs authentication
  5. Client creates a request and puts token in the header of the request
  6. Server validates JWT, performs necessary action and returns appropriate response
  7. Client displays result to the user.

There is also the Time Limit of a JWT which means the time span for the token to be valid in which after the time span the user will need to enter his credentials again


Using JWT in Flask

To use JWT in flask-api, install the flask_jwt_extended extension

pip install flask-jwt-extended
Enter fullscreen mode Exit fullscreen mode

in your .env file or where you keep secret keys, insert 2 fields.

JWT_SECRET_KEY=aRandomHash
JWT_ACCESS_TOKEN_EXPIRES=30
Enter fullscreen mode Exit fullscreen mode

The JWT_SECRET_KEY is just as important as the SECRET_KEY for the flask app. The JWT_ACCESS_TOKEN_EXPIRES is used to decide the timespan for a valid JWT.

in your config.py file or app.py

config.py

class Config:

    SECRET_KEY = os.getenv("SECRET_KEY")
    JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY")
    JWT_ACCESS_TOKEN_EXPIRES = timedelta(minutes = int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES"))) # remember to import timedelta from datetime module

    @staticmethod
    def init_app(app):
        pass
Enter fullscreen mode Exit fullscreen mode

or

app.py

from flask-jwt-extended import JWTManager
from datetime import timedelta
# Other imports

app.config['JWT_SECRET_KEY'] = os.getenv("JWT_SECRET_KEY")
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(minutes = int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES")))
app = Flask(__name__)
jwt = JWTManager(app)
Enter fullscreen mode Exit fullscreen mode

In the login endpoint of your api, insert this

from flask_jwt_extended import create_access_token
from flask_restful import Resource
from flask import request

class Login(Resource):

    def post(self):
        if request.is_json:
            username = request.json['username']
            user = User.query.filter_by(username = username).first()  # Retrieve user from the database

        if user and user.verify_password(request.json['password']): #check if user exists and password is correct
            access_token = create_access_token(identity = username) # create JWT Token and send to user
            return {'access_token' : access_token}, 200
            
    # Handle Errors

        elif not user: 
            return {'Message' : 'User not found'}, 404

        elif not user.verify_password(request.json['password']):
            return {'Message' : 'Incorrect password'}, 401
Enter fullscreen mode Exit fullscreen mode

Flask-RESTful was used to create the api's, not regular flask

In any area of your app that needs authorization and authentication, do this

 @jwt_required() # to indicate that jwt is required for this request
    def post(self):  

        data = request.get_json() # collect blog data
        blog_schema = CreateBlogSchema() # create marshmallow schema to validate blog schema
        
        try:
            new_blog = blog_schema.load(data) # try to create a new blog

        except ValidationError as error:
            abort(400, error.messages)m# catch errors if any and return them as response messages

       db.session.add(new_blog)
       db.session.commit()
       return {'Message' : 'Operation Successful'}, 201
Enter fullscreen mode Exit fullscreen mode

Marshmallow was used for the schema and FLask-SQlalchemy was used for the databases.

If you have any questions feel free to drop them down 👇 in the comments

Top comments (0)