Home > Blockchain >  flask jwt extended protect only specified request methods
flask jwt extended protect only specified request methods

Time:06-30

I have several general purpose routes in my API:

...
/api/general/user_types
/api/general/dlc_types
...

I want to have the GET method opened for all users without JWT token, but the POST, PUT and DELETE methods only accessible when the JWT token is included in the request.

The problem is that all these methods are allowed on the same route and I serve a different function based on the request method - GET = read, POST = create, PUT = update, DELETE = delete.

Any way to do this without separating the GET method into a separate route?

Here is how my routes are declared:

@general_api.route("/user_types", methods=["GET", "POST", "PUT", "DELETE"])
@jwt_required()
def user_types_crud():
    instance = ConstantsRoutes(UserTypes, "type")
    return crud_routes(request, instance)

The ConstantsRoute builds a CRUD class for the UserTypes table (SQLAlchemy model), and the crud_routes function takes a look at the request.method and returns the proper method (create|read|update|delete).

CodePudding user response:

I don't know of a build in decorator provided by the library. But if using a slightly extended version of the build in decorator is an option for you, you could define one as followed:

from functools import wraps
from flask import request, current_app
from flask_jwt_extended import verify_jwt_in_request

def jwt_required_for_methods(
    optional: bool = False,
    fresh: bool = False,
    refresh: bool = False,
    locations: LocationType = None,
    verify_type: bool = True,
    protected_methods: list[str] = ["GET", "POST", "PUT", "DELETE"]
) -> Any:

    def wrapper(fn):
        @wraps(fn)
        def decorator(*args, **kwargs):
            if request.method in protected_methods:
                verify_jwt_in_request(
                    optional, fresh, refresh,
                    locations, verify_type
                )
            return current_app.ensure_sync(fn)(*args, **kwargs)

        return decorator

    return wrapper

This way the JWT token is verified only of the request method is in the list passed as an argument. Protect your route with this decorator, where needed:

@general_api.route("/user_types", methods=["GET", "POST", "PUT", "DELETE"])
@jwt_required_for_methods(['POST', 'PUT', 'DELETE'])
def user_types_crud():
    instance = ConstantsRoutes(UserTypes, "type")
    return crud_routes(request, instance)

Hope i could help!

  • Related