Cvmcosta / ltijs

Turn your application into a fully integratable LTI 1.3 tool provider.
https://cvmcosta.github.io/ltijs/
Apache License 2.0
299 stars 67 forks source link

CANVAS - LTI integration error - MISSING_VALIDATION_COOKIE #132

Closed tatikamsetti closed 2 years ago

tatikamsetti commented 2 years ago

Describe the bug We are trying to integrate the custom LTI App Media Resources into CANVAS. It works fine in MOODLE, but throws the following error - {"status":401,"error":"Unauthorized","details":{"description":"Error validating ltik or IdToken","message":"MISSING_VALIDATION_COOKIE"}}

We tried to set ltiaas=true but didn't fix the issue.

For the platform URL and end points, we tried both instructure test URL and our own URL PLATFORM_ENDPOINT=https://canvas.test.instructure.com/api/lti/authorize_redirect PLATFORM_TOKEN_ENDPOINT=https://canvas.test.instructure.com/login/oauth2/token PLATFORM_KEY_ENDPOINT=https://canvas.test.instructure.com/api/lti/security/jwks

Expected behavior LTI tool should be successfully integrated in to CANVAS.

Provider logs provider:main Login request: +1ms provider:main { provider:main response_type: 'id_token', provider:main response_mode: 'form_post', provider:main id_token_signed_response_alg: 'RS256', provider:main scope: 'openid', provider:main client_id: '148090000000000146', provider:main redirect_uri: 'https://preview.ccle.ucla.edu', provider:main login_hint: '9b29b67498c5163d94a9a0df53f5a589dd93d517', provider:main nonce: 'eogdgmzkyb9f9lz19otqw23vi', provider:main prompt: 'none', provider:main state: '53fd067db374bdd33e516b8760d76b912511ad9d61c8698117', provider:main lti_message_hint: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJpZmllciI6IjE4NDJkZDZkNjJkODVmNzQwMmFiNTA4MGZmZTFhYmM5MWE2ODA4NTFkODE5OWE5ZGE0MzZjMGQ3MDc0ZmFjOTRlZDMxN2JiMTE5Mjg2YjFhMzZjYjc2N2U5OWZiYjkzOGIzNTAyMjlhNTczYjI0MGQ5NTM1NTUzZmJkMWY4MjVjIiwiY2FudmFzX2RvbWFpbiI6InVjbGEudGVzdC5pbnN0cnVjdHVyZS5jb20iLCJjb250ZXh0X3R5cGUiOiJDb3Vyc2UiLCJjb250ZXh0X2lkIjoxNDgwOTAwMDAwMDAwMDAyMzEsImNhbnZhc19sb2NhbGUiOiJlbiIsImV4cCI6MTYzNTM2MDk0Nn0.8T4uPaGbgfKq55foC-3OEnBtnxbqXKsds67qiycHCkc' provider:main } +0ms provider:main Receiving request at path: / +2s provider:main Path does not match reserved endpoints +0ms provider:main Cookies received: +0ms provider:main [Object: null prototype] {} +0ms provider:main Received idtoken for validation +0ms provider:auth Response state: 53fd067db374bdd33e516b8760d76b912511ad9d61c8698117 +0ms provider:auth Attempting to validate iss claim +0ms provider:auth Request Iss claim: undefined +0ms provider:auth Response Iss claim: https://canvas.test.instructure.com +0ms provider:main Deleting state cookie and Database entry +2ms provider:auth Error: MISSING_VALIDATION_COOKIE provider:auth at Function.validateToken (/usr/local/mediaresources/lti-media-resources/node_modules/ltijs/dist/Utils/Auth.js:98:27) provider:auth at sessionValidator (/usr/local/mediaresources/lti-media-resources/node_modules/ltijs/dist/Provider/Provider.js:400:38) provider:auth at Layer.handle [as handle_request] (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/layer.js:95:5) provider:auth at trim_prefix (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:317:13) provider:auth at /usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:284:7 provider:auth at Function.process_params (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:335:12) provider:auth at next (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:275:10) provider:auth at serveStatic (/usr/local/mediaresources/lti-media-resources/node_modules/serve-static/index.js:75:16) provider:auth at Layer.handle [as handle_request] (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/layer.js:95:5) provider:auth at trim_prefix (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:317:13) provider:auth at /usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:284:7 provider:auth at Function.process_params (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:335:12) provider:auth at next (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:275:10) provider:auth at /usr/local/mediaresources/lti-media-resources/node_modules/ltijs/dist/Utils/Server.js:115:14 provider:auth at Layer.handle [as handle_request] (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/layer.js:95:5) provider:auth at trim_prefix (/usr/local/mediaresources/lti-media-resources/node_modules/express/lib/router/index.js:317:13) +33ms provider:main Passing request to invalid token handler +33ms

Screenshots If applicable, add screenshots to help explain your problem.

Ltijs version

NodeJS version

Platform used

Additional context Add any other context about the problem here.

rlorenzo commented 2 years ago

NOTE, we also checked to make sure our browsers were not blocking 3rd party cookies

Cvmcosta commented 2 years ago

Hello! My initial suggestion is to check the network tab of the browser, check the requests that are part of the LTI flow and the cookies being set by them, most browsers can tell you if a cookie is not being set properly and why.

tatikamsetti commented 2 years ago

@Cvmcosta Thank you for the quick response. I tried to verify cookie information on network tab. It shows no request cookies but only one response cookie

Screen Shot 2021-10-27 at 12 18 07 PM

.

Cvmcosta commented 2 years ago

Hello, sorry for the late reply. This cookie needs to be set for the LTI launch to work, the issue seems to be the cookie is not being with sameSite: None and secure: True. Please check the LTIjs setup method and set the cookie settings to the correct values or enable devMode on the general settings.

rlorenzo commented 2 years ago

@Cvmcosta Thanks that got rid of the error. I see in https://cvmcosta.me/ltijs/#/provider?id=cookie-configuration

You mentioned: If the platform and tool are in different domains, some browsers will not allow cookies to be set unless they have the secure: true and sameSite: 'None' flag

So we didn't RTFM.

But now we are getting another error that we are unsure of how to fix. On the React end, the client cannot seem to find the LTI key. Here is the code we are using to get the key: https://github.com/ucla/lti-media-resources/blob/master/src/client/services/ltik.js

If this is out of scope of the LTIjs app, then feel free to close this issue.

danny-does-stuff commented 2 years ago

@rlorenzo I just barely was able to figure this out with Canvas, so I may be of some help. In your onConnect on the server, how are you redirecting to the react app?

rlorenzo commented 2 years ago

@dannyharding10 Here is the code for our onConnect: https://github.com/ucla/lti-media-resources/blob/master/src/server/index.js#L36

Did you have to do something special to get Canvas to work? Do you happen to have your project on a public Github?

danny-does-stuff commented 2 years ago

Our project is private unfortunately. And looking at this code, I'm wondering is your problem in dev or in prod?

I did not have to do anything special to get Canvas to work, Canvas is actually the first platform we are implementing this for. The one thing I did to make sure the token was available to the frontend was to call lti.redirect, which will append the token onto the query string. However it looks like you're doing this.. is ltik appearing in the url after calling lti.redirect?

rlorenzo commented 2 years ago

@dannyharding10 For our deployment to Canvas we haven't tried dev, we have just been using production mode.

Where do we find the ltik in the url? We tried looking at the network tab when loading the app, but have been unsuccessful.

@tatikamsetti Are you able to find out what @dannyharding10 is talking about here? Can you try running the app in dev mode?

Also, @dannyharding10 we only call lti.redirect() if not in production mode, else we are serving the React client files.

danny-does-stuff commented 2 years ago

@rlorenzo ok I see what you're saying. lti.redirect has some fancy logic to stick the ltik onto the query when redirecting (something like domain.com/loginRoute?ltik=jwt.token.string). However for your prod setup, because you just call res.sendFile, the ltik doesn't get added anywhere. ltijs does have a setup to send a cookie that will include the ltik, but I never got the cookies to work because I didn't need it. However it seems like that's what you will need unless you can come up with another way to keep the ltik around. I would suggest checking to make sure that a new cookie is set during this launch sequence that includes the ltik. If you can get that to work, then you don't need to worry about manually sending the token with future requests because it will be in the cookie.

For what it's worth, my setup has it's own session storage, which is what I am using to keep the ltik around. Inside of onConnect I simply save the token to the current user's session, and then it is available on subsequent requests. It looks like your setup does not include express or express-session like mine has, but I thought I would share in case it gives you any ideas.

tatikamsetti commented 2 years ago

@rlorenzo and @dannyharding10 I tried to run the app in dev mode and got a different error - 'Localhost refused to connect' But I see that ltik has been generated and token has been validated succesfully. Here is the screenshot from Network tab:

Screen Shot 2021-11-09 at 2 51 41 PM Screen Shot 2021-11-09 at 2 54 47 PM
rlorenzo commented 2 years ago

@dannyharding10 Here is our code that tries to get the ltik token: https://github.com/ucla/lti-media-resources/blob/master/src/client/services/ltik.js

As you can see it is trying to get the ltik from the URL. Which is the same as the sample client code: https://github.com/Cvmcosta/ltijs-demo-client/blob/master/src/pages/home.js#L89

How do we try to get the token from the cookie? What would the name of the cookie be?

rlorenzo commented 2 years ago

@dannyharding10 NM, we got it working. We left the ltiaas mode on and that disabled cookies. With that off everything is working again.

tatikamsetti commented 2 years ago

@Cvmcosta and @dannyharding10 The issue is being resolved as @rlorenzo mentioned above. So closing the ticket. Thank you for all your help.