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.

Home Page:https://dify.ai

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

Gitttttttt opened this issue · comments

Self Checks

  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
  • Please do not modify this template :) and fill in all the required fields.

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

@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.

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 .