Fix Failing LTI 1.3 Launch Due to Clickjacking Protection and Incorrect Authentication Response/Launch URL
X-Frame-Options DENY response header prevents LTI 1.3 launch
This commit fixes a bug caused by the X-Frame-Options
response header. The X-Frame-Options
response header indicates to the browser whether a site's content can be loaded within certain tags, including the <iframe> tag. This is a form of clickjacking protection.
In Django, this response header is set by the django.middleware.clickjacking.XFrameOptionsMiddleware
middleware. In the edx-platform, by default, X-Frame-Options
is set to DENY (see the X_FRAME_OPTIONS
Django setting), which means that the response content returned by Django views cannot be loaded within certain tags. However, this behavior can be disabled by decorating views with the django.views.decorators.clickjacking.xframe_options_exempt
view decorator.
This creates a problem for LTI 1.3 launches in the edx-platform. When an LTI component is loaded, the LtiConsumerXBlock
is loaded via the lms.djangoapps.courseware.views.views.render_xblock_view
view. This view is called in an <iframe> tag, but the view is decorated by the xfame_options_exempt
decorator, which disables clickjacking protection and communicates to the browser that the content can be loaded in the <iframe> tag.
Once the third-party login request of the LTI 1.3 launch is completed, the LTI tool directs the browser to make a request to the launch_gate_endpoint
. This endpoint returns a response, which is an auto-submitting form that makes a POST request - the LTI launch request - to the tool. This view has clickjacking enabled, so the browser blocks the requests, which prevents the launch from occurring.
This commit adds the xframe_options_exempt
view decorator to the launch_gate_endpoint view.
Note that LTI 1.1 does not have this bug, because the LTI launch request is handled via the lti_launch_handler
. The XBlock runtime handles requests to the LTI handlers via the openedx.core.djangoapps.xblock.rest_api.views.xblock_handler
view, which is also decorated by the xframe_options_exempt
view decorator.
LTI 1.3 launch URL should be redirect_uri provided by Tool in authentication request
This commit fixes a bug in the way we determine where to send the authentication response - the LTI 1.3 launch message - as part of an LTI 1.3 launch.
According to the 1EdTech Security Framework 1.0, during an LTI 1.3 launch, "the authentication response is sent to the redirect_uri." The redirect_uri
is a query or form parameter provided by the tool when it directs the browser to make a request to the Platform's authentication endpoint. However, we currently send the authentication response to the preregistered launch URL - lti_1p3_launch_url
in the LtiConsumerXBlock
or the LtiConfiguration
model. The difference is subtle, but it is important, because the specification indicates the Platform should respect the redirect_uri
provided by the Tool, assuming it is a valid redirect_uri
.
During the pregistration phase, "the Tool must provide one or multiple redirect URIs that are valid end points where the authorization response can be sent. The number of distinct redirect URIs to be supported by a platform is not specified." Currently, we do not support multiple redirect URIs, so the change is not immediately impactful. However, we should follow the specification and ensure that we return the authentication response to the correct URL.