{"id":4069,"date":"2013-06-14T08:44:40","date_gmt":"2013-06-14T12:44:40","guid":{"rendered":"http:\/\/www.dr-chuck.com\/csev-blog\/?p=4069"},"modified":"2013-06-14T14:07:31","modified_gmt":"2013-06-14T18:07:31","slug":"receiving-grades-ims-lti-outcomes-signed-sourcedids","status":"publish","type":"post","link":"https:\/\/www.dr-chuck.com\/csev-blog\/2013\/06\/receiving-grades-ims-lti-outcomes-signed-sourcedids\/","title":{"rendered":"Receiving Grades  IMS LTI Outcomes: Signed sourcedids"},"content":{"rendered":"<p>This is a design for an approach to securely accept grades from an external tool and put those grades in the grade book.  Please review this design for security and feasibility.<\/p>\n<p><strong>Overview of the Structure of IMS Outcomes<br \/>\n<\/strong><\/p>\n<p>When you look at the <a href=\"http:\/\/www.imsglobal.org\/lti\/v1p1pd\/ltiIMGv1p1pd.html\" target=\"_blank\">IMS Learning Tools Interoperability 1.1<\/a> (LTI) Launch, there is a field called the <strong>lis_result_sourcedid<\/strong>.  If the administrator and instructor decide that a particular <strong>resource_link_id<\/strong> is to send grades to the grade book, they must create the column in the grade book and indicate which grade book column to accumulate grades for the particular resource.<\/p>\n<p>The <strong>lis_result_sourcedid<\/strong> must contain enough information to uniquely identify the <strong>resource_link_id<\/strong>, course, and particular row and column to store a grade for the user.  The value will be different for each tool launch from a different user.  When the external tool wants to set a grade for a user, it must present the <strong>lis_result_sourcedid<\/strong> for that <strong>user_id<\/strong>\/<strong>resource_link_id<\/strong> combination.   This value is completely opaque to the tool &#8211; the tool is not supposed to be able to parse or otherwise understand this string &#8211; the tool must simply receive the value, store it and then present it when attempting to set a a grade.<\/p>\n<p>This gives the Tool Consumer a wide range of choices as to how it constructs the <strong>lis_result_sourcedid<\/strong>.   This document describes the particular approach that I use and recommend to create this <strong>lis_result_sourcedid<\/strong>.<\/p>\n<p><strong>Data Model for Resource Link Level Grade Secrets<\/strong><\/p>\n<p>To support this feature, we will add the following data items in the LTI Resource Links.  This value need not be visible to the Instructor and there is little value revealing the value to the Instructor or admin.  <\/p>\n<p><code>imslti.gradesecret=random UUID<\/code><\/p>\n<p>The LTI code generates the secret internally once the instructor or admin has indicated that this <strong>resource_link_id<\/strong> is supposed to  accept grades.<\/p>\n<p><strong>During Launch: Constructing the lis_result_sourcedid<\/strong><\/p>\n<p>The essential data needed in the <strong>lis_result_sourcedid<\/strong> is the <strong>resource_link_id<\/strong> and the userid.  The key is to make sure that the <strong>lis_result_sourcedid<\/strong> cannot be tampered with while the tool in possession of the <strong>lis_result_sourcedid<\/strong>.  The base string will be as follows:<\/p>\n<p><code>\tgradesecret + ':::' + resource_link_id + ':::' + user_id <\/code><\/p>\n<p>A SHA1 signature will be computed from that base string and the <strong>lis_result_sourcedid<\/strong> sent in the launch will be:<\/p>\n<p><code>\tsignature + ':::' + resource_link_id + ':::' + user_id <\/code><\/p>\n<p>All the other information regarding the grade book comes from data stored in the content item associated with the <strong>resource_link_id<\/strong> so there is no need to replicate this information in the <strong>lis_result_sourcedid<\/strong>.  These is little reason to otherwise encrypt the <strong>lis_result_sourcedid<\/strong> as it simply contains information the external tool already knows.<\/p>\n<p>So the only protection needed is to insure the integrity of the <strong>resource_link_id<\/strong>\/<strong>user_id<\/strong> using a simple message signature.  Encrypting the <strong>lis_result_sourcedid<\/strong> further would obfuscate the information for no particular increase in security but it can be done if the TC wants to do so.<\/p>\n<p>The resulting <strong>lis_result_sourcedid<\/strong> will be sent with LTI launches for which the instructor has configured the tool to receive grades.<\/p>\n<p><strong>Use Case Walk Through<\/strong><\/p>\n<p>This section walks through the entire steps of the process in order.<\/p>\n<p>Instructor or admin  places the LTI resource link and configures with the url, secret, and key.<br \/>\nInstructor or admin uses the LTI config UI to indicate that the tool will be sending grades, and  picks the grade book column to store results if necessary.  This causes the <strong>imsti.gradebooksecret<\/strong> property to be set with a random UUID if it is not already set.<\/p>\n<p>Student launches the tool in the consumer  The launch includes the <strong>lis_result_sourcedid<\/strong> which is the <strong>resource_link_id<\/strong> and <strong>user_id<\/strong> and an integrity signature based on gradebooksecret.<\/p>\n<p>The Tool Provider stores the <strong>lis_result_sourcedid<\/strong> for each <strong>user_id<\/strong> in its tables somewhere, remembering the <strong>oauth_consumer_key<\/strong> as well.<\/p>\n<p>Student uses the tool and earns a grade, or perhaps the student uses the tool and the instructor goes into the tool and grades the student work and requests that grades be sent back to the TC.<\/p>\n<p>Either as a side effect of the student completing the work, or the instructor pressing a &#8220;send-grades&#8221; button, the tool provider creates a Outcomes service request message including the <strong>lis_result_sourcedid<\/strong> and sign the overall message it using OAuth using the <strong>oauth_consumer_key<\/strong> which the Tool Consumer used to sign the launch request.  <\/p>\n<p>The overall message signature establishes that the TP indeed sent the message and that the message contents were not modified while in-transit.<\/p>\n<p>The service message is sent to the designated service URL on the tool consumer.<\/p>\n<p><code>(1) The TC parses the lis_result_sourcedid, producing a signature, resource_link_id and user_id.<br \/>\n(2) The TC looks up the content item using the resource_link_id<br \/>\n(3) It then pulls gradesecret from the content item and checks the lis_result_sourcedid signature<br \/>\n(4) It then looks up the oauth_consumer_key and secret from the content item (or from a system wide registry) and checks the OAuth signature of the message.<br \/>\n(5) The TC verifies that the user_id is a member of the context_id that contains the content item (resource_link_id).<\/code><\/p>\n<p>If all of the above tests pass &#8211; we  set the grade.  <\/p>\n<p><strong>Advanced Concepts (Optional)<\/strong><\/p>\n<p>Since these secrets are system generated and not user entered, a TC can come up with a  &#8220;rotation&#8221;policy to change the grade secret periodically for each <strong>resource_link_id<\/strong>.  To do this we add two new data items to each resource link associated with a <strong>resource_link_id<\/strong>:<\/p>\n<p><code>imslti.gradesecretdate=Date The gradesecret was set<br \/>\nimslti.oldgradesecret=The Immediate prior secret<\/code><\/p>\n<p>Based on some time scale chosen by the TC administrator, the TC can go through and &#8220;expire secrets&#8221; that are older than some desired time period.   The regeneration process can copy the current value for gradesecret to oldgradesecret and then generate a new <strong>gradesecret<\/strong> and update the <strong>gradesecretdate<\/strong>.  The verification process above is updated to check both the gradesecret and oldgradesecret and accept either as valid.<\/p>\n<p>The launch process simply uses the latest <strong>gradesecret<\/strong> when it signs the <strong>lis_result_sourcedid<\/strong> during a launch thus extending the expiry date on the <strong>lis_result_sourcedid<\/strong>.<\/p>\n<p>If the TC system automatically regenerates all <strong>gradesecret<\/strong> values after 15 days, it will appear to the TP that signed <strong>lis_result_sourcedid<\/strong> values expire after a minimum of 15 and maximum of 30 days depending on the relative timing of the generation of the gradesecret and the generation of the <strong>lis_result_sourcedid<\/strong>.<\/p>\n<p>A <strong>gradesecret<\/strong> and\/or <strong>oldgradesecret<\/strong> can be manually altered, removed or regenerated at any time to &#8220;invalidate&#8221; all outstanding <strong>lis_result_sourcedid<\/strong> values.<\/p>\n<p><strong>Sample Source Code<\/strong><\/p>\n<p>This is implemented in the Sakai <strong>ServiceServlet<\/strong> here is the code below:<\/p>\n<p><a href=\"https:\/\/source.sakaiproject.org\/svn\/basiclti\/trunk\/basiclti-blis\/src\/java\/org\/sakaiproject\/blti\/ServiceServlet.java\" target=\"_blank\">https:\/\/source.sakaiproject.org\/svn\/basiclti\/trunk\/basiclti-blis\/src\/java\/org\/sakaiproject\/blti\/ServiceServlet.java<\/a><\/p>\n<p>Look for the <strong>doPostXml<\/strong> method and walk through it (patches welcome).  There are libraries of code elsewhere in the source tree &#8211; but this is the starting point for Sakai&#8217;s outcome service code.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>This document introduces the notion of a signed lis_result_sourcedid that allows very fine-grained authorization down to the individual user \/ <strong>resource_link_id<\/strong> if the TC so chooses.  The approach includes provisions for grade secret revocation, and seamless grade secret expiry and rotation.<\/p>\n<p>Comments welcome\u2026<\/p>\n<p>Original document written: Version: 3 &#8211; August 18, 2010<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a design for an approach to securely accept grades from an external tool and put those grades in the grade book. Please review this design for security and feasibility. Overview of the Structure of IMS Outcomes When you look at the IMS Learning Tools Interoperability 1.1 (LTI) Launch, there is a field called [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4069","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/4069","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/comments?post=4069"}],"version-history":[{"count":18,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/4069\/revisions"}],"predecessor-version":[{"id":4087,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/4069\/revisions\/4087"}],"wp:attachment":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/media?parent=4069"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/categories?post=4069"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/tags?post=4069"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}