Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-51969

LTI registration: Missing Tool Proxy GUID in 'tc_profile_url'

    XMLWordPrintable

    Details

    • Testing Instructions:
      Hide

      Steps to reproduce

      1. Install Moodle behind nginx with configuration as described here. The problem depends on how the server handles the PATH_INFO environment variable, it might not occur in a different setting.
      2. Go to Site Administration -> Plugins -> Activity Modules -> LTI -> Manage external tool registrations.
      3. Configure a new external tool registration. Set the registration URL to 'http://lti.tools/test/tp.php'. It does not matter what you enter for the other parameters.
      4. Register the tool and inspect the 'tc_profile_url' parameter.

      Expected result

      The 'tc_profile_url' parameter should look something like this:

      tc_profile_url=http://example.com/moodle/mod/lti/services.php/profile/Acb6GQ5BGM5N0VM?lti_version=LTI-2p0
      

      Actual result

      The tool proxy GUID is missing in the 'tc_profile_url' parameter:

      tc_profile_url=http://example.com/moodle/mod/lti/services.php/profile/?lti_version=LTI-2p0
      

       

      Show
      Steps to reproduce Install Moodle behind nginx with configuration as described here . The problem depends on how the server handles the PATH_INFO environment variable, it might not occur in a different setting. Go to Site Administration -> Plugins -> Activity Modules -> LTI -> Manage external tool registrations. Configure a new external tool registration. Set the registration URL to 'http://lti.tools/test/tp.php'. It does not matter what you enter for the other parameters. Register the tool and inspect the 'tc_profile_url' parameter. Expected result The 'tc_profile_url' parameter should look something like this: tc_profile_url=http://example.com/moodle/mod/lti/services.php/profile/Acb6GQ5BGM5N0VM?lti_version=LTI-2p0 Actual result The tool proxy GUID is missing in the 'tc_profile_url' parameter: tc_profile_url=http://example.com/moodle/mod/lti/services.php/profile/?lti_version=LTI-2p0  
    • Affected Branches:
      MOODLE_29_STABLE, MOODLE_31_STABLE, MOODLE_33_STABLE, MOODLE_34_STABLE, MOODLE_35_STABLE
    • Fixed Branches:
      MOODLE_34_STABLE, MOODLE_35_STABLE
    • Pull from Repository:
    • Pull 3.4 Branch:
      MDL-51969-MOODLE_34_STABLE
    • Pull 3.5 Branch:
      MDL-51969-MOODLE_35_STABLE
    • Pull Master Branch:
      MDL-51969-master

      Description

      Explanation

      The 'tc_profile_url' is determined by the get_endpoint() function in mod/lti/classes/local/ltiservice/service_base.php:

          public function get_endpoint() {
       
              $this->parse_template();
              $url = $this->get_service()->get_service_path() . $this->get_template();
              foreach ($this->params as $key => $value) {
                  $url = str_replace('{' . $key . '}', $value, $url);
              }
              $toolproxy = $this->get_service()->get_tool_proxy();
              if (!empty($toolproxy)) {
                  $url = str_replace('{tool_proxy_id}', $toolproxy->guid, $url);
              }
       
              return $url;
       
          }
      

      The function calls parse_template() which determines the '{tool_proxy_id}' parameter from the PATH_INFO environment variable. If not set the '{tool_proxy_id}' parameter is set to the guid of the tool proxy.

      Now look at the parse_template() function:

          protected function parse_template() {
       
              if (empty($this->params)) {
                  $this->params = array();
                  if (isset($_SERVER['PATH_INFO'])) {
                      $path = explode('/', $_SERVER['PATH_INFO']);
                      $parts = explode('/', $this->get_template());
                      for ($i = 0; $i < count($parts); $i++) {
                          if ((substr($parts[$i], 0, 1) == '{') && (substr($parts[$i], -1) == '}')) {
                              $value = '';
                              if ($i < count($path)) {
                                  $value = $path[$i];
                              }
                              $this->params[substr($parts[$i], 1, -1)] = $value;
                          }
                      }
                  }
              }
       
              return $this->params;
       
          }
      

      If the PATH_INFO variable is not set the function returns an empty array. But if the PATH_INFO variable is an empty string the function sets all parameters to an empty string. As a result the '{tool_proxy_id}' parameter is set to an empty string and won't be replaced with the tool proxy guid by get_endpoint() anymore.

      Workaround/ProposedFix

      Check in parse_template() if the PATH_INFO variable is empty:

      $ git diff
      diff --git a/mod/lti/classes/local/ltiservice/resource_base.php b/mod/lti/classes/local/ltiservice/resource_base.php
      index 4d617fe..60c7327 100644
      --- a/mod/lti/classes/local/ltiservice/resource_base.php
      +++ b/mod/lti/classes/local/ltiservice/resource_base.php
      @@ -255,7 +255,7 @@ abstract class resource_base {
       
               if (empty($this->params)) {
                   $this->params = array();
      -            if (isset($_SERVER['PATH_INFO'])) {
      +            if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO'])) {
                       $path = explode('/', $_SERVER['PATH_INFO']);
                       $parts = explode('/', $this->get_template());
                       for ($i = 0; $i < count($parts); $i++) {
      

      Note that according to RFC 3875, section 4.1.5, an empty PATH_INFO variable is perfectly correct:

      PATH_INFO = "" | ( "/" path )

        Attachments

          Activity

            People

            • Votes:
              3 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Fix Release Date:
                12/Nov/18