dmitry-viskov / pylti1.3

LTI 1.3 Advantage Tool
MIT License
110 stars 59 forks source link

Error: JWK must contain a "kty" parameter" #53

Open disazoz opened 2 years ago

disazoz commented 2 years ago

Tying to run flask example tool in Moodle. The game loaded successfully, and when JS trying get a score from Moodle, got this error.

127.0.0.1 - - [14/Oct/2021 03:20:09] "GET /api/scoreboard/lti1p3-launch-adcbe674-c539-46d7-bd71-a88fa3d41a6e/ HTTP/1.1" 500 - Traceback (most recent call last): File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2464, in call return self.wsgi_app(environ, start_response) File "c:\Users\disazoz\Desktop\test\pylti1.3-flask-example\game\app.py", line 26, in call return self.app(environ, start_response) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2450, in wsgi_app response = self.handle_exception(e) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1867, in handle_exception reraise(exc_type, exc_value, tb) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask_compat.py", line 39, in reraise raise value File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2447, in wsgi_app response = self.full_dispatch_request() File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1952, in full_dispatch_request rv = self.handle_user_exception(e) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1821, in handle_user_exception reraise(exc_type, exc_value, tb) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask_compat.py", line 39, in reraise raise value File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1950, in full_dispatch_request rv = self.dispatch_request() File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1936, in dispatch_request return self.view_functionsrule.endpoint File "c:\Users\disazoz\Desktop\test\pylti1.3-flask-example\game\app.py", line 222, in scoreboard scores = ags.get_grades(score_line_item) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 200, in get_grades lineitem = self.find_or_create_lineitem(lineitem, find_by=find_by) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 157, in find_or_create_lineitem lineitem = self.find_lineitem_by_tag(tag) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 142, in find_lineitem_by_tag return self.find_lineitem('tag', tag) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 117, in find_lineitem lineitems, lineitems_url = self.get_lineitems_page(lineitems_url) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 83, in get_lineitems_page accept='application/vnd.ims.lis.v2.lineitemcontainer+json' File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\service_connector.py", line 110, in make_service_request access_token = self.get_access_token(scopes) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\service_connector.py", line 87, in get_access_token raise LtiServiceException(r) pylti1p3.exception.LtiServiceException: HTTP response [https://learn.qweasd.su/mod/lti/token.php]: 400 - { "error" : "JWK must contain a "kty" parameter" }

Not sure if it related, but i'm using private and public keys that were in the example git repo. The Moodle platform just self hosted instance.

dmitry-viskov commented 2 years ago

hi @disazoz . How did you set Public Key on the Moodle side? From the Flask example JWKS URL (http://127.0.0.1:9001/jwks/) returns this:

{
  "keys": {
    "keys": [
      {
        "alg": "RS256", 
        "e": "AQAB", 
        "kid": "NtQYzsKs_TWLQ0p3bLmfM7fOwY0nEBVVH3z3Q-zJ06Y", 
        "kty": "RSA", 
        "n": "uvEnCaUOy1l9gk3wjW3Pib1dBc5g92-6rhvZZOsN1a77fdOqKsrjWG1lDu8kq2nL-wbAzR3DdEPVw_1WUwtr_Q1d5m-7S4ciXT63pENs1EPwWmeN33O0zkGx8I7vdiOTSVoywEyUZe6UyS-ujLfsRc2ImeLP5OHxpE1yULEDSiMLtSvgzEaMvf2AkVq5EL5nLYDWXZWXUnpiT_f7iK47Mp2iQd4KYYG7YZ7lMMPCMBuhej7SOtZQ2FwaBjvZiXDZ172sQYBCiBAmOR3ofTL6aD2-HUxYztVIPCkhyO84mQ7W4BFsOnKW4WRfEySHXd2hZkFMgcFNXY3dA6de519qlcrL0YYx8ZHpzNt0foEzUsgJd8uJMUVvzPZgExwcyIbv5jWYBg0ILgULo7ve7VXG5lMwasW_ch2zKp7tTILnDJwITMjF71h4fn4dMTun_7MWEtSl_iFiALnIL_4_YY717cr4rmcG1424LyxJGRD9L9WjO8etAbPkiRFJUd5fmfqjHkO6fPxyWsMUAu8bfYdVRH7qN_erfGHmykmVGgH8AfK9GLT_cjN4GHA29bK9jMed6SWdrkygbQmlnsCAHrw0RA-QE0t617h3uTrSEr5vkbLz-KThVEBfH84qsweqcac_unKIZ0e2iRuyVnG4cbq8HUdio8gJ62D3wZ0UvVgr4a0", 
        "use": "sig"
      }, 
      {
        "alg": "RS256", 
        "e": "AQAB", 
        "kid": "ZMWbDPXjPhc17r93sEH4QvLr7dNgKSm7EWD0OvFRcKo", 
        "kty": "RSA", 
        "n": "9m-JmFyK1vzg6XY9D_TiURXqhXTUDquxdkQzpeuqQlrUetSMCiUk7FyJXnox1pnccsA-i8gUDRhSIpJdH-p6HuKs8a2yxTxZ4AjzXwgAzf80HCe3E1UCx4Ed2g09tuwaRqQi43dsuf2sGPairbR4OfgCSMZkyeRVZdQKzV2Uj2w7rDTSJQtCpc4spD_58biCZgTweXD-F68xZh5FGTnVqGlPk8BOBbazIWTaMFsKdG0hHS1GtfO-yzoaBlzhvoLZN63GU40_el7iZWq4VTMfiG337qfcax8cp30LVlWGxRnUuLeGWOYmKPJUDeu8pZKLdybvqbWwOrX35B2JV1_LAjzcLCD6XOnQ9P9qwyAOgbTogvq4elROKJSWAliiXEv6wyT4oEVe-mlZcqxsbiot62ZZ3TKRFs7_25bmKhnfPoPc7d96rCTpF9lK4KrCBJOJLhhAGSsnlaZYiL55Vgl0TNCY7nk-UHWLFpqcgkjbPPjwaHxZ9PCX0L10Hore3gNxJgiNL-cNh-4Hb95K8ZW8GFgMVlGLqe7JHHetdic8c2je3IBCe_oGs33fC_aZPBdbOI0Bk8jxg12HI9eL1IHMNajexSjJ-yody3IcLafi2Fd5os0nDYGLMPpHf7URa7gnPOWTOOpwb5MZ3sSmc_rlKcDaZ66uMLATvKrJj7Eg1Hc", 
        "use": "sig"
      }
    ]
  }
}

As you may see all items contain required kty parameter. I may assume that you set public key manually in the incorrect format

disazoz commented 2 years ago

Thanks for the reply.

On the Moodle side I use Keyset URL option and put JWKS URL from PyLTI. Yes, I see, that PyLTI has kty in JWKS.

I just checked setup with manual RSA key on moodle side, and at least there are no kty error anymore. But the scoreboard still does not work. Getting this error after game is finished.

127.0.0.1 - - [20/Oct/2021 02:51:19] "POST /api/score/lti1p3-launch-43cfd02d-e1f7-46f3-b0e3-02eefd4d53fa/2/13/ HTTP/1.1" 500 - Traceback (most recent call last): File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2464, in call return self.wsgi_app(environ, start_response) File "c:\Users\disazoz\Desktop\pylti1.3-flask-example-master\game\app.py", line 24, in call return self.app(environ, start_response) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2450, in wsgi_app response = self.handle_exception(e) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1867, in handle_exception reraise(exc_type, exc_value, tb) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask_compat.py", line 39, in reraise raise value File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2447, in wsgi_app response = self.full_dispatch_request() File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1952, in full_dispatch_request rv = self.handle_user_exception(e) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1821, in handle_user_exception reraise(exc_type, exc_value, tb) File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask_compat.py", line 39, in reraise raise value File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1950, in full_dispatch_request rv = self.dispatch_request() File "C:\Users\disazoz\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1936, in dispatch_request return self.view_functionsrule.endpoint File "c:\Users\disazoz\Desktop\pylti1.3-flask-example-master\game\app.py", line 188, in score grades.put_grade(sc, sc_line_item) File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\assignments_grades.py", line 63, in put_grade content_type='application/vnd.ims.lis.v1.score+json' File "C:\Programs\WPy64-3771\python-3.7.7.amd64\lib\site-packages\pylti1p3\service_connector.py", line 124, in make_service_request raise LtiServiceException(r) pylti1p3.exception.LtiServiceException: HTTP response [https://learn.qweasd.su/mod/lti/services.php/5/lineitems/15/lineitem/scores?type_id=7]: 400 - []

dmitry-viskov commented 2 years ago

@disazoz it looks like Moodle issue. Check error details there

hmoffatt commented 2 years ago

I have this issue too. The problem is that the flask demo app is returning the keys in a 'keys' object in the /jwks endpoint rather than directly.

The fix to game.py is is

-    return jsonify({'keys': tool_conf.get_jwks()})
+    return jsonify(tool_conf.get_jwks())
mschwaig commented 2 years ago

I also tried to get the flask example project to work with Moodle the first error that I ran into had Moodle complain about something along the lines of (googled it because I can't reproduce it now without a fresh Moodle)

Exception - Argument 1 passed to Firebase\\JWT\\JWK::parseKeySet() must be of the type array, null given

That one was resolved by what @hmoffatt wrote above (thanks). i made a PR with that change (https://github.com/dmitry-viskov/pylti1.3-flask-example/pull/14) in the flask example repo.

I also ran into that

ylti1p3.exception.LtiServiceException: HTTP response [http://moodle/mod/lti/services.php/2/lineitems/3/li
neitem/scores?type_id=1]: 400 - []

that happened only on that same POST request, and for me that was caused by using the admin account to test. Once I switched to a student account for testing that error went away.

hmoffatt commented 2 years ago

@mschwaig the second issue might be https://github.com/dmitry-viskov/pylti1.3/issues/68, which is that the library does not check it has access to create line items before trying it.

mgarefal commented 1 year ago

Hello team, I still get the error Exception - Argument 1 passed to Firebase\JWT\JWK::parseKeySet() must be of the type array, null given dispite the change

hmoffatt commented 1 year ago

any suggestions?

Wrong URL? Do you see your JWKs endpoint being called?

I am using Moodle 4.0 latest and don't have any issue.

mgarefal commented 1 year ago

Thanks for the reply hmoffatt, Yes. The endpoint is working and it returns the keys. When I set the endpoint in the keyset url I get the error Argument 1 passed to Firebase\JWT\JWK::parseKeySet() must be of the type array, null given When insert the public key instead of keyset url, I get [https://**************/moodle401/mod/lti/services.php/2/lineitems?type_id=2]: 401 - { "status": 401, "reason": "Unauthorized", "request": { "method": "GET", "url": "/moodle401/mod/lti/services.php/2/lineitems?type_id=2", "accept": "application/vnd.ims.lis.v2.lineitemcontainer+json" } From what I have read the URL should be like this "url": "/moodle401/mod/lti/services.php/2/lineitems/scores?type_id=2", If I hard Code it for testing I get the No handler found error

I know that it is working for you because I have read the Issues. I am looking a way to debug the problem. I have also tried to simulate the tool with Postman, but with no success.

mgarefal commented 1 year ago

Hi hmoffatt, can you assist me, to do some tests with your working moodle and my tool? Maybe the problem is with my moodle setup, or the php version running the moodle. I suggest, If you have some time to spare and help me, to add my external tool in your moodle. If you are willing lets contact in private, to exchange data. Is it possible to send pm with git platform? Thanks in advance

hmoffatt commented 1 year ago

I've updated my Moodle to 4.1 and it's still working ok for me. You can find my Twitter account on my github profile and send me a DM there, I don't think there is a way to DM directly on github.

besonn commented 3 weeks ago

@mgarefal Hi there, did you fix this error? The same error occurred to me too. When I used public key instead of keyset url, I have got "status": 401,"reason": "Unauthorized".

besonn commented 1 week ago

@hmoffatt @dmitry-viskov Hello there, I am getting the same error. I have deployed Moodle on a public ip address. When I used public key instead of keyset url, I have got "status": 401,"reason": "Unauthorized". Argument https://github.com/dmitry-viskov/pylti1.3/issues/1 ($jwks) must be of type array, null given, called in [dirroot]/mod/lti/locallib.php happend when I used keyset url. And when I wanted to have the tool launched, HTTP 302 appeared, then I cannot get into the tools html. Looking forward to your reply. Thank you so much.