Search code examples
pythonflaskjwtgunicornflask-restful

Flask Restful NoAuthorizationError Missing Authorization Header


I'm running Flask Restful on a server in production mode using Python 3.6 and hitting an endpoint that requires jwt auth, but I keep getting a "NoAuthorizationError Missing Authorization Header" error.

The strange part is that the very same request is sent using Postman to the local version of the exact same Flask app on my mac and it works just fine without any errors. The problem only occurs on the live server and all of the pip packages are the exact same version as well.

UPDATE I am using Gunicorn on the live server and when I stop the app and run normally using python run.py the error goes away and returns the correct response.

I have the following handlers set for jwt errors and again, it is caught on the local version of my app:

  • jwt.token_in_blacklist_loader
  • jwt.expired_token_loader
  • jwt.invalid_token_loader
  • jwt.revoked_token_loader
  • jwt.needs_fresh_token_loader
  • jwt.unauthorized_loader
  • jwt.claims_verification_failed_loader

For testing purposes I'm not sending a token in the request itself. Even if I do, the error still persists.

Here is the response locally on my mac:

{
    "errors": {
        "application": "Missing Authorization Header",
        "validation": null
    },
    "http_status": 401,
    "message": "There was a problem authenticating your token.",
    "status": 0,
    "time": 20
}

Here is the response on the live server:

Aug 29 17:15:15 [5168]: return self.dispatch_request(*args, **kwargs)
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_restful/__init__.py", line 595, in dispatch_request
Aug 29 17:15:15 [5168]: resp = meth(*args, **kwargs)
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 102, in wrapper
Aug 29 17:15:15 [5168]: verify_jwt_in_request()
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 31, in verify_jwt_in_request
Aug 29 17:15:15 [5168]: jwt_data = _decode_jwt_from_request(request_type='access')
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 284, in _decode_jwt_from_request
Aug 29 17:15:15 [5168]: raise NoAuthorizationError(errors[0])
Aug 29 17:15:15 [5168]: flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header

I have been attempting to track this issue here, but haven't had success.


Solution

  • For anyone else coming across this error, it's actually an issue with Flask Restful itself and how it handles errors.

    Solution #1

    The first solution that did work for me, was to propagate the exceptions... meaning that exceptions are re-raised instead of being handled by the app's error handlers. However, according to this it's not a great solution because it overrides Flask's native error handler functions: app.handle_user_exception and app.handle_exception.

    So you would set PROPAGATE_EXCEPTIONS in your app configuration:

    app.config['PROPAGATE_EXCEPTIONS'] = True
    

    Solution #2

    The final solution that I'm going with is to enhance the error handler of Flask's Api, based on a recent suggestion found here.

    from flask import Flask
    from flask_restful import Api
    
    class CustomApi(Api):
        def handle_error(self, e):
            for val in current_app.error_handler_spec.values():
                for handler in val.values():
                    registered_error_handlers = list(filter(lambda x: isinstance(e, x), handler.keys()))
                    if len(registered_error_handlers) > 0:
                        raise e
            return super().handle_error(e)
    
    app = Flask(__name__)
    api = CustomApi(app, prefix='/api/v2') # same params can be passed here