Skip to content

Deploy: Configuration for LTI 1.3 Deployment

Lance E Sloan (lsloan) edited this page Oct 7, 2020 · 18 revisions

🚧 Under Construction

This document is for a new feature of MyLA, LTI v1.3 support. Your patience while these updates are made is appreciated. Your feedback is welcome.

Configure MyLA

To complete the steps in the next section, MyLA must be configured according to the project's README.md document. It needs to be installed on a server that is accessible by Canvas.

Generating Keys

About Keys

To enable LTI launch requests, MyLA needs a public and private RS256 key pair in PEM format. For some LTI features, the LMS need to use a JWK format of the public key to communicate with MyLA, so that may be needed as well. For the most part, the JWK public key should not be used. It's safer to give a URL to MyLA's /lti/jwks/ service instead, which generates the JWK public key from the PEM public key on demand. It is still generated here mostly for the purposes of troubleshooting the configuration.

πŸ’‘ – When configuring MyLA's LTI support it is important to note that the two formats of public keys are used for different purposes.

  • The public key PEM is used for LTI launch requests.
  • The public key JWK is used by the LMS for secure communication with an already running LTI. That is usually to support LTI Advantage features, which MyLA does not yet support

There are currently two ways to generate those three key files.

Generate Keys with Django Management Tool

MyLA includes a key generation program, createkeys, that is available via the Django management tool, manage.py. While MyLA is running in a Docker container, enter the following command to create key files:

docker exec -it student_dashboard python manage.py createkeys

The program will create the new key files in the same directory that holds the env.json configuration file.

It will create three files with the suffixes _private.pem and _public.pem. By default, the two files will be named with a timestamp of the format YYYYmmddHHMMSS, followed by one of the suffixes. If you want to specify a name for the key files instead of a timestamp, use the --basename option:

docker exec -it student_dashboard python manage.py createkeys --basename example

That will create key files named example_private.pem and example_public.pem.

Get JWK of the Public Key (Optional)

A JWK (JSON Web Key) is a JSON data structure that represents a cryptographic key. In the LTI lifecycle, when the LMS needs to send requests to the tool, it must encrypt them with the tool's public key. In most cases, the LMS may request the public key from the tool using an unencrypted (but still secure) request. The tool will respond to the request by sending its public key encoded as part of a JWK Set (JWKS), which is an array of multiple JWK values.

Because the retrieval of the JWK is handled automatically, it is extremely rare that it would ever need to be saved in a file or manually inserted into an LTI configuration. However, some old LMSs may require it. This section is to support those old LMSs, otherwise it is useful for reference and debugging purposes.

Using MyLA's JWKS Service

The best and recommended way to get MyLA's JWK is to request it from the app's JWKS service. That will be at the URL https://myla-host.example.edu/lti/jwks/.

Using MyLA's Django Management Tool

🚧 This section is for a new feature that has not yet been released.

MyLA includes a key generation program, getjwk, that is available via the Django management tool, manage.py. While MyLA is running in a Docker container, enter the following command to store the JWK in a file:

docker exec -it student_dashboard python manage.py getjwk

The program will create a JWK file in the same directory that holds the env.json configuration file. It will be based on the public key that was available the last time MyLA was started.

It will create a file with the suffix _public-jwk.json. By default, the file will be named with a timestamp of the format YYYYmmddHHMMSS, followed by the suffix. If you want to specify a name for the JWK file instead of a timestamp, use the --basename option:

docker exec -it student_dashboard python manage.py get --basename example

That will create a JWK file named example_public-jwk.json.

Alternatively, if the JWK doesn't need to be saved

Configure Security Settings

  • The CSP block of the settings can be copied and should work "as-is".
  • Change "REPORT_ONLY" to false if there are no console errors in your browser when testing
  • You'll also need "CSRF_COOKIE_SECURE": true when running on HTTPS.

Configure LTI Settings

⚠️ – The hostname myla-host.example.edu appears several times in the following configuration examples. It must be replaced with the hostname of the computer on which MyLA is being tested.

  • There are a number of LTI settings including

    • "STUDENT_DASHBOARD_LTI" : true
      This setting enables LTI support.
  • Create Developer keys (Go to Canvas "Key Settings" page, following these instructions)

Use ONE of the two following sections, "Manual Entry" or "Paste JSON"

Enter Configuration Parameters

Canvas currently offers three methods for entering the parameters for LTI key configuration:

  • Paste JSON – This is the currently recommended method for MyLA
  • Manual Entry – This works, but is not recommended, because it is easy to make mistakes
  • Enter URL – MyLA support for this method is coming soon, but it's not available yet

Paste JSON method

  • Copy the following JSON and paste into the "LTI 1.3 Configuration" field

    • Change the title and description attributes, if desired.

    πŸ’‘ – In the near future, the LTI specification will require JWK to be specified by URL only. To ensure compatibility, do not paste the contents of the JWK into a configuration property. Only use the public_jwk_url property to provide a URL to MyLA's JWK, like https://myla-host.example.edu/lti/jwks/.

    {
        "title": "My Learning Analytics Test",
        "scopes": [
            "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem",
            "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly",
            "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly",
            "https://purl.imsglobal.org/spec/lti-ags/scope/score",
            "https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly",
            "https://canvas.instructure.com/lti/public_jwk/scope/update",
            "https://canvas.instructure.com/lti/account_lookup/scope/show",
            "https://canvas.instructure.com/lti/data_services/scope/create",
            "https://canvas.instructure.com/lti/data_services/scope/show",
            "https://canvas.instructure.com/lti/data_services/scope/update",
            "https://canvas.instructure.com/lti/data_services/scope/list",
            "https://canvas.instructure.com/lti/data_services/scope/destroy",
            "https://canvas.instructure.com/lti/data_services/scope/list_event_types",
            "https://canvas.instructure.com/lti/feature_flags/scope/show"
        ],
        "extensions": [
            {
                "domain": "myla-host.example.edu",
                "platform": "canvas.instructure.com",
                "settings": {
                    "platform": "canvas.instructure.com",
                    "placements": [
                        {
                            "default": "disabled",
                            "placement": "course_navigation",
                            "message_type": "LtiResourceLinkRequest",
                            "target_link_uri": "https://myla-host.example.edu/lti/launch/"
                        }
                    ]
                },
                "privacy_level": "public"
            }
        ],
        "public_jwk": {},
        "description": "This is LTI key for LTI1.3",
        "custom_fields": {
            "user_username": "$User.username",
            "canvas_user_id": "$Canvas.user.id",
            "canvas_course_id": "$Canvas.course.id"
        },
        "public_jwk_url": "https://myla-host.example.edu/lti/jwks/",
        "target_link_uri": "https://myla-host.example.edu/lti/launch/",
        "oidc_initiation_url": "https://myla-host.example.edu/lti/login/"
    }

Manual Entry method

  • Redirect URIs: https://myla-host.example.edu/lti/launch/

  • Target Link URI: https://myla-host.example.edu/lti/launch/

  • OpenID Connect Initiation Url: https://myla-host.example.edu/lti/login/

  • JWK Method: Public JWK URL

    • Public JWK URL: https://myla-host.example.edu/lti/jwks/

      πŸ’‘ – In the near future, the LTI specification will require JWK to be specified by URL only. To ensure compatibility, do not paste the contents of the JWK into a configuration property. Only use the public_jwk_url property to provide a URL to MyLA's JWK, like https://myla-host.example.edu/lti/jwks/.

  • LTI Advantage Services: Enable all toggles

  • Additional Settings

    • Domain: myla-host.example.edu

    • Custom Fields

    user_username=$User.username
    canvas_user_id=$Canvas.user.id
    canvas_course_id=$Canvas.course.id
    • Privacy Level: Public

    • Placements: Choose "Course Navigation" only, remove any others added by default

      • Course Navigation section
        • Target Link URI: https://myla-host.example.edu/lti/launch/
    • Click the "Save" button

    • Find the new key and click the ✎ (pencil) icon to edit it.

    • Select the "Paste JSON" method if it's not selected already

    • In the "LTI 1.3 Configuration" field, find the "placements" array

    • In that array, add the following to the first object:

      "default": "disabled",

      That will prevent the tool from being installed in courses by default.

Finishing Configuration

Whichever method in the section above is used to enter the configuration parameters, the following steps

  • Change "State" from OFF to ON for the newly created key

  • Install the MyLA tool in a course, subaccount, or root account as you prefer. since with the default: disabled option the tool won't enabled in course navigation

  • Create new External App: "Settings -> Apps -> +App"

  • Choose "Configuration Type: by ClientID"

  • Insert "ClientID" from the created Key (value from Details column)

  • Update the settings in the LTI_CONFIG section of env.json on the server hosting MyLA:

    "https://canvas.instructure.com": [
      {
        "/* requests without ID from this platform use this config by default": "*/",
      "default": true,
        
        "/* from Canvas: Developer Keys -> value from Details column": "*/",
        "client_id": "𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏",
        
        "/* static auth_login_url URL from this platform": "*/",
        "auth_login_url": "http://canvas.instructure.com/api/lti/authorize_redirect",
    
        "/* static auth_token_url URL from this platform": "*/",
        "auth_token_url": "http://canvas.instructure.com/login/oauth2/token",
        
        "/* static URL to get public key from this platform": "*/",
        "key_set_url": "http://canvas.instructure.com/api/lti/security/jwks",
        
        "/* this tool's private key ": "*/",
        "private_key_file": "/secrets/example_private.pem",
        
        "/* this tool's public key ": "*/",
        "public_key_file": "/secrets/example_public.pem",
        
        "/* Go to Canvas where this tool installed, click on the setting button (a gear icon, similar to 'βš™οΈ'), click 'Deployment Id', copy it, and paste here": "*/",
        "deployment_ids": [
          "𝒏:𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏𝒏"
        ]
      }
    ]
  • Enable the LTI in the Course navigation, depending on where you have installed the LTI tool (course, root account, or subaccount)

    • Go to the course where MyLA was installed
    • Settings -> Navigation
    • Enable the MyLA tool and save
    • Tool will appear in left navigation

After the configuration changes are complete, MyLA's Docker containers on the server will probably need to be restarted in order for them to take effect.

Testing

After launch the tool from course navigation if the course doesn't exits in MyLA DB it will be created only by instructor and MyLA Django admin's only and UI may display message something like "Course data is not pulled in yet" Make yourself as admin locally by going to django_auth table and change the is_superuser column value to 1. Run the cron the course data will be pulled in and when the LTI launched you should get see courses view page Then if you "Act as a User" in that course in Canvas, click the link in the Navigation you should be able to get right in.

Enabling/Disabling the standard backend

There is a setting ENABLE_BACKEND_LOGIN which is set to False now if LTI or SAML are enabled. If you set this to True the standard internal login/logout will work. This should probably only be enabled for testing.

pylti1.3 module

MyLA uses a third party module that implements LTI 1.3 workflows and validation. See the pylti1.3 GitHub repo for additional documentation.