IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Perry Way -
Number of replies: 6

Hello everyone,

We have a strange situation here we've been attempting to solve over the course of years. We have two LTI providers, Testout and Cengage. They work in respect as it allows communication to the provider but when the provider returns back grades it does not work.

It's taken years but we have finally worked our way to the top of the Cengage technology staff. I myself am a developer and have built Moodle plugins. I understand this technology first hand, so it was a pleasure to finally work with them over the course of the last week to resolve our issues.

We we both determined is that IIS does not operate with the prescribed Moodle LTI implementations. The paths that both of these vendors use when doing the round trip communications back to us (reporting the grades) wind up getting mangled by IIS or by Moodle. Technically IIS doesn't mangle anything but as soon as it's touched by Moodle a "slash arguments" formed URI becomes mangled.

The result is a cryptic message reporting "No handler found for /".  The Moodle service then spits out the following JSON if you attempt to use your browser to hit this path you can view the 400 data returned: https://<site domain>/mod/lti/services.php/file=/8612/lineitems&type_id=2709

{
    "status": 400,
    "reason": "No handler found for / text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 ",
    "request": {
        "method": "GET",
        "url": "/mod/lti/services.php/?file=/file=/8612/lineitems&type_id=2709",
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "contentType": ""
    }
}

It appears that the problem is highly exacerbated by PHP on IIS. If you notice the original path of :

/mod/lti/services.php/file=/8612/lineitems&type_id=2709

becomes

/mod/lti/services.php/?file=/file=/8612/lineitems&type_id=2709

Interestingly this behavior does not happen on IIS for other technologies. Only Moodle is affected and my assumption is that this has to do with how PHP or Moodle interprets "slash arguments". IIS actually seems to work for other technologies without mangling the URI path. 

The debugging that I have managed to do on a test site indicates that due to the mangling of the URI path there is nothing that can be parsed from it so eventually gets interpreted as a path of nothing, or "/" because it cannot find the handler for it because the URI path is mangled.

Other posts I have found related to this problem in the past have gone unanswered. I know IIS is not a widely used web server in the Moodle community. I understand that. My belief is that the only reason why IIS is even an issue is because other technologies haven't fully supported IIS. Unfortunately at this moment I am unable to ascertain if the problem lies with PHP or with Moodle's use of PHP on IIS. 

If anyone has any information on how to solve this issue, I would love to hear it.  Our instructors are tired of reporting grades manually. They would like to make use of the full features of our providers which means reporting back the grades received on tests and whatnot.

Average of ratings: -
In reply to Perry Way

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Jake Dallimore -
Picture of Core developers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers Picture of Testers
Hi Perry,

Great post. You're 100% right that we need the slashargs to be present in exactly the format that we advertise, to the tool, during the launch. There have been many, many posts about this over the years but I can't say how many were using IIS.

I haven't used IIS with Moodle, so can't speak to a solution, but I will note we have specific docs on this subject here: https://docs.moodle.org/404/en/Internet_Information_Services#IIS_configuration_steps. I'm not sure how up-to-date these are though.

One thing that does seem odd with your example above is the presence of the '/file' part in the URL. That's not something we're expecting. Even if slashargs was working properly, that wouldn't match a service handler. Not sure if that was just part of the example though, or was a real URL.

Hopefully others can clarify the setup needed for IIS.

Cheers,
Jake
In reply to Jake Dallimore

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Perry Way -
Hi Jake, Thanks for taking the time to look this over. I waited to respond because I'm so puzzled how to move this forward.

That link you provided is one I've seen quite some time ago, perhaps 2 or 3 years ago? We have followed every rule and suggestion on the Moodle site.

I'm struggling with not having the exact URIs and/or request form data or request query data to be able to go any further in my testing. If I had the URIs I could maybe fix whatever is wrong. Cengage can't provide the URI's for me since that happens inside their API code on their machines.

Is there a way to have someone in the Moodle community test the REGEX value that is suggested to use on IIS to transform slash dot arguments and make Moodle work correctly?

The value is ^([^\?]+?\.php)(\/.+)$
 
Also, the Rewrite URL has the value of {R:1}\?file={R:2}
 
When I test this on IIS in the server manager, the URI of: /mod/lti/services.php/file=/8612/lineitems&type_id=2709
 
Becomes:
 
IIS screen shot example
 
The above leads me to believe IIS is behaving correctly. And it is PHP that is causing the file=/ duplication.

Lastly I struggle with not understanding what the objective is in the slash dot arguments in terms of how they need to be transformed since I don't have a before and an after example to work with. If I knew what is needed I could either fix the problem and provide a solution for others or correct the REGEX value to work with IIS correctly. I suspect the REGEX value is invalid. That's what I think. However, we might also find that IIS has some kind of inherent problem that we can't fix with REGEX transformations but could with additional .php scripting which I am capable of doing. I just need to know what needs to be accomplished.
In reply to Perry Way

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Liam Moran -
Picture of Core developers
That rewrite rule looks to be doing exactly what you attest:
/mod/lti/services.php/file=/8612/lineitems&type_id=2709
becomes
/mod/lti/services.php/?file=/file=/8612/lineitems&type_id=2709
The second capture group is everything from the forward slash after .php ; the rewrite rule says to put ?file= in between .php and that capture group.

The regex seems overly aggressive to me, but if this is the only problem you see: to fix this specifically, you could run add a highly targeted rewrite rule to run before the one breaking this url and stop running rules after that:
Pattern (check ignore case): /mod/lti/services.php/(file=)(.*)
Rewrite URL: /mod/lti/services.php?file={R:2}

And check "Stop processing of subsequent rules" on both of these rewrite rules.

That would rewrite things like:
/mod/lti/services.php/file=/8612/lineitems&type_id=2709
to:
/mod/lti/services.php?file=/8612/lineitems&type_id=2709

That would only run on these particular services requests where the first parameter has file as its name.
Average of ratings: Useful (1)
In reply to Liam Moran

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Liam Moran -
Picture of Core developers
I hit "Post to forum" prematurely.

I'm pretty sure the url you want is going to be: /mod/lti/services.php/8216/lineitems?type_id=2709

That's not what the rewrite rules I suggested would get you, but given what IIS is getting, I think you can rewrite to that and see if this works. (I'm jumping into meetings for the rest of the day)

My hunch is that the rewrite rule needs to be prevented from running on this path, for sure, and putting one that gets what you want in front of it is the way I'd attack the problem.
In reply to Liam Moran

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Perry Way -
Thanks. I'm going to give this idea a try.
In reply to Perry Way

Re: IIS - Moodle LTI does not work for two way communications with LTI providers on IIS

by Liam Moran -
Picture of Core developers
I took a look at my logs and see grade service api calls like:
/mod/lti/services.php/{course['id']}/lineitems/?type_id={lti_types['id']}
and:
/mod/lti/services.php/{course['id']}/lineitems/{grade_items['id']}/lineitem/scores?type_id={lti_types['id']}

You can use Failed Request Tracing to figure out what IIS is getting from the tools to rewrite to those formats before the other .php/stuff rule is run to get things working.