langgenius / dify

Dify is an open-source LLM app development platform. Dify's intuitive interface combines AI workflow, RAG pipeline, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production.
https://dify.ai
Other
50.05k stars 7.15k forks source link

Reporting "KeyError: 'app_id' " while send request to api `/api/chat-messages` #5825

Closed Gitttttttt closed 4 months ago

Gitttttttt commented 4 months ago

Self Checks

Dify version

0.6.9

Cloud or Self Hosted

Self Hosted (Source)

Steps to reproduce

First, login with email and password; Then, send a request to the api /api/chat-messages with the token (or other login_required apis), it will show follow error: ERROR:app:Exception on /api/chat-messages [POST] Traceback (most recent call last): File "D:\miniconda3\envs\dify\lib\site-packages\flask\app.py", line 880, in full_dispatch_request rv = self.dispatch_request() File "D:\miniconda3\envs\dify\lib\site-packages\flask\app.py", line 865, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(view_args) # type: ignore[no-any-return] File "D:\miniconda3\envs\dify\lib\site-packages\flask_restful__init.py", line 489, in wrapper resp = resource(*args, kwargs) File "D:\miniconda3\envs\dify\lib\site-packages\flask\views.py", line 110, in view return current_app.ensure_sync(self.dispatch_request)(kwargs) # type: ignore[no-any-return] File "D:\miniconda3\envs\dify\lib\site-packages\flask_restful\init__.py", line 604, in dispatch_request resp = meth(*args, kwargs) File "D:\GitProject\wanwei\test\ww-dify\api\controllers\web\wraps.py", line 18, in decorated app_model, end_user = decode_jwt_token() File "D:\GitProject\wanwei\test\ww-dify\api\controllers\web\wraps.py", line 46, in decode_jwt_token app_model = db.session.query(App).filter(App.id == decoded['app_id']).first() KeyError: 'app_id' INFO:werkzeug:172.16.60.73 - - [01/Jul/2024 20:02:28] "POST /api/chat-messages HTTP/1.1" 500 -

And the debug info for the method decode_jwt_token() in the file api/controllers/web/wraps.py like this(Decoded has not key 'app_id'): image

So why does it get app_id from decoded? Is there anything wrong? Thanks for help

✔️ Expected Behavior

request correctly

❌ Actual Behavior

show errors

dosubot[bot] commented 4 months ago

@Gitttttttt Hello there! I'm here to help you with any bugs, questions, or contributions you have for the project. Let's tackle this issue together!

The KeyError: 'app_id' occurs because the app_id key is missing from the decoded JWT token. The decode_jwt_token function relies on the app_id key to query the App model. To resolve this issue, ensure that the JWT token being generated includes the app_id key in its payload.

Here's how you can modify the token generation process to include the app_id key:

  1. Modify the JWT Token Generation: Ensure that the app_id is included in the payload when generating the JWT token. Here is an example using the PassportService class:

    from flask import current_app
    import jwt
    
    class PassportService:
       def __init__(self):
           self.sk = current_app.config.get('SECRET_KEY')
    
       def issue(self, payload):
           return jwt.encode(payload, self.sk, algorithm='HS256')
    
       def verify(self, token):
           try:
               return jwt.decode(token, self.sk, algorithms=['HS256'])
           except jwt.exceptions.InvalidSignatureError:
               raise Unauthorized('Invalid token signature.')
           except jwt.exceptions.DecodeError:
               raise Unauthorized('Invalid token.')
           except jwt.exceptions.ExpiredSignatureError:
               raise Unauthorized('Token has expired.')
    
    def generate_jwt_token(app_id, end_user_id, app_code):
       payload = {
           'app_id': app_id,
           'end_user_id': end_user_id,
           'app_code': app_code,
           # other necessary fields
       }
       passport_service = PassportService()
       token = passport_service.issue(payload)
       return token
  2. Ensure app_id is Included: When generating the JWT token, make sure to include the app_id in the payload. This will allow the decode_jwt_token function to properly decode the token and retrieve the app_id key.

By including the app_id in the JWT token payload, the decode_jwt_token function will be able to retrieve it and avoid the KeyError [1][2].

To continue talking to Dosu, mention @dosu.

crazywoola commented 4 months ago

This is not a public an api. If you would like to get technical support on this part, please reach out to our business@dify.ai .