Flask-HTTPAuth icon indicating copy to clipboard operation
Flask-HTTPAuth copied to clipboard

Token is `None` in containerized setup

Open finngaida opened this issue 1 year ago • 16 comments

Posting here as I'm struggling to find information in other corners of the web. I'm running Flask on a Kubernetes Pod and struggling to properly authenticate my requests.

auth = HTTPTokenAuth(scheme="Bearer")

@auth.verify_token
def auth_verify_token(token: str):
    # ^ here I receive a value of `None`
    return "user"

# app setup, etc... 

@app.route("/test", methods=["GET"])
def test():
    print(request.headers.get('Authorization')) # prints "Bearer <token>" as expected
    return "OK" 

@app.route("/test2", methods=["GET"])
@auth.login_required
def test2():
    # this code is never run, as we get a 401 based on the issue above
    return "OK" 

I should note that when I run this setup locally via flask run everything works as expected.

Any hints, tips, suggestions greatly appreciated.

finngaida avatar May 10 '23 16:05 finngaida

Same versions of everything? You are likely using different versions of Flask, Werkzeug or Flask-HTTPAuth. I suggest you make sure you use the most up to date version of Flask-HTTPAuth, the recent releases of Flask broke some functionality that I had to fix.

miguelgrinberg avatar May 10 '23 16:05 miguelgrinberg

I am on Flask==2.3.2 and Flask-HTTPAuth==4.8.0, do you mean I should pull it from main?

finngaida avatar May 10 '23 17:05 finngaida

What about werkzeug? Did you have all the same versions compared to your working case locally?

miguelgrinberg avatar May 10 '23 18:05 miguelgrinberg

werkzeug==2.3.4 Yes, I built the container from the same source code I run locally, just behind gunicorn instead of the flask run debug server.

finngaida avatar May 10 '23 18:05 finngaida

Well, then I do not know. You must be missing some difference between the working and non working cases. The use of containers does not affect the way this extension works in any way, so I don't see how that can cause this.

miguelgrinberg avatar May 10 '23 18:05 miguelgrinberg

I'll update you here if I find out more

finngaida avatar May 11 '23 15:05 finngaida

Hi @miguelgrinberg , I also faced this issue. Seems like the token in 'verify_token' (Basic authentication) is None. I upgraded python version from 3.7 to 3.8 and in the requirements we don't lock versions for 'flask' and 'Flask-HTTPAuth'. After seeing this open issue I looked at the versions used. Indeed the versions were different than when it used to work. When locking the versions as they were in python3.7 (but still using 3.8) it does work. Is there any recommendation regarding the versions' combination? This is the combination that does work -

Werkzeug == 2.2.3
flask == 2.2.5
Flask-HTTPAuth == 4.8.0
(both python 3.7 and python 3.8)

This is the combination that didn't work (python 3.8)-

flask-2.3.2
Flask_HTTPAuth-4.8.0
Werkzeug-2.3.6

zivsh222 avatar Jun 23 '23 08:06 zivsh222

@zivsh222 Thanks for the additional information. There were some compatibility issues with the release of Flask 2.3, but those are fixed in the 4.8.0 version. I'm testing with the token_auth.py example in this repo and I'm not seeing any problems with the versions you reported as being problematic.

miguelgrinberg avatar Jun 23 '23 13:06 miguelgrinberg

Hi @miguelgrinberg , Thanks for checking. I haven't tried this example, but it seems like this sample uses 'bearer' while in my case it's 'basic'. Could it be related?

app = Flask(__name__)
app.auth = HTTPTokenAuth(scheme='Basic')

Also, we're using the decorator as @app.auth.verify_token instead of @auth.verify_token, but I don't think it matters.

zivsh222 avatar Jun 24 '23 12:06 zivsh222

@zivsh222 You can't send a token with the Basic scheme, there are rules about this scheme that tie it to the Basic Authentication described in the HTTP spec.

Flask 2.3 uses a more robust parser for the Authorization header, for that reason your token now is not parsed anymore. I suggest you switch to the Bearer scheme, which is intended for tokens.

miguelgrinberg avatar Jun 25 '23 07:06 miguelgrinberg

@miguelgrinberg , I don't have access to the calling API, I just implemented the app that gets the requests, but looking here It looks like it is in use. (we use HTTPS)

zivsh222 avatar Jun 25 '23 12:06 zivsh222

The example you linked shows username and password, that is not a token. Run the code through a base64 decoder to see the actual credentials.

miguelgrinberg avatar Jun 25 '23 12:06 miguelgrinberg

I solved this issue by changing my Werkzeug version to 2.2.3, i.e, I ran

pip install Werkzeug==2.2.3

and added this line to my requirements.txt:

Werkzeug==2.2.3

It was failing with these:

Flask==2.1.0
Flask-HTTPAuth==4.7.0
Werkzeug==2.3.6

And it is now working with these:

Flask==2.1.0
Flask-HTTPAuth==4.7.0
Werkzeug==2.2.3

All 2.3. versions cause failure.

LachlanGreen avatar Jun 30 '23 06:06 LachlanGreen

@LachlanGreen this is not a great solution. As I explained above, the problem is that your application is incorrectly using the Authorization header. In older versions of Werkzeug, the bad usage was not detected. Werkzeug 2.3 correctly rejects those bad headers, and for that reason your application fails. Instead of downgrading Werkzeug, you should fix your application to make correct use of the Authorization header.

miguelgrinberg avatar Jun 30 '23 10:06 miguelgrinberg

I am experiencing this too, using the Bearer scheme. Think something is wrong.

Roobxyz avatar Sep 06 '23 12:09 Roobxyz

I am experiencing this too, using the Bearer scheme.

Upgrade to 4.8.0 of flask-httpauth as there were improvements in getting the token from the auth packet. That fixed it for me.

flask==2.3.3 Flask-HTTPAuth==4.8.0

prophund avatar Sep 10 '23 09:09 prophund