AnsweredAssumed Answered

LTI and Cross-Origin Resource Sharing (CORS) issues (Code: 422)

Question asked by Simon Tysland on Nov 1, 2019
Latest reply on Nov 5, 2019 by Simon Tysland

Hello!

 

 

EDIT: I've figured out the problem. Check out my comment below

 

 

I have been struggling with this issue for an entire week, and I can't seem to figure it out.

 

 

We are making a educational game using Unity, to be integrated as an embedded WebGL build with LTI in canvas.

I have written the LTI integration and are able to launch the LTI from an course in Canvas (with proper post parameters which I can successfully validate with OAuth).

 

I am using LTILibrary for .net found here: GitHub - andyfmiller/LtiLibrary: LTI 1.1.1 library for .NET Applications.  (rewritten to not use async, as async does not work in webgl). This works great, no issues what so ever!

 

I am trying to do a grade passback to and read a grade from canvas. When doing a grade passback/read in a standalone application, or in Unity editor, I can successfully send the POST request and get the proper response (and the grade is passed to the student's grades successfully).

 

Now to my issue: When launching the LTI tool in Canvas and trying to do the grade passback and/or read grade request, I get the errors (turbodev (d0t) net is the domain the LTI tool is hosted on):

 

 

Now to the issue, is something wrong with the data/headers I am sending, or is the data/headers blocked by CORS-policy, thus throwing the 422 error?

 

I have tried so many different ways of figuring out this. Also tried sending the POST request with Ajax in html (outside of webgl build), with the same CORS error. Thought LTI tool's was designed to not cause CORS-policy issues. Weird thing is that it works just fine outside of the browser.

 

If anyone would be able to help me out, check my procedures and steps for errors, point my in the right direction or anything, I would be so glad.

 

For your information: Unity web requests is are implemented using the XMLHttpRequest class in JavaScript, using the browser to handle WWW requests. 

 

Full break down of how this is implemented (wall of text, wanted to include as much details as possible):

Disclaimer: I am using a Canvas test environment, via Canvas webpage by clicking "Try for free now" and creating an account. This means that I don't have admin rights, only teacher rights. But I can add the LTI in a course I've created.

 

  1. Generate LTI config XML: 

    <?xml version="1.0" encoding="UTF-8"?>
    <cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"
    xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"
    xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"
    xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"
    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd
    http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd
    http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd
    http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">
    <blti:title>TTG LTI test</blti:title>
    <blti:description>Debug LTI test application</blti:description>
    <blti:icon></blti:icon>
    <blti:launch_url>https://turbodev (d0t) net/HVL/LTI/</blti:launch_url>
    <blti:extensions platform="canvas.instructure.com">
    <lticm:property name="tool_id">d3b1h7a0e4j9a0b1b1</lticm:property>
    <lticm:property name="privacy_level">public</lticm:property>
    <lticm:property name="domain">turbodev (d0t) net</lticm:property>
    </blti:extensions>
    <cartridge_bundle identifierref="BLTI001_Bundle"/>
    <cartridge_icon identifierref="BLTI001_Icon"/>
    </cartridge_basiclti_link>

  2. Create a course
  3. Go to settings > Apps > View App Configurations > "+ App" (create app) > Paste XML option > Create Consumer key / secret and pasting LTI config xml > submit
  4. Go to assignments > Create assignment > Submission type: External Tool > I find the LTI tool I've created and the URL is entered > Save 

  5. Go to Course Home and enter "Student View" (in order to get lis_result_sourcedid), go to assignement and enter the assignement with the LTI tool
  6. LTI tool is launched and embedded 

  7. Every LTI parameter is successfully posted, including lis_outcome_service_url and lis_result_sourcedid (and is successfully OAuth as you can see at the bottom of the WebGL window)
  8. When clicking the "Read Result" button in the WebGL build, I send these headers and xml data (utf8 encoded), Note: ID's, consumer key and body hash is not sensitive, because this is a test environment and test application, thus no reason to hide them from public: 

     

    lis_outcome_service_url: https://canvas.instructure.com/api/lti/v1/tools/342507/grade_passback
    lis_result_sourcedid: 342507-1727279-12972729-24965083-ab99f8fb6b67e5bac471da61b8f95d614c36d8b0

     

    Method: POST
    Content-Type: application/xml
    Authorization: OAuth oauth_body_hash="bDk%2BNVTEzZhF%2FW0tpCM09PJdJm4%3D",oauth_consumer_key="ONE",oauth_nonce="23ce9be4105348be810f5d85779a10fd",oauth_signature="FYVsEie%2BNWikJGbRqbj6%2FNX7ZHQ%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1572611757",oauth_version="1.0"

     

    <?xml version="1.0" encoding="utf-8"?>
    <imsx_POXEnvelopeRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">
    <imsx_POXHeader>
    <imsx_POXRequestHeaderInfo>
    <imsx_version>V1.0</imsx_version>
    <imsx_messageIdentifier>6a1d537a-a919-4a7d-b0a2-65ce2a113f5e</imsx_messageIdentifier>
    </imsx_POXRequestHeaderInfo>
    </imsx_POXHeader>
    <imsx_POXBody>
    <readResultRequest>
    <resultRecord>
    <sourcedGUID>
    <sourcedId>342507-1727279-12972729-24965083-ab99f8fb6b67e5bac471da61b8f95d614c36d8b0</sourcedId>
    </sourcedGUID>
    </resultRecord>
    </readResultRequest>
    </imsx_POXBody>
    </imsx_POXEnvelopeRequest>

     

  9. As a response I get the 422 error and CORS-policy error (check screenshots above)
  10. When clicking the "Read Result" button in the Unity editor, I get the proper response (I've set the result to be 0.5 prior to this): 

    <?xml version="1.0" encoding="UTF-8"?>
    <imsx_POXEnvelopeResponse xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">
    <imsx_POXHeader>
    <imsx_POXResponseHeaderInfo>
    <imsx_version>V1.0</imsx_version>
    <imsx_messageIdentifier/>
    <imsx_statusInfo>
    <imsx_codeMajor>success</imsx_codeMajor>
    <imsx_severity>status</imsx_severity>
    <imsx_description/>
    <imsx_messageRefIdentifier>6a1d537a-a919-4a7d-b0a2-65ce2a113f5e</imsx_messageRefIdentifier>
    <imsx_operationRefIdentifier>readResult</imsx_operationRefIdentifier>
    </imsx_statusInfo>
    </imsx_POXResponseHeaderInfo>
    </imsx_POXHeader>
    <imsx_POXBody>
    <readResultResponse>
    <result>
    <resultScore>
    <language>en</language>
    <textString>0.5</textString>
    </resultScore>
    </result>
    </readResultResponse>
    </imsx_POXBody>
    </imsx_POXEnvelopeResponse>

 

Note: The course and the assignment is published

Outcomes