Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate the LTI 1.3 access token audience and URL. #2342

Merged
merged 3 commits into from
Mar 17, 2024

Conversation

drgrice1
Copy link
Member

This adds a new LTI 1.3 authentication parameter named $LTI{v1p3}{AccessTokenAUD}. This is used for the audience (aud) in the signed JWT that is sent when requesting an access token from the LMS. This access token is used for grade passback.

Previously the $LTI{v1p3}{AccessTokenURL} was used for both the audience and the actual URL that the access token request containing the signed JWT is sent to. I suspect that the audience and the URL may not be the same for all LMS's. They are the same for Moodle. These also needed to be the same for testing on my local Canvas instance. However, @Alex-Jordan showed me some information from D2L that indicates these are different there. I suspect these may need to be different for Canvas in production as well.

@Alex-Jordan
Copy link
Contributor

I found a moment to try this. I cannot try it with a development WW server without coordination with the D2L people here. In our D2L test server, there is a deployment set up for our production WW server. OK, so here is what I did with the production WW server:

  • added the one line to the config file, using the URL for "audience" that my PCC D2L contact had previously given me in that spreadsheet I showed you (https://api.brightspace.com/auth/token). I verified the other settings still match what I was previously given for them from our D2L team.
  • edited that one line in lib/WeBWorK/Authen/LTIAdvantage/SubmitGrade.pm as in this PR.
  • restarted webwork2, but as often happens, something failed and a reboot brought it back. This is some SELinux issue that creeps in over time that I haven't figures out. Anyway after the reboot it's fine, with webwork2 (and webwork2-job-queue) running.
  • In the test D2L server, in a course, there is an "External Learning Tool" using the deployment the D2L team already set up. Its URL is https://webwork.pcc.edu/webwork2/new-lti-1p3-test (just to confirm it is pointing to our production server).
  • In a content area, I set up a link using that ELT.
  • The WW course has grade passback mode set to 'course' (just testing 'course' for now; can look at 'homework' later)
  • The WW course has both debug options on, however as I think you know, with LTI 1.3 I'm not sure they will have an impact.
  • To be clear, the WW course has this in course.conf:
$authen{user_module} = [
{ '*' => 'WeBWorK::Authen::LTIAdvantage' }, # first try LTI 1.3
{ '*' => 'WeBWorK::Authen::Basic_TheLastOption' } # fallback authorization method
];
include('conf/authen_LTI_1_3.conf');
$LTIVersion = 'v1p3';

$debug_lti_parameters = 1;
$debug_lti_grade_passback = 1;

as well as grade passback set to 'course' in simple.conf

  • There is one assignment in the WW course. I have entered the WW course via the D2L test server course. (Single sign-on still works.)
  • When I click to submit an answer to a question, I get:
Warning messages

    Submitting all grades for user alex.jordan
    Failed to obtain access token from LMS:
    Bad Request

This is not different from what I had when I last looked into this, probably at this time:
https://webwork.maa.org/moodle/mod/forum/discuss.php?d=8333#p20580

  • There is no grade data appearing in the D2L course Grades area.

Do you have any thoughts observations about it? Has develop branch had any other LTI related changes compared to main that I should include?

@drgrice1 drgrice1 force-pushed the lti-1.3-audience branch 2 times, most recently from 16e8305 to 3409fcf Compare February 28, 2024 02:07
@Alex-Jordan
Copy link
Contributor

I see what your updates are doing, and I will try it with them. But one thing is at the moment you still have v1p1 in the conf file instead of v1p3. But more importantly, I already used warn statements today to look at $c->url_for('root')->to_abs->to_string and it was indeed https. So I will try things again tonight, I'm just not optimistic that this is the issue.

@drgrice1
Copy link
Member Author

Hmm. Then I will remove that commit.

@drgrice1
Copy link
Member Author

It is odd that $c->url_for('root')->to_abs->to_string in lib/WeBWorK/Authen/LTIAdvantage/SubmitGrade.pm has https but when $c->url_for->to_abs is called on line 459 of lib/WeBWorK/Authen/LTIAdvanced.pm (for LTI 1.1) it does not?

@Alex-Jordan
Copy link
Contributor

I checked, and at this time both are https. I'm sorry, I just reviewed emails from the summer and on or about August 9, we actually set up https for the WeBWorK server whilst grasping at straws. So I guess at that time, $LTI{v1p1}{OverrideSiteProtocolDomain} became unnecessary for me at that time. It is still set, but I suppose it's just replacing https with https now.

That message from the D2L vendor support team that said When launching the tool we see an error in the system log. Redirect Uri must match one of the registered Redirect URL values. The Redirect URI that is being sent is : RedirectUri http://webwork.pcc.edu/webwork2/ltiadvantage/launch came on August 4, before the change. It will be worth asking them to look at this again to see if they still see http or if now they see whatever the next issue is.

@Alex-Jordan
Copy link
Contributor

I'm poring over the $request from after line 157 in LTIAdvantage/SubmitGrade.pm, using a warn statement to look for anything suspect. I only see two things, and don't know what to make of them.

  • $request->{local_port} is 51130 (actually it changes each time) and $request->{remote_port} is 443.
  • $request->{req}{version} is 1.1. Is that refering to an LTI version?

@drgrice1
Copy link
Member Author

drgrice1 commented Feb 28, 2024

The $request object is a Mojo::Transaction::HTTP. The local_port is the local interface port (see https://docs.mojolicious.org/Mojo/Transaction#local_port). That is the port that the Mojolicious UserAget object for the request gets delegated to. That will be different for each each request. The $request->{req} is a Mojo::Message::Request which derives from a Mojo::Message. The version for that is the HTTP version (see https://docs.mojolicious.org/Mojo/Message#version) which defaults to 1.1. Those are really details of the request sent by webwork2 for the access token.

What we are really interested in is the $response. That is the response from D2L. One thing you could try is to add $c->log->info($c->dumper($response)) after line 177 of LTIAdvantage/SubmitGrade.pm. Although that will be a lot more than is really of interest. More specifically you could do $c->log->info($response->body) That will show the entire body of the response. Although, I suspect that all you will see is something like { "message": "Bad Request", ... } with a few more keys in that object. As I mentioned before, LMS's don't reveal much of what is going wrong here.

@drgrice1
Copy link
Member Author

Another thing you could try is to comment out line 143 (or maybe instead line 146) of LTIAdvantage/SubmitGrade.pm. That is the oddity between making this work for both Moodle and Canvas. Moodle needs line 146. Canvas needs line 143 (and I think also line 146 -- I don't recall exactly). Fortunately, having line 143 didn't cause a problem for Moodle, but maybe it does for D2L?

I am pretty sure that the problem is something not being quite right in the encoded JWT for D2L. For both Moodle and Canvas I had to delve into their code to figure out what was needed to get this to work. Unfortunately, no one seems to just follow the LTI Advantage specifications exactly (or they all have their own interpretation of those specifications that vary slightly).

@Alex-Jordan
Copy link
Contributor

Alex-Jordan commented Feb 28, 2024 via email

@drgrice1 drgrice1 force-pushed the lti-1.3-audience branch 3 times, most recently from 7635f54 to 3fc8f3e Compare February 29, 2024 22:01
Copy link
Contributor

@Alex-Jordan Alex-Jordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we are still investigating the larger issue, but as far as this PR goes, it seems good for a merge.

@drgrice1
Copy link
Member Author

drgrice1 commented Mar 7, 2024

This now also switches from using the webwork server url for the iss claim to using the client id in the JWT sent when requesting an access token from the LMS for grade passback.

With this change this is confirmed to work for Moodle, Canvas, and D2L.

Copy link
Contributor

@Alex-Jordan Alex-Jordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested in production (just the changes here applies to 2.18) and it works.

@drgrice1
Copy link
Member Author

drgrice1 commented Mar 7, 2024

Should this be made a hotfix?

@Alex-Jordan
Copy link
Contributor

I guess it should be a hotfix. I'm thinking about a school that uses D2L, and is stuck with 2.18 for some reason.

pstaabp added a commit that referenced this pull request Mar 13, 2024
Separate the LTI 1.3 audience and URL and correct iss claim (hotfix of #2342)
@Alex-Jordan
Copy link
Contributor

I think this is very safe to merge, if @pstaabp, @dlglin, @drdrew42, @somiaj, or @taniwallach want to look over the very small amount of code changes. There are three things here:

  • typo corrections
  • account for the audience access token
  • change the issuer for access tokens requests to be the client ID

This has been tested with D2L, Moodle, and Canvas and it seems that each change is a good change.

@drgrice1
Copy link
Member Author

Could someone merge this? The hotfix version of this was already merged. So this should be as well.

This adds a new LTI 1.3 authentication parameter named
`$LTI{v1p3}{AccessTokenAUD}`.  This is used for the audience (`aud`) in
the signed JWT that is sent when requesting an access token from the
LMS.  This access token is used for grade passback.

Previously the `$LTI{v1p3}{AccessTokenURL}` was used for both the
audience and the actual URL that the access token request containing the
signed JWT is sent to.  I suspect that the audience and the URL may not
be the same for all LMS's.  They are the same for Moodle.  These also
needed to be the same for testing on my local Canvas instance.  However,
@Alex-Jordan showed me some information from D2L that indicates these
are different there.  I suspect these may need to be different for
Canvas in production as well.
This switches from using the webwork server url for the iss claim to
using the client id in the JWT sent when requesting an access token from
the LMS for grade passback.

This is confirmed to work on Moodle, Canvas, and D2L.
@Alex-Jordan Alex-Jordan merged commit 7875f15 into openwebwork:develop Mar 17, 2024
2 checks passed
@drgrice1 drgrice1 deleted the lti-1.3-audience branch March 18, 2024 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants