0

I am building a flask webapp and I am trying to return custom error message in case of 401 error which is raised when auth header is missing. For Authentication I use Flask-Jwt-Extended. I want to overwrite expired_token_loader(callback) to return 401 error and then catch it using @app.errohandler(401) and redirect to login.
So far I have done this:

@jwt.unauthorized_loader
def unauthorized_callback(callback):
    # Missing auth header
    # abort(401)
    return make_response("", 401)

@app.errorhandler(401)
def unauthorized(e):
    return "Custom 401 Error", 401

Found out in official Flask-JWT-Extended documentation that the function decorated with @jwt.unauthorized_loader must return a Flask Response.

So when I try to abort(401) as it is shown above and not return anything from unaturhorized_callback() it shows werkzeug.exceptions.Unauthorized: 401 Unauthorized: ...

And when I return make_response("", 401) it shows this, that means that the error handler did not handle the error:
enter image description here

EDIT: I am trying to redirect on trigger of the @jwt.unauthorized_loader so I wanted to throw an 401 error and then catch it with for example @app.errorhandler(401) and redirect.
I am doing this because I am also building a mobile app where I am catching 401 error and when I redirect inside the @jwt.unauthorized_loader it is always error 302, otherwise the redirect won't work. So I cannot do make_response(redirect("/login"), 401). So my goal is to throw 401 error and then handle it different ways in web app and mobile app. Thank you for help.

jestrabikr
  • 420
  • 5
  • 12

2 Answers2

0

I believe the reason this isn't working is because the callback method for @jwt.unauthorized_loader is already called in the context of an @app.errorhandler, and any exception raised in an errorhandler will not cause trigger other errorhandlers.

Instead of trying to handle this with aborts and exceptional control flow, why not just use a helper method to make your custom response and use it in both places?

def unauthorized_response():
    return make_response("Custom 401 Error", 401)

@jwt.unauthorized_loader
def unauthorized_callback(callback):
    return unauthorized_response()

@app.errorhandler(401)
def unauthorized(e):
    return unauthorized_response()
vimalloc
  • 3,869
  • 4
  • 32
  • 45
  • Thank you so much for help. I am trying to redirect on trigger of the `@jwt.unauthorized_loader` so I wanted to throw an 401 error and then catch it with for example `@app.errorhandler(401)` and redirect. I am doing this because I am also building a **mobile app** where I am catching 401 error and when I redirect inside the `@jwt.unauthorized_loader` it is always error 302, otherwise the redirect won't work. So I cannot do `make_response(redirect("/login"), 401)`. **So my goal is to throw 401 error and then handle it different ways in web app and mobile app**. **Thanks for you help** – jestrabikr Aug 29 '21 at 12:07
0

Not exactly what I wanted but in the end it did what I need. Insted of redirecting with custom http response code I did render_template with 401 code as shown below:

@jwt.unauthorized_loader
def unauthorized_callback(callback):
    # Missing auth header
    flash("Missing auth header please login")
    return make_response(render_template("login.html"), 401)
jestrabikr
  • 420
  • 5
  • 12