0

I'm trying to implement flask_jwt_extended to my flask app.

My Use Case is, I want to set Authorization headers to every request. So that when a @jwt_required decorator is decorated to a flask route it can be access if an access token is present on the Authorization headers. I've tried some solutions like the one below:

I use @app.after_request to attach headers to every request but still it gives me this response

{
  "msg": "Missing Authorization Header"
}

Here is my code:

@app.after_request
def add_headers(resp):
    access_token = session.get("access_token", None)
    if access_token is not None:
        resp.headers["Authorization"] = f"Bearer {access_token}"
        return resp
    return resp

my login route:

@app.route('/', methods=["GET", "POST"])
def login():
    if request.method == "POST":
        form = request.form
        _username = form["username"]
        _password = form["password"]
        for username in Users:
            if username.get(_username):
                if safe_str_cmp(username[_username]["password"],_password):
                    access_token = create_access_token(identity=username[_username]["user_id"], fresh = True)
                    session["access_token"] = access_token
                    res = make_response(redirect(url_for("home")))
                    res.headers["Authorization"] = f"Bearer {access_token}"
                    return res
                else:
                    return "Incorrect password"
        return f"Hello{_username} doesn't exist"
    return render_template("login.html")

Here is my protected route:

@app.route('/home')
@jwt_required
def home():
    res = Response(render_template("base.html"))
    return res

I've also tried adding my headers in the route,But it still the headers I specify are not recognize and still give me the same response message. Here's how do it

@app.route('/home')
@jwt_required
def home():
    access_token = session.get("access_token", None)
    print(access_token)
    if access_token is not None:
        res = Response(render_template("base.html"), headers={"Authorization" : f"Bearer {access_token}"})
        return res
    res = Response(render_template("base.html"))
    return res
  • Not sure what you tried to achieve here. My guess is, you wanted to send the token to the view so that you can use it with the next request made from view to your api layer? You have have set the bearer token in the request header, setting them in response header would have not achieved anything. A better way to deal with this scenario is probably using a session. – Zobayer Hasan Jan 05 '21 at 07:49

1 Answers1

0

Writing this for those who will come across this and are trying to implement an OAuth flow

Don't use decorators use middleware instead

I believe you should handle this in a middleware. In the middleware, you can set the authorization property of the 2nd parameter of the call function which contains the current wsgi app environment variables you have passed in your init function. Look at code below:

def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    cookie = Request(environ).cookies.get('access_token')
    if cookie is not None:
        environ['HTTP_AUTHORIZATION']='Bearer '+cookie
    return self.app(environ, start_response)
Night King
  • 455
  • 4
  • 12