Add some useful comments describing LTI 1.3 implementation

flag=none

Test Plan:
New comments are clear and correct

Change-Id: Ib568a7767ddaf23552a3bdae09515849dc19a0f9
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/256190
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Evan Battaglia <ebattaglia@instructure.com>
QA-Review: Evan Battaglia <ebattaglia@instructure.com>
Product-Review: Weston Dransfield <wdransfield@instructure.com>
This commit is contained in:
Weston Dransfield 2021-01-06 14:06:48 -07:00
parent 78216630d6
commit 972fb4c954
5 changed files with 154 additions and 0 deletions

View File

@ -19,6 +19,8 @@ module Lti
module Ims
class InvalidLaunch < StandardError; end
# Contains actions to handle the second step of an LTI 1.3
# Launch: The authentication request
class AuthenticationController < ApplicationController
include Lti::RedisMessageClient
@ -41,10 +43,31 @@ module Lti
# Redirect the "authorize" action for the domain specified
# in the lti_message_hint
#
# This means that tools can simply use the canvas.instructure.com
# domain in the authentication requests rather than keeping
# track of institution-specific domain.
def authorize_redirect
redirect_to authorize_redirect_url
end
# Handles the authentication response from an LTI tool. This
# is the second step in an LTI 1.3 launch.
#
# Please refer to the following specification sections:
# - https://www.imsglobal.org/spec/security/v1p0#step-2-authentication-request
# - http://www.imsglobal.org/spec/lti/v1p3/
#
# If the authentication validations described in the specifications
# succeed, this action uses the "lti_message_hint" parameter
# to retrieve a cached ID token (LTI launch) and sends it to the
# tool.
#
# The cached ID Token is generated at the time Canvas makes
# the login request to the tool.
#
# For more details on how the cached ID token is generated,
# please refer to the inline documentation of "app/models/lti/lti_advantage_adapter.rb"
def authorize
validate_oidc_params!
validate_current_user!

View File

@ -20,6 +20,46 @@
require 'lti_advantage'
module Lti
# Responsible for generating parameters for both Login requests
# and Authentication Responses (ID token).
#
# This class serves a similar purpose to LtiOutboundAdapter
# (and exposes the same interface), but is only
# used for LTI 1.3. LtiOutboundAdapter is used only for LTI 1.x.
#
# Please refer to the following IMS specification sections:
# - https://www.imsglobal.org/spec/security/v1p0#step-1-third-party-initiated-login
# - http://www.imsglobal.org/spec/lti/v1p3/#additional-login-parameters
#
# LtiAdvantageAdapter offers various methods that provide
# context-tailored parameters for login requests and authentication
# responses:
# - generate_post_payload_for_assignment
# - generate_post_payload_for_homework_submission
# - generate_post_payload
#
# These are the primary methods used to interface with
# LtiAdvantageAdapter from external classes. A brief
# overview of each can be found in method-specific
# documentation.
#
# In general, the formation of the login request (and later
# authentication response) is handled in the following way:
#
# 1. Generate the complete, signed id_token that will be sent
# in the authentication response from Canvas to the tool.
# 2. Create a random cache key, and store the id_token in
# cache for later retrieval if authentication with the
# the tool succeeds.
# 3. Include the cache key as the "lti_message_hint" parameter
# in the login request. This value is passed back to Canvas
# By the tool in the authentication request (handled by
# app/controllers/lti/ims/authentication_controller.rb#authorize).
#
# For information on how the cached ID token is eventually retrieved
# and sent to a tool, please refer to the inline documentation of
# app/controllers/lti/ims/authentication_controller.rb
class LtiAdvantageAdapter
MESSAGE_HINT_LIFESPAN = 5.minutes
@ -35,14 +75,64 @@ module Lti
@target_link_uri = opts[:launch_url]
end
# Generates a login request pointing to a cached launch (ID token)
# suitable for assignment LTI launches.
#
# This ensures, for example, that Assignment and Grade services
# parameters are included in the cached launch.
#
# See method-level documentation of "generate_post_payload" for
# more details.
#
# For information on how the cached ID token is eventually retrieved
# and sent to a tool, please refer to the inline documentation of
# app/controllers/lti/ims/authentication_controller.rb
def generate_post_payload_for_assignment(*args)
login_request(resource_link_request.generate_post_payload_for_assignment(*args))
end
# Generates a login request pointing to a cached launch (ID token)
# suitable for submission LTI launches.
#
# These launches occur when a student launches a tool with
# the intent of selecting some document or link that will
# be used as their submission for an assignment.
#
# See method-level documentation of "generate_post_payload" for
# more details.
#
# For information on how the cached ID token is eventually retrieved
# and sent to a tool, please refer to the inline documentation of
# app/controllers/lti/ims/authentication_controller.rb
def generate_post_payload_for_homework_submission(*args)
login_request(resource_link_request.generate_post_payload_for_homework_submission(*args))
end
# Generates a login request pointing to a general-use
# cached launch (ID token).
#
# This method, along with all other "generate_post_payload_for_*"
# methods, generates a login request in the following way:
#
# 1. Determine what the message type should be. For now this
# is always either "LtiResourceLinkRequest" or "DeepLinkingRequest".
# Default to "LtiResourceLink" if the requested message type is
# not recognized.
# 2. Invoke the constructor for the "factory" class that builds
# the requested message type. At the time of writting, these
# classes live in "lib/lti/messages".
# 3. Cache the ID token returned from the factory class (this is a
# signed JWT, so always a string)
# 4. Construct the login request parameters with a lti_message_hint
# that points to the cached ID token.
#
# Please refer to the following IMS specification sections:
# - https://www.imsglobal.org/spec/security/v1p0#step-1-third-party-initiated-login
# - http://www.imsglobal.org/spec/lti/v1p3/#additional-login-parameters
#
# For information on how the cached ID token is eventually retrieved
# and sent to a tool, please refer to the inline documentation of
# app/controllers/lti/ims/authentication_controller.rb
def generate_post_payload
login_request(generate_lti_params)
end

View File

@ -18,6 +18,19 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
module Lti::Messages
# A "factory" class that builds an ID Token (JWT) to be used in LTI Advantage
# LTI Deep Linking Requests. These requests indicate to the launched
# tool that Canvas expects it to return data via deep linking.
#
# This class relies on a another class (LtiAdvantage::Messages::DeepLinkingRequest)
# to model the data in the JWT body and produce a signature.
#
# For details on the data included in the ID token please refer
# to http://www.imsglobal.org/spec/lti-dl/v2p0.
#
# For implementation details on LTI Advantage launches in
# Canvas, please see the inline documentation of
# app/models/lti/lti_advantage_adapter.rb.
class DeepLinkingRequest < JwtMessage
ACCEPT_TYPES = {
'migration_selection' => %w(file).freeze,

View File

@ -20,6 +20,22 @@
require 'lti_advantage'
module Lti::Messages
# Base class for all LTI Message "factory" classes.
#
# This class, and it's child classes, are responsible
# for constructing and ID token suitable for LTI 1.3
# authentication responses (LTI launches).
#
# These class have counterparts for simply modeling the
# data at "gems/lti-advantage/lib/lti_advantage/messages".
#
# For details on the data included in the ID token please refer
# to http://www.imsglobal.org/spec/lti/v1p3/.
#
# For implementation details on LTI Advantage launches in
# Canvas, please see the inline documentation of
# app/models/lti/lti_advantage_adapter.rb.
class JwtMessage
EXTENSION_PREFIX = 'https://www.instructure.com/'.freeze

View File

@ -18,6 +18,18 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
module Lti::Messages
# A "factory" class that builds an ID Token (JWT) to be used in LTI Advantage
# LTI Resource Link Requests (a.k.a standard LTI 1.3 tool launches).
#
# This class relies on a another class (LtiAdvantage::Messages::ResourceLinkRequest)
# to model the data in the JWT body and produce a signature.
#
# For details on the data included in the ID token please refer
# to http://www.imsglobal.org/spec/lti/v1p3/.
#
# For implementation details on LTI Advantage launches in
# Canvas, please see the inline documentation of
# app/models/lti/lti_advantage_adapter.rb.
class ResourceLinkRequest < JwtMessage
def initialize(tool:, context:, user:, expander:, return_url:, opts: {})
super