instructure / ims-lti Goto Github PK
View Code? Open in Web Editor NEWA Ruby library to help implement IMS LTI tool consumers and providers
License: MIT License
A Ruby library to help implement IMS LTI tool consumers and providers
License: MIT License
Starting with Ruby 3.0, rexml
is no longer a default gem, so it should be explicitly listed as a dependency to ensure it's installed. It is required in lib/ims/lti.rb; this may fail with a LoadError
when run on Ruby 3.
This affects multiple branches of this gem, so ideally it should be backported to the 1.2 series as well as master.
First of all, thanks for this gem. So far, I have successfully used this gem to launch a tool from a tool provider and to create user accounts and/or login in users at the same time.
The problem I'm having is that I can't figure out how to manage outcomes, I'd like to be able to make a request for the grades of a specific student, I'm not sure how to go about this.
Any help would be much appreciated.
Are there any examples of how to handle the registration process and how to pass data back to the consumer after launch?
Hi Guys,
I'm developing in a Rails 4.0 / Ruby 2 environment - and encountered s the above issue when using the following 'require' statement in my consumer code (as per your wiki guidance):
require 'ims/lit'
To resolve this issue, I modified the require statement to
require 'ims'
This is just a heads up more than anything... maybe adding a note to the wiki page might be useful. Many thanks for developing this gem, really helped fastrack my LTI implementation knowledge.
Mark
Is there any documentation to use this gem? I have to create an LTI 2 tool but I am unable to find any documentation of how to use this gem? I know of a one example that uses it https://github.com/instructure/lti_tool_provider_example but rather than digging too much into it, I would like to read what functionalities does this gem provide?
I think it would be pretty simple to add:
def admin?
has_role?("urn:lti:instrole:ims/lis/administrator")
end
To detect the admin user. I wouldn't even complain if the roles returned followed a pattern, but that urn is a bit unwieldly!
Again, happy to contribute, I think the params just need to have .encode('UTF-8')
called on them before sending or something. Just direct me to the relevant part of the code.
http://www.imsglobal.org/developers/alliance/LTI/cert/index.php
2.5: Parameters are encoded using UTF-8
Hi I am using this gem for my ruby based application ,
And I want to send the scores back to the LMS , but the problem is in my platform a teacher can grade the assignments now I want to send the scores back to the LMS when the teacher view the application from inside LMS,
say @teacher_loogedin.student_1_grade
is the grade of the student when teacher is logged in his/her account inside LMS using my LTI provider tool , now I want to send back the score to the LMS and LMS should record the score on behalf of the student 1
, can I do this ?
I have written a function to accomplish this but here score is only the parameter , how to use a student specific parameter like student_email
so that the score is reflected for that particular student only.
def submitscore
@tp = IMS::LTI::ToolProvider.new(@@launch_params[:oauth_consumer_key],
Rails.configuration.lti_settings[@@launch_params[:oauth_consumer_key]],
@@launch_params)
# add extension
@tp.extend IMS::LTI::Extensions::OutcomeData::ToolProvider
if [email protected]_service?
@message = "This tool wasn't lunched as an outcome service"
puts "This tool wasn't lunched as an outcome service"
render(:launch_error)
end
res = @tp.post_extended_replace_result!(score: params[:result]) # here I want to pass a parameter of student email such that the corresponding student can be graded
if res.success?
puts "Score Submitted"
else
puts "Error during score submission"
end
redirect_to @@launch_params[:launch_presentation_return_url]
end
my problem is also similar to this but I need to solve this using this gem , please help me
Hi, thanks for the great gem.
We're on our way to upgrading LTI to version 1.3 and would like to use your gem (at least partially). Do you have any documentation regarding versions 2. x.x?
I really appreciate any help you can provide.
Thanks for you help with getting me on the 2.0 version of the gem. My LTI tool provider launches are still failing though on 2.2.1, and this time they don't clear even with a reload of page, so in some ways it's a step back, but I have a feeling something else is going on. I'm creating an authenticator thusly:
authenticator = IMS::LTI::Services::MessageAuthenticator.new(@request.url, @params, secret)
authenticator.valid_signature?
That still returns false.
Here is a dump of the console output for the request, params, and validator that may help, hopefully:
`App 9783 stdout: --- OAUTH Key ====> ocill-lti-key
App 9783 stdout: --- OAUTH Secret ====> REDACTED!
App 9783 stdout: --- REQUEST URL https://lrc-tesuto.lrc.lsa.umich.edu/ocill/launch/create
App 9783 stdout: --- REQUEST PARAMS {"oauth_consumer_key"=>"ocill-lti-key", "oauth_signature_method"=>"HMAC-SHA1", "oauth_timestamp"=>"1510067228", "oauth_nonce"=>"70h3qDQemquvfZeKZ03OIJt5Me06hmoUuA4DEscIgQ", "oauth_version"=>"1.0", "context_id"=>"de25c863939f3cacfc02480738d072d95597842c", "context_label"=>"johnathb Sandbox", "context_title"=>"A Canvas training course for johnathb", "custom_canvas_assignment_points_possible"=>"10", "custom_canvas_assignment_title"=>"OCILL Staging Test", "custom_canvas_enrollment_state"=>"active", "ext_ims_lis_basic_outcome_url"=>"https://umich.instructure.com/api/lti/v1/tools/10530/ext_grade_passback", "ext_lti_assignment_id"=>"f9139721-be1f-473a-91b5-6a08a386074c", "ext_outcome_data_values_accepted"=>"url,text", "ext_outcome_result_total_score_accepted"=>"true", "ext_outcomes_tool_placement_url"=>"https://umich.instructure.com/api/lti/v1/turnitin/outcomes_placement/10530", "ext_roles"=>"urn:lti:instrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Instructor,urn:lti:instrole:ims/lis/Student,urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/User", "launch_presentation_document_target"=>"iframe", "launch_presentation_locale"=>"en", "launch_presentation_return_url"=>"https://umich.instructure.com/courses/56125/external_content/success/external_tool_redirect", "lis_outcome_service_url"=>"https://umich.instructure.com/api/lti/v1/tools/10530/grade_passback", "lti_message_type"=>"basic-lti-launch-request", "lti_version"=>"LTI-1p0", "oauth_callback"=>"about:blank", "resource_link_id"=>"52e0499f9ed929340aec886dd08c7035e45471f5", "resource_link_title"=>"OCILL Staging Test", "roles"=>"Instructor", "tool_consumer_info_product_family_code"=>"canvas", "tool_consumer_info_version"=>"cloud", "tool_consumer_instance_contact_email"=>"[email protected]", "tool_consumer_instance_guid"=>"7db438071375c02373713c12c73869ff2f470b68.umich.instructure.com", "tool_consumer_instance_name"=>"University of Michigan - Ann Arbor", "user_id"=>"1ec00186b63b783a994fd2d5b7648ba6cdfe9807", "oauth_signature"=>"7jq4lBIBYoMzIeShPZbPNJjOrEs=", "controller"=>"launch", "action"=>"create"}
App 9783 stdout: --- AUTHENTICATOR INSPECT ===> #<IMS::LTI::Services::MessageAuthenticator:0x007fd77b5535c0 @launch_url="https://lrc-tesuto.lrc.lsa.umich.edu/ocill/launch/create", @params={"oauth_consumer_key"=>"ocill-lti-key", "oauth_signature_method"=>"HMAC-SHA1", "oauth_timestamp"=>"1510067228", "oauth_nonce"=>"70h3qDQemquvfZeKZ03OIJt5Me06hmoUuA4DEscIgQ", "oauth_version"=>"1.0", "context_id"=>"de25c863939f3cacfc02480738d072d95597842c", "context_label"=>"johnathb Sandbox", "context_title"=>"A Canvas training course for johnathb", "custom_canvas_assignment_points_possible"=>"10", "custom_canvas_assignment_title"=>"OCILL Staging Test", "custom_canvas_enrollment_state"=>"active", "ext_ims_lis_basic_outcome_url"=>"https://umich.instructure.com/api/lti/v1/tools/10530/ext_grade_passback", "ext_lti_assignment_id"=>"f9139721-be1f-473a-91b5-6a08a386074c", "ext_outcome_data_values_accepted"=>"url,text", "ext_outcome_result_total_score_accepted"=>"true", "ext_outcomes_tool_placement_url"=>"https://umich.instructure.com/api/lti/v1/turnitin/outcomes_placement/10530", "ext_roles"=>"urn:lti:instrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Instructor,urn:lti:instrole:ims/lis/Student,urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/User", "launch_presentation_document_target"=>"iframe", "launch_presentation_locale"=>"en", "launch_presentation_return_url"=>"https://umich.instructure.com/courses/56125/external_content/success/external_tool_redirect", "lis_outcome_service_url"=>"https://umich.instructure.com/api/lti/v1/tools/10530/grade_passback", "lti_message_type"=>"basic-lti-launch-request", "lti_version"=>"LTI-1p0", "oauth_callback"=>"about:blank", "resource_link_id"=>"52e0499f9ed929340aec886dd08c7035e45471f5", "resource_link_title"=>"OCILL Staging Test", "roles"=>"Instructor", "tool_consumer_info_product_family_code"=>"canvas", "tool_consumer_info_version"=>"cloud", "tool_consumer_instance_contact_email"=>"[email protected]", "tool_consumer_instance_guid"=>"7db438071375c02373713c12c73869ff2f470b68.umich.instructure.com", "tool_consumer_instance_name"=>"University of Michigan - Ann Arbor", "user_id"=>"1ec00186b63b783a994fd2d5b7648ba6cdfe9807", "oauth_signature"=>"7jq4lBIBYoMzIeShPZbPNJjOrEs=", "controller"=>"launch", "action"=>"create"}, @options={:consumer_key=>"ocill-lti-key", :signature_method=>"HMAC-SHA1", :timestamp=>"1510067228", :nonce=>"70h3qDQemquvfZeKZ03OIJt5Me06hmoUuA4DEscIgQ", :version=>"1.0", :callback=>"about:blank"}, @parsed_params={:context_id=>"de25c863939f3cacfc02480738d072d95597842c", :context_label=>"johnathb Sandbox", :context_title=>"A Canvas training course for johnathb", :custom_canvas_assignment_points_possible=>"10", :custom_canvas_assignment_title=>"OCILL Staging Test", :custom_canvas_enrollment_state=>"active", :ext_ims_lis_basic_outcome_url=>"https://umich.instructure.com/api/lti/v1/tools/10530/ext_grade_passback", :ext_lti_assignment_id=>"f9139721-be1f-473a-91b5-6a08a386074c", :ext_outcome_data_values_accepted=>"url,text", :ext_outcome_result_total_score_accepted=>"true", :ext_outcomes_tool_placement_url=>"https://umich.instructure.com/api/lti/v1/turnitin/outcomes_placement/10530", :ext_roles=>"urn:lti:instrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Instructor,urn:lti:instrole:ims/lis/Student,urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/User", :launch_presentation_document_target=>"iframe", :launch_presentation_locale=>"en", :launch_presentation_return_url=>"https://umich.instructure.com/courses/56125/external_content/success/external_tool_redirect", :lis_outcome_service_url=>"https://umich.instructure.com/api/lti/v1/tools/10530/grade_passback", :lti_message_type=>"basic-lti-launch-request", :lti_version=>"LTI-1p0", :resource_link_id=>"52e0499f9ed929340aec886dd08c7035e45471f5", :resource_link_title=>"OCILL Staging Test", :roles=>"Instructor", :tool_consumer_info_product_family_code=>"canvas", :tool_consumer_info_version=>"cloud", :tool_consumer_instance_contact_email=>"[email protected]", :tool_consumer_instance_guid=>"7db438071375c02373713c12c73869ff2f470b68.umich.instructure.com", :tool_consumer_instance_name=>"University of Michigan - Ann Arbor", :user_id=>"1ec00186b63b783a994fd2d5b7648ba6cdfe9807", :controller=>"launch", :action=>"create"}, @consumer_key="ocill-lti-key", @Signature="7jq4lBIBYoMzIeShPZbPNJjOrEs=", @secret="REDACTED!", @message=#<IMS::LTI::Models::Messages::BasicLTILaunchRequest:0x007fd7836bb6d0 @custom_params={"custom_canvas_assignment_points_possible"=>"10", "custom_canvas_assignment_title"=>"OCILL Staging Test", "custom_canvas_enrollment_state"=>"active"}, @ext_params={"ext_ims_lis_basic_outcome_url"=>"https://umich.instructure.com/api/lti/v1/tools/10530/ext_grade_passback", "ext_lti_assignment_id"=>"f9139721-be1f-473a-91b5-6a08a386074c", "ext_outcome_data_values_accepted"=>"url,text", "ext_outcome_result_total_score_accepted"=>"true", "ext_outcomes_tool_placement_url"=>"https://umich.instructure.com/api/lti/v1/turnitin/outcomes_placement/10530", "ext_roles"=>"urn:lti:instrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Instructor,urn:lti:instrole:ims/lis/Student,urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/User"}, @unknown_params={"controller"=>"launch", "action"=>"create"}, @oauth_consumer_key="ocill-lti-key", @oauth_signature_method="HMAC-SHA1", @oauth_timestamp="1510067228", @oauth_nonce="70h3qDQemquvfZeKZ03OIJt5Me06hmoUuA4DEscIgQ", @oauth_version="1.0", @context_id="de25c863939f3cacfc02480738d072d95597842c", @context_label="johnathb Sandbox", @context_title="A Canvas training course for johnathb", @launch_presentation_document_target="iframe", @launch_presentation_locale="en", @launch_presentation_return_url="https://umich.instructure.com/courses/56125/external_content/success/external_tool_redirect", @lis_outcome_service_url="https://umich.instructure.com/api/lti/v1/tools/10530/grade_passback", @lti_message_type="basic-lti-launch-request", @lti_version="LTI-1p0", @oauth_callback="about:blank", @resource_link_id="52e0499f9ed929340aec886dd08c7035e45471f5", @resource_link_title="OCILL Staging Test", @roles="Instructor", @tool_consumer_info_product_family_code="canvas", @tool_consumer_info_version="cloud", @tool_consumer_instance_contact_email="[email protected]", @tool_consumer_instance_guid="7db438071375c02373713c12c73869ff2f470b68.umich.instructure.com", @tool_consumer_instance_name="University of Michigan - Ann Arbor", @user_id="1ec00186b63b783a994fd2d5b7648ba6cdfe9807", @oauth_signature="7jq4lBIBYoMzIeShPZbPNJjOrEs=", @launch_url="https://lrc-tesuto.lrc.lsa.umich.edu/ocill/launch/create">, @simple_oauth_header=#<SimpleOAuth::Header:0x007fd7836bb108 @method="POST", @uri=#<URI::HTTPS https://lrc-tesuto.lrc.lsa.umich.edu/ocill/launch/create>, @params={:context_id=>"de25c863939f3cacfc02480738d072d95597842c", :context_label=>"johnathb Sandbox", :context_title=>"A Canvas training course for johnathb", :custom_canvas_assignment_points_possible=>"10", :custom_canvas_assignment_title=>"OCILL Staging Test", :custom_canvas_enrollment_state=>"active", :ext_ims_lis_basic_outcome_url=>"https://umich.instructure.com/api/lti/v1/tools/10530/ext_grade_passback", :ext_lti_assignment_id=>"f9139721-be1f-473a-91b5-6a08a386074c", :ext_outcome_data_values_accepted=>"url,text", :ext_outcome_result_total_score_accepted=>"true", :ext_outcomes_tool_placement_url=>"https://umich.instructure.com/api/lti/v1/turnitin/outcomes_placement/10530", :ext_roles=>"urn:lti:instrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Instructor,urn:lti:instrole:ims/lis/Student,urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/User", :launch_presentation_document_target=>"iframe", :launch_presentation_locale=>"en", :launch_presentation_return_url=>"https://umich.instructure.com/courses/56125/external_content/success/external_tool_redirect", :lis_outcome_service_url=>"https://umich.instructure.com/api/lti/v1/tools/10530/grade_passback", :lti_message_type=>"basic-lti-launch-request", :lti_version=>"LTI-1p0", :resource_link_id=>"52e0499f9ed929340aec886dd08c7035e45471f5", :resource_link_title=>"OCILL Staging Test", :roles=>"Instructor", :tool_consumer_info_product_family_code=>"canvas", :tool_consumer_info_version=>"cloud", :tool_consumer_instance_contact_email=>"[email protected]", :tool_consumer_instance_guid=>"7db438071375c02373713c12c73869ff2f470b68.umich.instructure.com", :tool_consumer_instance_name=>"University of Michigan - Ann Arbor", :user_id=>"1ec00186b63b783a994fd2d5b7648ba6cdfe9807", :controller=>"launch", :action=>"create"}, @options={:nonce=>"70h3qDQemquvfZeKZ03OIJt5Me06hmoUuA4DEscIgQ", :signature_method=>"HMAC-SHA1", :timestamp=>"1510067228", :version=>"1.0", :consumer_key=>"ocill-lti-key", :callback=>"about:blank", :consumer_secret=>"REDACTED!"}>>
`
IMS has recently announced that it's abandoning LTI 2.0 in favor of a new concept called LTI Advantage, which seems to be including LTI 1.1 + several extensions. So then I'm wondering what version of this gem is compatible with that. Should we still be using version 2 or should we go back to version 1? How is it going to evolve from here? Thanks.
IMS::LTI::ToolProvider.new("consumer_key", "secrete", {:timezone => Time.now.zone}})
Trying to use ToolProvider and ToolConsumer methods but getting error. Can you please tell me what am I doing wrong
Hello all. We are working on an LTI Integration with canvas in our rails 3 app. However, we are receiving the error
undefined method code' for nil:NilClass
when calling
if provider.valid_request?(request, false)
We have traced this error to the oauth gem, however can not determine why the request is being passed as nil. It is populating when we debug it through logger or a raise and we can not tell if it is getting lost in our handoff to the lti gem or the gem's hand off to oauth.
Does anyone know anything about this?
I forgot to save the lis_outcome_service_url, and when I tried to update in console, I get:
>> @tp.post_replace_result!(0.5)
IMS::LTI::InvalidLTIConfigError:
Which has no message. In my regular code I was trying:
rescue Exception => e
Rails.logger.debug "**********EXCEPTION**********"
Rails.logger.debug $!
Rails.logger.debug e
but all I got was "*_EXCEPTION_" which made it hard to figure out *why it was wrong. :D
I think my issue is probably related to #12 but I'm not sure how to debug things.
When I post scores to canvas, sometimes I get the REXML exception, which does appear to be in the result page that's returned. The problem is I'm not sure if there's a way that I can test where things are going wrong? I've been using the "Test Student" account for my course, and that seems to work fine, but when others post grades there are issues.
Hi,
I am new Canvas and LTI.
I just started working on an LTI 2.0 app.
I am able to launch the app but the problem is that it is enabled for all courses.
By default, course navigation should be disabled and the teacher should explicitly enable it.
course_navigation[default] to disabled
while launching.external_tools
API to update itapi/v1/accounts/{id}/external_tools/{id}
Now if i just want to update the app after launch then the issue is that I don't see the app in the external_tools
list API which I launched using LTI-2 however, I am getting those apps which i am launching using this API
curl -X POST '{host}/api/v1/accounts/1/external_tools' \
-H "Authorization: Bearer {Tocken]" \
-F 'name=LTI Example' \
-F 'consumer_key=asdfg' \
-F 'shared_secret=lkjh' \
-F 'url=https://example.com/ims/lti' \
-F 'privacy_level=name_only' \
-F 'course_navigation[default]=disabled' \
-F 'course_navigation[text]=LTI Test' \
-F 'course_navigation[enabled]=true' \
-F 'user_navigation[visibility]=public'
So
Is there a method or parameter that I can use to disable the course navigation by default while launching the app?
Why external_tools
list API is not returning apps which are launched using ims-lti
gem?
The behavior is reproducible using this https://github.com/instructure/lti_tool_provider_example app
Thank you.
Method IMS::LTI::generate_identifier tries to generate a unique identifier by calling UUID.new. When that's inserted in a message this it to_s on the UUID object, which generates an internal representation, not the identifier string. The code needs to call UUID.new.generate to get the actual string.
I see this has been changed in version 1.1.8 to use SecureRandom.uuid instead, which I think is a good move, but that is only available in ruby 1.9. So maybe it's worth fixing version 1.1.7 for people still using ruby 1.8.
Thanks,
Octav
The GET
request issued to fetch the tool consumer profile does not set the correct Accept header of application/vnd.ims.lti.v2.toolconsumerprofile+json
, and does not add the lti_version
parameter to the request.
Both of these requirements are specified here
https://www.imsglobal.org/lti/model/uml/purl.imsglobal.org/vocab/lti/v2/lti/ToolConsumerProfile/service.html
in section 3.1. Attempting the request without either results in a 400 error when running the IMS LTI certification test suite.
Hi,
This is a very helpful gem, it saved me a lot of work. One issue I found, according to IMS documentation (LTI version 1.1) the xmlns string in outcome requests and responses needs to be "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0". I'm getting an error from the LTI consumer because of that. Could you replace it please? Thanks.
If not, do you know of another Ruby gem that supports LTI 1.1 ?
thanks in advance,this looks like a great project
I need to upgrade an app from v1.2.4 to v2.2.3 (as we are bumping Ruby from v2.7.2 to v3.1.2)
We have simple code which uses IMS::LTI::ToolConsumer.new
, IMS::LTI::ToolConsumer.launch_url
, and IMS::LTI::ToolConsumer.generate_launch_data
. I cannot find and hents on how to change this code to use the new available classes (since IMS::LTI::ToolConsumer
has now been deleted).
When I try to POST a grade from an LTI provider similarly to the Sinatra example app like this:
res = @tp.post_replace_result!(params['score'])
I'm getting a #<REXML::ParseException: Missing end tag for 'link' (got "head")
exception. Full stack trace below.
Any suggestions on how to track this one down? Is this in this Gem or something on my end? I've gotten this to work before, but I'm a little lost with this one.
Thanks!
Line: 236
Position: 18074
Last 80 unconsumed characters:
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/rexml/parsers/baseparser.rb:338:in
pull_event' /home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/rexml/parsers/baseparser.rb:183:in
pull'
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/rexml/parsers/treeparser.rb:22:inparse' /home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/rexml/document.rb:281:in
build'
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/rexml/document.rb:43:ininitialize' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/outcome_response.rb:108:in
new'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/outcome_response.rb:108:inprocess_xml' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/outcome_response.rb:78:in
process_post_response'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/outcome_request.rb:134:inpost_outcome_request' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/outcome_request.rb:81:in
post_replace_result!'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/bundler/gems/ims-lti-544874ea0690/lib/ims/lti/tool_provider.rb:130:inpost_replace_result!' /vagrant/projects/apprennet-com/app/models/lti_session.rb:65:in
send_grade_postback'
/vagrant/projects/apprennet-com/app/controllers/lti_launcher_controller.rb:35:intest_grade_postback' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/implicit_render.rb:4:in
send_action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/abstract_controller/base.rb:167:inprocess_action' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/rendering.rb:10:in
process_action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/abstract_controller/callbacks.rb:18:inblock in process_action' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:414:in
_run__677254598__process_action__38662926__callbacks'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:405:in__run_callback' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:385:in
_run_process_action_callbacks'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:81:inrun_callbacks' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/abstract_controller/callbacks.rb:17:in
process_action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/rescue.rb:29:inprocess_action' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/instrumentation.rb:30:in
block in process_action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/notifications.rb:123:inblock in instrument' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/notifications/instrumenter.rb:20:in
instrument'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/notifications.rb:123:ininstrument' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/instrumentation.rb:29:in
process_action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/params_wrapper.rb:207:inprocess_action' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/abstract_controller/base.rb:121:in
process'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/abstract_controller/rendering.rb:45:inprocess' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal.rb:203:in
dispatch'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal/rack_delegation.rb:14:indispatch' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_controller/metal.rb:246:in
block in action'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:73:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:73:in
dispatch'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:36:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/journey-1.0.4/lib/journey/router.rb:68:in
block in call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/journey-1.0.4/lib/journey/router.rb:56:ineach' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/journey-1.0.4/lib/journey/router.rb:56:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:612:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/mongoid-2.7.1/lib/rack/mongoid/middleware/identity_map.rb:33:in
block in call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/mongoid-2.7.1/lib/mongoid.rb:133:inunit_of_work' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/mongoid-2.7.1/lib/rack/mongoid/middleware/identity_map.rb:33:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/warden-1.2.3/lib/warden/manager.rb:35:inblock in call' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/warden-1.2.3/lib/warden/manager.rb:34:in
catch'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/warden-1.2.3/lib/warden/manager.rb:34:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/best_standards_support.rb:17:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/etag.rb:23:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/conditionalget.rb:25:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/head.rb:14:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/params_parser.rb:21:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/flash.rb:242:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:210:in
context'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:205:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/cookies.rb:341:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/dragonfly-0.9.15/lib/dragonfly/cookie_monster.rb:9:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/callbacks.rb:28:in
block in call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:405:in_run__366245983__call__1040513793__callbacks' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:405:in
__run_callback'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:385:in_run_call_callbacks' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:81:in
run_callbacks'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/callbacks.rb:27:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/reloader.rb:65:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/remote_ip.rb:31:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/debug_exceptions.rb:16:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/show_exceptions.rb:56:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/rack/logger.rb:32:in
call_app'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/rack/logger.rb:16:inblock in call' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.13/lib/active_support/tagged_logging.rb:22:in
tagged'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/rack/logger.rb:16:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/request_id.rb:22:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/methodoverride.rb:21:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/runtime.rb:17:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/lock.rb:15:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/static.rb:63:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/dragonfly-0.9.15/lib/dragonfly/middleware.rb:13:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in
forward'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-cache-1.2/lib/rack/cache/context.rb:245:infetch' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-cache-1.2/lib/rack/cache/context.rb:185:in
lookup'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-cache-1.2/lib/rack/cache/context.rb:66:incall!' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/engine.rb:479:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/application.rb:223:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/content_length.rb:14:incall' /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/railties-3.2.13/lib/rails/rack/log_tailer.rb:17:in
call'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rack-1.4.5/lib/rack/handler/webrick.rb:59:inservice' /home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:138:in
service'
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:94:inrun' /home/vagrant/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/server.rb:295:in
block in start_thread'
...
Missing end tag for 'link' (got "head")
Line: 236
Position: 18074
Last 80 unconsumed characters:
Line: 236
Position: 18074
Last 80 unconsumed characters:
We're attempting to build a product for the various LMS services and hoping to us Content-Item Message –– at the moment I have a launch to a Rails application working, and am trying to find information on how to successfully POST back to the LMS either server-side or via javascript-triggered form submission –– have ben unable to find documentation that has enabled me to get this working. From some issues I've seen posted here, it looks like this library could potentially handle this, but not sure yet.
I'm trying to connect desire2learn to our tool provider.
This is logged at the line:
if provider.valid_request?(request)
I copied this line from the example in the documentation. shouldn't it just return false if the request is malformed or otherwise messed up?
Here's the request parameters from our desire2learn test portal:
Parameters: {
"launch_presentation_locale"=>"EN-US__",
"tool_consumer_info_version"=>"10.1.0 SP5",
"tool_consumer_info_product_family_code"=>"desire2learn",
"tool_consumer_instance_guid"=>"",
"tool_consumer_instance_name"=>"",
"tool_consumer_instance_description"=>"",
"tool_consumer_instance_contact_email"=>"",
"context_id"=>"6670",
"context_title"=>"Sandbox Course 1",
"context_label"=>"Sandbox _101",
"context_type"=>"CourseOffering",
"ext_tc_profile_url"=>"https://notreal.desire2learndemo.com/d2l/api/ext/1.0/lti/tcservices",
"ext_d2l_token_id"=>"2602",
"ext_d2l_link_id"=>"8",
"ext_d2l_token_digest"=>"3n+aoHDWP3bh9Vq2lbB+ERC07vw=",
"resource_link_id"=>"74891df6-8638-1e24-994b-6b57ce61886d_439707169",
"resource_link_title"=>"TestProvider",
"resource_link_description"=>"TestProvider",
"lis_result_sourcedid"=>"755de886-03ca-4e78-988a-629a9ae70382",
"lis_outcome_service_url"=>"https://notreal.desire2learndemo.com/d2l/le/lti/Outcome",
"lti_version"=>"LTI-1p0",
"lti_message_type"=>"basic-lti-launch-request",
"oauth_version"=>"1.0",
"oauth_nonce"=>"141431938",
"oauth_timestamp"=>"1371067056",
"oauth_signature_method"=>"HMAC-SHA1",
"oauth_consumer_key"=>"TEST",
"oauth_callback"=>"about:blank",
"oauth_signature"=>"3PytuKS5veuuydipM2MWj2lis+M=",
"basiclti_submit"=>"Launch Endpoint with BasicLTI Data",
"id"=>"1"}
The IMS::LTI::Services::MessageAuthenticator initialization parses the params object into options and parsed_params.
The course level navigation results in an @options that looks like this:
{:consumer_key=>"lti-example-dev", :signature_method=>"HMAC-SHA1", :timestamp=>"1498094063", :nonce=>"sTtZphI5tfJarJfZQksP1Bdm6nILujuMntjpVk10bc", :version=>"1.0", :callback=>"about:blank"}
The content item selection results in an @options that looks like this:
{:consumer_key=>"lti-example-dev", :signature_method=>"HMAC-SHA1", :timestamp=>"1498094088", :nonce=>"TTNKN94qqjX8vmehAIlsod7GhXLkQpRqy52FxYamG4", :version=>"1.0"}
The primary difference is that the content item selection does not have a callback.
In message_authenticator.rb there's this bit of code that generates the simple_oauth_header. By default it always adds in a callback even if the request doesn't include that value. If I remove the callback then the signature succeeds. Is there a reason to always have a default callback value?
def simple_oauth_header @simple_oauth_header ||= begin @simple_oauth_header = SimpleOAuth::Header.new( :post, launch_url, @parsed_params, @options.merge( { consumer_key: consumer_key, consumer_secret: @secret, callback: 'about:blank' } ) ) @simple_oauth_header end end
I also discussed this issue in the Canvas community. For reference, here's a link:
https://community.canvaslms.com/message/72970-lti-launch-fails-for-content-item-selection-with-latest-ims-lti-gem
The OutcomeRequest#generate_request_xml method is very useful as a communication debugging tool, it would be great if it were made public, so I don't have to edit the source when I need it. The similar OutcomeResponse#generate_response_xml is already public.
And both of them should accept options, so I can pass an indent to the builder. So something like this:
def generate_request_xml options = {}
builder = Builder::XmlMarkup.new(options)
Thanks,
Octav
I did update for rails app form 4 to 5 recently.
Then IMS::LTI::ToolProvider is not working properly.
Here is the code:
private_key = res[:body]["private_key"]
provider = IMS::LTI::ToolProvider.new(public_key, private_key, params.to_unsafe_h)
unless provider.valid_request?(request)
if provider.context_student? || provider.institution_student?
return render :participant_wait_for_activity
else
return render :invalid_key
end
end
I got an error when provider.valid_request?(request)
is excuted.
Here is the error:
OAuth::RequestProxy::UnknownRequestType (ActionDispatch::Request):
The warn
on line 124 of /models/messages/message.rb means that any time you create a message with standard LTI parameters (user_id, lis_person_contact_email_primary) it will flood your logs with warnings because they are not in the whitelist. Can we either add all the standard LTI parameters into the whitelist or just remove the warn
line?
Ideally there would be an option like "error_on_unknown_paramter" which would make it so it would throw an error in an known paramter, otherwise it just continues.
Hi,
I appear to have an issue whereby the request object passed to the "valid_request?" check is failing for the first attempt due to params on the end of the url? If I reload, the request params are reset and the check passes. This thread seems to indicate this is a known issue:
What is the best way around this? Thanks.
Hello,
I am echoing issue #158 which is 4 years old. I was wondering if this lib still does not support LTI 1.3?
I have been reading the code in lib/ims/lti/services/message_authenticator.rb
and found functions for JWT support. So I thought maybe it has been implemented since?
Thank you.
Now required for v1.1.1 certification. Happy to contribute a patch if someone can direct me to the relevant part of the code.
http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html
http://www.imsglobal.org/developers/alliance/LTI/cert/index.php (see 4.10)
I know it supports 1.1 and 1.2, but is 1.3 supported?
Hi,
I would like the instructor to be able to grade the work done by students on my app, before sending the grade back to the LMS.
I thought to store the intructor lti params as a session object and create a new provider object (IMS::LTI::ToolProvider.new) when they go to grade the student's work (and create one for each students' assignment grade, just before creating it, modify the sourcedid and out service url). However, this large amount of data cannot be stored in the session (cookie overflow) and from what I have read online, it would be a bad practice to modify the session to handle the size of params.
I also thought I could modify the provider object of the instructor like so:
provider.lis_result_sourcedid = "sourcedid of a particular student" provider.lis_outcome_service_url = "outcome url of a particular student"
But it looks like this is not possible either. What do you suggest is the best way to solve this problem? Thank you very much.
I spent days debugging an issue where I was using both a ToolProvider and ToolConsumer in an integration test. I was running a local Rails server on the default port (3000) and it turned out that validation would always fail when the port number was included in the launch_url which I used to build the ToolConsumer's request.
Here's a simplified version of my code:
tool_consumer = IMS::LTI::ToolConsumer.new(
"testkey",
"deep dark secret",
{ "resource_link_id" => 1234, "launch_url" => "http://localhost:3000/auth" }
)
post "http://localhost:3000/auth", tool_consumer.generate_launch_data
And in the auth controller:
tool_provider = IMS::LTI::ToolProvider.new("testkey", "deep dark secret", params)
tool_provider.valid_request!(request)
This would always throw an OAuth::Unauthorized
exception. If I took out the port in the launch_url it authenticated just fine.
According to this part of the OAuth spec (http://oauth.net/core/1.0/#sig_url), the port and query string should always be removed from the launch url. I believe this is why the validation fails - the RequestValidator module calls OAuth::Signature.build()
and verify()
directly, and that module appears to be following the spec by dropping the port from the request digest. It looks like generate_launch_data
is already dropping the query string, and drops the port if it's the default one. What it should be doing is dropping the port in all cases.
What's the next step? Assuming you guys agree this is a bug, I can provide a pull request that fixes it as well as some tests to verify correctness.
hurry up and bera hsdovugrbnfseig wnfodcx
RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.
via e.g.
spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']
Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.
There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.
I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!
Appendix:
If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies
p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.
In version 1.1.13, the oauth
dependency was relaxed to > 0.4.5, < 0.6
. However, in commit 6a91689, @rivernate overwrote that change and restored a hard dependency on exactly oauth 0.4.5, and that regression was released in ims-lti 1.2.
If not, is there any plans of releasing a v1.2 update?
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.