Search code examples
python-3.xjwtflask-restfulflask-jwt-extended

flask_jwt_extended is throwing an error decoding my JWT. How can I capture it?


I'm having issues trying to capture a malformed JWT error in my app.

I'm using flask_jwt_extended and when I send a manually created JWT. I get this error message:

Error on request:
Traceback (most recent call last):
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/jwt/api_jws.py", line 180, in _load
    signing_input, crypto_segment = jwt.rsplit(b'.', 1)
ValueError: not enough values to unpack (expected 2, got 1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_restful/__init__.py", line 266, in error_router
    return self.handle_error(e)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_restful/__init__.py", line 458, in wrapper
    resp = resource(*args, **kwargs)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_jwt_extended/view_decorators.py", line 103, in wrapper
    verify_jwt_in_request()
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_jwt_extended/view_decorators.py", line 32, in verify_jwt_in_request
    jwt_data = _decode_jwt_from_request(request_type='access')
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_jwt_extended/view_decorators.py", line 267, in _decode_jwt_from_request
    decoded_token = decode_token(encoded_token, csrf_token)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_jwt_extended/utils.py", line 80, in decode_token
    encoded_token, verify=False, algorithms=config.algorithm
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/jwt/api_jwt.py", line 84, in decode
    payload, _, _, _ = self._load(jwt)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/jwt/api_jws.py", line 183, in _load
    raise DecodeError('Not enough segments')
jwt.exceptions.DecodeError: Not enough segments

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/werkzeug/serving.py", line 302, in run_wsgi
    execute(self.server.app)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/werkzeug/serving.py", line 290, in execute
    application_iter = app(environ, start_response)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_restful/__init__.py", line 269, in error_router
    return original_handler(e)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask_restful/__init__.py", line 269, in error_router
    return original_handler(e)
  File "/Users/desmondlim/.virtualenvs/rest-api/lib/python3.7/site-packages/flask/app.py", line 1719, in handle_user_exception
    return handler(e)
TypeError: invalid_token() takes 0 positional arguments but 1 was given

My token is just this

AUTH_T wrong-token

Which should fail.

I've created a project with the same error:

app.py

import resource as testing

from flask import Flask, jsonify
from flask_restful import Api
from flask_jwt_extended import JWTManager

from jwt import InvalidSignatureError


app = Flask(__name__)

app.config['JWT_SECRET_KEY'] = 'secret-key'
app.config['JWT_HEADER_TYPE'] = 'AUTH_T'
app.config['JWT_BLACKLIST_ENABLED'] = True
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh']
app.config['PROPAGATE_EXCEPTIONS'] = True
app.config['DEBUG'] = False


api = Api(app)
jwt = JWTManager(app)


@jwt.invalid_token_loader
def invalid_token():
    return jsonify({
        'message': 'Invalid token.',
        'error': 'invalid_token'
    }), 401


@jwt.revoked_token_loader
def revoked_token():
    return jsonify({
        'message': 'Token is revoked.',
        'error': 'revoked_token'
    }), 401


@app.errorhandler(InvalidSignatureError)
def invalid_signature():
    return jsonify({
        'message': 'Invalid signature token.',
        'error': 'wrong_token'
    }), 401


api.add_resource(testing.Testing, '/test')


if __name__ == '__main__':
    app.run(port=5000, debug=False)

resource.py

from flask_jwt_extended import jwt_required
from flask_restful import Resource


class Testing(Resource):

    @jwt_required
    def get(self):
        return {'message': 'okay'}, 200

This is very odd. From what I've read, what I've done should have solved the problem but it seems that the issue is still around. Anyone have any ideas on a fix? If anyone runs this does it work?

Desmond


Solution

  • As of version 3.21.0 of Flask-JWT-Extended, this will just work without having to make a custom decorator.