add canvas_environment to LTI 1.3 login request

why:
* so that LTI 1.3 tools can redirect to different domain or launch url
if desired

closes INTEROP-8009
flag=none

test plan:
* launch the lti 1.3 test tool
* find the /login request or install the LTI debugger Firefox extension
* the login request should contain canvas_environment: prod
* add a new `testcluster.yml` file to the `config` directory
* add `test_cluster_name: 'beta'` to that file
* in a rails console, run ` Setting.set('allow_tc_access_', 'true')
* restart the canvas web container
* relaunch the tool
* the login request should contain canvas_environment: beta

Change-Id: Ic58b6c5ba56a1da7f71bd202afff0c12aed9a70c
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/314295
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Tucker Mcknight <tmcknight@instructure.com>
QA-Review: Tucker Mcknight <tmcknight@instructure.com>
Product-Review: Alexis Nast <alexis.nast@instructure.com>
This commit is contained in:
Xander Moffatt 2023-03-27 13:22:52 -06:00
parent 54e33a7e8e
commit b28b5bf4d4
9 changed files with 116 additions and 4 deletions

View File

@ -182,6 +182,7 @@ module Lti
deployment_id: @tool.deployment_id,
target_link_uri: target_link_uri,
lti_message_hint: message_hint,
canvas_environment: ApplicationController.test_cluster_name || "prod",
canvas_region: @context.shard.database_server.config[:region] || "not_configured"
)
req.lti_storage_target = Lti::PlatformStorage.lti_storage_target if @include_storage_target

View File

@ -268,7 +268,7 @@ h2 .defined-in {
}
table {
border: 1px solid red;
border: 1px solid gray;
border-collapse: collapse;
}

View File

@ -33,6 +33,67 @@ Canvas <a href="http://www.imsglobal.org/spec/security/v1p0/#step-1-third-party-
The request also includes a `login_hint` that is passed in the next step. Last, the request include the `target_link_uri` that has been configured on the Developer key; this is later used by the tool as a recommended final redirect.
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mono">iss</td>
<td>The issuer, as described above.</td>
</tr>
<tr>
<td class="mono">login_hint</td>
<td>Opaque value that must be passed back to Canvas in the next step.</td>
</tr>
<tr>
<td class="mono">target_link_uri</td>
<td>The recommended final redirect for the tool; not required.</td>
</tr>
<tr>
<td class="mono">client_id</td>
<td>The OAuth2 client id, or Developer Key id, for convenience.</td>
</tr>
<tr>
<td class="mono">deployment_id</td>
<td>Unique identifier for the specific deployment of this tool, for convenience.</td>
</tr>
<tr>
<td class="mono">canvas_region</td>
<td>For hosted Canvas, the AWS region (e.g. us-east-1) in which the institution that provided this token resides. For local or open source Canvas, this will have a value of "unknown". This field is safe to ignore. This can be used for tools that are hosted in multiple regions to launch to one url and redirect to the correct region.</td>
</tr>
<tr>
<td class="mono">canvas_environment</td>
<td>For hosted Canvas, the environment (e.g. "production", "beta", or "test") from which the tool is being launched. For local or open source Canvas, this will have a value of "production". This field is safe to ignore. Tools can use this to redirect to beta- or test-specific instances of their tool on launch. This is in place of the LTI 1.1 `environments` tool config option, which is not recognized for 1.3 tools.</td>
</tr>
</tbody>
</table>
<a name="login-redirect"></a>
####Step 1.5: Optional Tool-to-tool Redirect
There are situations where a tool wants to use a region-specific or environment-specific instance of itself to respond to the LTI launch, like keeping traffic within the same region as the instance of Canvas, or using a different domain or even launch URL when launched from beta Canvas vs normal production.
Tools can use the `canvas_region` or `canvas_environment` parameters specified above, or even the Canvas URL from the request's referrer, to decide if they want to redirect.
Example of redirecting to a different domain based on region and environment:
- Login request is made to the tool's OIDC initiation URL, `mytool.net/login`, and contains `canvas_region: us-west-2, canvas_environment: beta`.
- The tool redirects to `beta-pdx.mytool.net/login`, forwarding all of the request parameters.
- The beta-pdx instance of the tool responds by continuing on to Step 2 below.
Example of redirecting to a different launch URL based on environment:
- Login request is made to the tool's OIDC initiation URL, `mytool.net/login`, and contains `canvas_environment: beta, target_link_uri: mytool.net/launch`.
- The tool continues on to Step 2 below, but sends `redirect_uri: mytool.net/beta_launch` instead of using the target_link_uri.
Tools that wish to utilize this redirect need to make sure that all possible initiation URLs, whether the domains or paths vary, are added to the redirect URIs list on their corresponding Developer Key, so that the auth request in Step 2 succeeds.
Tools that utilize different instances for beta and test must also make sure that they are storing the correct corresponding values for Canvas URLS like the OIDC Auth URL, JWKs URL, and the Issuer/`iss`, and that they use the beta or test versions of all of those URLs when the tool is launched from beta or test Canvas.
<a name="step-2"></a>
###Step 2: Authentication Request
To complete authentication, tools are expected to send back an <a href="http://www.imsglobal.org/spec/security/v1p0/#step-2-authentication-request" target="_blank">authentication request</a> to an "OIDC Authorization end-point". This can be a GET or POST, however, this request needs to be a redirect in the users browser and not made server to server as we need to validate the current user's session data. For cloud-hosted Canvas, regardless of the domain used by the client, the endpoint is always:
@ -97,7 +158,8 @@ Tools will need to be aware of some Canvas-specific settings in order to accept
- Beta: `https://canvas.beta.instructure.com/api/lti/security/jwks`
- Test: `https://canvas.test.instructure.com/api/lti/security/jwks`
- **Authorization Redirect URL**: The values and use of this are described in [Step 2](#step-2). Since the URL is static, you will want to configure this in your tool.
- **Authorization Redirect URL**: The values and use of this are described in [Step 2](#step-2). Since the URL is static, you will want to configure this in your tool. Tools that wish to utilize [Step 1.5](#login-redirect) need to include _all_ possible
redirect URLs here.
- **Client ID**: The `client_id` of the Developer Key that's been configured in Canvas. Your tool will need to use this in the authentication response to Canvas ([Step 2](#step-2)) and it is also used during the <a href="" target="_blank">Client Credentials Grant</a> to access <a href="file.oauth.html#accessing-lti-advantage-services" target="_blank">LTI Advantage Services</a>.
@ -555,6 +617,24 @@ object for placement-specific target_link_uri's</p>
</td>
</tr>
<!-- environments -->
<tr class="request-param ">
<td>environments</td>
<td>
<strong style="color: red;">Ignored<strong>
</td>
<td>JSON object</td>
<td class="param-desc">
<p>LTI 1.1 tools <a href="file.tools_xml.html">support enviroment-specific domains and launch urls</a>, used for launching
from beta or test instances of Canvas. This config option is not supported for LTI 1.3. Tools instead should use the
<code>canvas_environment</code> parameter of the OIDC Login request to redirect to environment-specific launch urls or
instances of the tool, as specified in <a href="file.lti_dev_key_config.html#login-redirect">Step 1.5</a> above.
</p>
</td>
</tr>
<!-- public_jwk -->
<tr class="request-param ">

View File

@ -532,6 +532,9 @@ matching, and to only return URLs matching that domain.
External tools can support different LTI environments for different canvas environments.
NOTE: This setting is only supported by LTI 1.1 tools. LTI 1.3 tools should redirect to the
desired domain/launch URL as described in the <a href="file.lti_dev_key_config.html#login-redirect">LTI 1.3 configuration guide</a>.
* __domain__: All url domains in this tool's configuration will be replaced with this domain
* __launch_url__: the blti:launch\_url property that should be used for all canvas test environments.
This property takes precedent over domain changes if both properties are set.
@ -541,8 +544,7 @@ by specifying the environment as part of the property name (ie, test\_launch\_ur
beta\_domain, etc). When used in this manner, specific environment properties take
precedent over the default values.
NOTE: Test environment settings are established during the refresh process when the environments are
<a href="https://community.canvaslms.com/t5/Releases/What-is-the-Canvas-release-schedule-for-beta-production-and-test/ta-p/242411">mirrored from production</a>.
These settings will be applied dynamically during the launch process.
### Test Environment Example

View File

@ -30,6 +30,7 @@ module LtiAdvantage::Messages
OPTIONAL_PARAMETERS = %i[
lti_message_hint
canvas_region
canvas_environment
client_id
lti_storage_target
deployment_id

View File

@ -1124,6 +1124,7 @@ RSpec.describe ApplicationController do
target_link_uri
lti_message_hint
canvas_region
canvas_environment
client_id
deployment_id
lti_storage_target

View File

@ -155,6 +155,7 @@ describe ExternalToolsController do
target_link_uri
lti_message_hint
canvas_region
canvas_environment
client_id
deployment_id
lti_storage_target

View File

@ -111,6 +111,7 @@ describe UsersController do
target_link_uri
lti_message_hint
canvas_region
canvas_environment
client_id
deployment_id
lti_storage_target

View File

@ -134,6 +134,7 @@ describe Lti::LtiAdvantageAdapter do
target_link_uri
lti_message_hint
canvas_region
canvas_environment
client_id
deployment_id
lti_storage_target
@ -187,6 +188,30 @@ describe Lti::LtiAdvantageAdapter do
expect(login_message["canvas_region"]).to eq "not_configured"
end
it 'sets the "canvas_environment" to "prod"' do
expect(login_message["canvas_environment"]).to eq "prod"
end
context "when in beta" do
before do
allow(ApplicationController).to receive(:test_cluster_name).and_return("beta")
end
it 'sets "canvas_enviroment" to "beta"' do
expect(login_message["canvas_environment"]).to eq "beta"
end
end
context "when in test" do
before do
allow(ApplicationController).to receive(:test_cluster_name).and_return("test")
end
it 'sets "canvas_enviroment" to "test"' do
expect(login_message["canvas_environment"]).to eq "test"
end
end
it "accepts a student_id parameter" do
expect(adapter.generate_post_payload(student_id: 123).keys).to include("iss")
end