pallets-eco / flask-jwt

JWT (JSON Web Tokens) for Flask applications
MIT License
564 stars 177 forks source link

Default handler returns Bad Request, but default error code is 401 #88

Open CptSpaceToaster opened 8 years ago

CptSpaceToaster commented 8 years ago

https://github.com/mattupstate/flask-jwt/blob/master/flask_jwt/__init__.py#L113-L128 and https://github.com/mattupstate/flask-jwt/blob/master/flask_jwt/__init__.py#L182-L193

401 is Unauthorized 400 is Bad Request

401 Bad Request is not a thing.

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1

It looks like the default was changed in this commit

I'm not sure if the default should be changed back, or if the default request handler should return Unauthorized instead. There appears to be some back and forth here.

The RFC appears to indicate that 400 Bad Request is the "most correct" response, but stack overflow, and some RESTful examples seem to interpret 401 Unauthorized more loosely, and return 401 when users fail to provide the correct credentials.

CptSpaceToaster commented 8 years ago

Currently able to use this as a workaround:

from werkzeug.http import HTTP_STATUS_CODES

# inverse lookup for status codes
iHTTP_STATUS_CODES = {error: status for status, error in HTTP_STATUS_CODES.items()}

The inverse status code dictionary can be used to lookup the correct status code, and we can re-write the default error handler.

@jwt_ext.jwt_error_handler
def error(error):
    code = iHTTP_STATUS_CODES.get(error.error, error.status_code)

    return {
        'error': error.error,
        'description': error.description,
        'status': code
    }, code, error.headers

Note, I'm currently using flask-api. Other flask users likely have to pass the return dictionary into jsonify()