Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

422 Error with @jwt_required() in Flask App Deployed on VPS with Nginx #563

Closed
mhammadzahi opened this issue Nov 22, 2024 · 8 comments
Closed

Comments

@mhammadzahi
Copy link

Hi everyone,
I'm facing an issue while deploying my Flask application on a VPS server with Nginx. The app works fine when tested locally and also when hosted on Heroku. However, when deployed on my VPS, any route protected by @jwt_required() throws a 422 error.

Server Setup: Ubuntu VPS Nginx as a reverse proxy Flask Development Server to run the Flask app (just for test) Flask-JWT-Extended for JWT authentication

What Works: All API routes without the @jwt_required() decorator work perfectly. The same application works as expected (even with @jwt_required()) when deployed on Heroku.

What Fails: Any route using the @jwt_required() decorator on the VPS setup returns a 422 error. Removing @jwt_required() allows the routes to work normally.

I suspect it might have something to do with Nginx configurations, but I can’t figure out what. Could it be related to how headers or JSON bodies are being handled by the server? Any suggestions or troubleshooting tips would be greatly appreciated! Thanks in advance!

@vimalloc
Copy link
Owner

Hrm... this sounds vaguely familiar, but it's been a very long time since I've done any nginx configuration, and I'm not seeing anything specific off hand. Some questions to help troubleshoot this further:

  • are you using headers or cookies to pass in the JWTs?
  • what does the message from the 422 response say?
  • what are you using behind ngnix to run the flask app (such as uwsgi)?
  • can you paste any relevant configurations, such as from nginx?

@mhammadzahi
Copy link
Author

mhammadzahi commented Nov 23, 2024

Hi Lily, I hope you're doing well, Thank you for your support!

the Errors says: 422 Unprocessable Entity,

I am using only Flask development server (jsut for test)

when I remove @jwt_required() decorator the request works fine and print the header normally! The same application works as expected (even with @jwt_required()) when deployed on Heroku.

@app.route('/upload', methods=['POST'])
@jwt_required()
def upload_file_view():
print(request.headers)
...
...

here is Nginx config:

server {
listen 443 ssl;
server_name name.com www.name.com;

ssl_certificate /etc/letsencrypt/live/name.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/name.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

client_max_body_size 100M;  # Set maximum body size for POST requests
client_body_timeout 240s;
client_header_timeout 240s;
keepalive_timeout 240s;
send_timeout 240s;

location / {
    # CORS headers
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;

    # Handle preflight OPTIONS request
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Content-Length' 700;
        add_header 'Access-Control-Max-Age' 1728000;
        return 204;
    }

    # Forward Authorization header for JWT
    proxy_set_header Authorization $http_authorization;
    
    # Forward Content-Type header for JSON or other request types
    proxy_set_header Content-Type $http_content_type;

    # Proxy pass to Flask app
    proxy_pass http://127.0.0.1:5000;  # Flask app address
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

}

@darknetehf
Copy link

@mhammadzahi , you need to add proper logging in your application to troubleshoot issues, without it we can only guess.
Maybe adding a temp route like this could give you a useful stack trace?
(Assuming you have already defined a logger to output to console and/or file)

@app.errorhandler(422)
def handle_exception(ex):
    logger.exception(ex)

If you can pinpoint the exact line of code that triggers the error, that would be a start. I don't know if your app runs as a service, but maybe try to run your app manually over SSH and look at console messages.

@menyDev
Copy link

menyDev commented Dec 2, 2024

I got the same issue as @mhammadzahi comments. I have an api deployed on google app engine, it was working great with version 4.6.0, but after the update to version 4.7.1 I only get 422 response. Currently, my solution was to return to version 4.6.0

@vimalloc
Copy link
Owner

vimalloc commented Dec 2, 2024

@mhammadzahi

You shouldn't be using the flask dev server like that. Per their docs

When running publicly rather than in development, you should not use the built-in development server (flask run). The development server is provided by Werkzeug for convenience, but is not designed to be particularly efficient, stable, or secure.

Here is the documentation for doing that provided by flask:

RE the error message, I need the actual message returned by the response of the 422 Unprocessable Entity. I also still need to know how you are sending the JWTs to your backend. If you are using cookies for example, it's entirely possible you are running into some cross origin issues based on the domain your flask app is being served on compared to the nginx host.

I think if you follow along with the official flask deployment instructions, and use a wsgi server configured with nginx, that will likely fix your issues.

@vimalloc
Copy link
Owner

vimalloc commented Dec 2, 2024

@menyDev That's not going to be the same issue as this ticket. The only difference between 4.6.0 and 4.7.1 is we added the JWT_VERIFY_SUB option, due to a change with the underlying PyJWT library. I suspect you're running into something along those lines if 4.6.0 is working and 4.7.1 is not. Please look over that, and if you're still running into issues open a new issue.

(see: #561)

@vimalloc vimalloc closed this as completed Dec 2, 2024
@mhammadzahi
Copy link
Author

mhammadzahi commented Dec 15, 2024

@vimalloc, You should not close it, I did not find the solution yet! your library is not working

@vimalloc
Copy link
Owner

vimalloc commented Dec 15, 2024

That is not correct, this library is in fact working correctly, it’s your nginx setup that has an issue. Please see my above comment for further steps you can take to resolve the issue.

If you are unable to resolve the issue using the above steps, then please provide the details of what you tried, as well as the additional details I had asked for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants