flaskjwtflask-jwt-extended

Is it possible to set jwt to optional during runtime?


I am using Flask-JWT-Extended (https://pypi.org/project/Flask-JWT-Extended/) to secure my flask app. The jwt_required decorator takes optional as an argument. Nevertheless my flask app is created inside a class and I cannot set the optional argument before instantiating the class. Here is what I tried:

from flask import Flask, jsonify
from flask_jwt_extended import jwt_required, JWTManager

jwt_optional = False


class Node:

    def __init__(self, name: str, key: str, jwt_opt: bool = False):
        self.app = Flask(name)
        self.app.config['SECRET_KEY'] = key
        global jwt_optional
        jwt_optional = jwt_opt
        self.app.add_url_rule(rule='/get_token',
                              endpoint='get_token',
                              view_func=self.get_token,
                              methods=['GET'])

    @jwt_required(optional=jwt_optional)
    def get_token(self):
        print('Token success')
        return jsonify({'msg': 'Token success'})


if __name__ == '__main__':
    node = Node('Test Node', key='unsafe', jwt_opt=True)
    app = node.app
    app.config['TESTING'] = True
    jwt = JWTManager(app=app)
    test_app = app.test_client()
    response = test_app.get('/get_token')
    print(response.json)

I guess it's obvious that it does not work since the decorator is evaluated before I change the global variable.

Is it possible to make the token optional at runtime?


Solution

  • I also had to deal with the case of optional JWTs. What I ended up doing is putting the decorator on top of a generic function and then simply call that function during the route itself - or skip it, in case jwt_optional is True

    jwt_optional = True
    
    @jwt_required()
    def jwt_protection():
       pass
    
    # ...
    
    class Node:
      # ...
      def get_token(self):
        if jwt_optional is False:
            jwt_protection()
        print('Token success')
        return jsonify({'msg': 'Token success'})
    

    I thought this was a simple workaround, it might also help in your situation