skip to Main Content

I have built an api with flask-restful and flask-jwt-extended and have correctly configured the validation passages for token expiration and invalidation. However, even though it has built the token expiration and invalid validation callbacks, api does not process correctly and reports the error: Signature has expired

On the server in the cloud, we have a Centos 7 x64 of 16gb ram, running the application using gunicorn in version 19.9.0. Using the miniconda to create the applications’ python environments.

In tests in the production environment, the application complains of the expired token. However in a test environment, using Ubuntu 18.04.2, x64 with 16 gb ram, using the same settings with miniconda and gunicorn, the application has no problems executing it, returning the correct message when the token expires.

My jwt.py

from flask import Blueprint, Response, json, request
from flask_jwt_extended import (JWTManager, create_access_token,
                                create_refresh_token, get_jwt_identity,
                                jwt_required)

from app.models.core import User

from .schemas import UserSchema
from .utils import send_reponse, user_roles


def configure_jwt(app):
    JWT = JWTManager(app)

    @JWT.expired_token_loader
    def my_expired_token_callback(expired_token):
        return Response(
            response=json.dumps({
                "message": "Expired token"
            }),
            status=401,
            mimetype='application/json'
        )

    @JWT.invalid_token_loader
    def my_invalid_token_callback(invalid_token):
        return Response(
            response=json.dumps({
                "message": "Invalid token"
            }),
            status=422,
            mimetype='application/json'
        )

Error log:

[2019-05-23 15:42:02 -0300] [3745] [ERROR] Exception on /api/company [POST]
Traceback (most recent call last):
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_restful/__init__.py", line 458, in wrapper
    resp = resource(*args, **kwargs)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 102, in wrapper
    verify_jwt_in_request()
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 31, in verify_jwt_in_request
    jwt_data = _decode_jwt_from_request(request_type='access')
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 266, in _decode_jwt_from_request
    decoded_token = decode_token(encoded_token, csrf_token)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/utils.py", line 107, in decode_token
    allow_expired=allow_expired
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/tokens.py", line 138, in decode_jwt
    leeway=leeway, options=options)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 104, in decode
    self._validate_claims(payload, merged_options, **kwargs)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 134, in _validate_claims
    self._validate_exp(payload, now, leeway)
  File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 175, in _validate_exp
    raise ExpiredSignatureError('Signature has expired')
jwt.exceptions.ExpiredSignatureError: Signature has expired

I’m trying to understand why the application is able to correctly return the token expiration message in the test environment, where in the production environment it returns the error code 500 Internal Server Error. In addition to fixing this problem in our application.

2

Answers


  1. Chosen as BEST ANSWER

    Based on this link found inside the project repository, I discovered that the problem is related to the flask configuration option called PROPAGATE_EXCEPTIONS, which must be True.

    The issue in the flask-jwt-extended repository that helped me find the answer.


  2. This comment states that Flask Restful needs to ignore JWT and JWT Extended Exceptions and provides a simple snippet that solves the issue.

    Copying the code from above link,

    from flask_jwt_extended.exceptions import JWTExtendedException
    from jwt.exceptions import PyJWTError
    
    class FixedApi(Api):
      def error_router(self, original_handler, e):
        if not isinstance(e, PyJWTError) and not isinstance(e, JWTExtendedException) and self._has_fr_route():
          try:
            return self.handle_error(e)
          except Exception:
            pass  # Fall through to original handler
        return original_handler(e)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search