Hi everyone,
At my college, we are currently running WeBWorK 2.19 on Ubuntu 24.04.2 LTS. We’re trying to integrate it with D2L Brightspace using LTI 1.3, but it’s not working as expected.
This semester, students are logging in directly using bulk-created accounts. However, I’d like to get the LTI integration working by the summer term so students can log in via Brightspace.
We followed the configuration steps from the official guide:
https://webwork.maa.org/wiki/Desire2Learn_Brightspace_LTI_1.3_Configuration
The server itself is running fine. But when we try to access WeBWorK through a Brightspace link, it redirects to the login page with this URL:https://webwork.qcc.cuny.edu/webwork2/ltiadvantage/login
Even when I try to log in using my admin credentials, I get the following error:
"No WeBWorK course was found associated to this LMS course. If this is an error, please contact the WeBWorK system administrator."
I’ve enabled $debug_lti_parameters = 1;
but no debug info is displayed when accessing WeBWorK via the Brightspace link.
I've double-checked the settings and everything seems correct—but clearly, something’s off.
I’d really appreciate any suggestions on how to resolve this issue. Below, I’ve included the registration information, configuration settings, and relevant debug.log
message from one of my LTI login attempts.
Thanks in advance for any help!
------------------
** Register as a standard tool
Name: QCC WeBWorK
Description: QCC WeBWorK
Domain: https://webwork.qcc.cuny.edu
Redirect URLs: https://webwork.qcc.cuny.edu/webwork2/ltiadvantage/launch
OpenID Connect Login URL: https://webwork.qcc.cuny.edu/webwork2/ltiadvantage/login
Target Link URI: https://webwork.qcc.cuny.edu/webwork2
Keyset URL: https://webwork.qcc.cuny.edu/webwork2/ltiadvantage/keys
Under Roles, option selected: "Send Institution Role."
------------------
** Settings in authen_LTI.conf file:
$debug_lti_parameters = 1;
$debug_lti_grade_passback = 1;
$authen{user_module} = [
{ '*' => 'WeBWorK::Authen::LTIAdvantage' }, # first try LTI 1.3
#{ '*' => 'WeBWorK::Authen::LTIAdvanced' }, # next try LTI 1.1
{ '*' => 'WeBWorK::Authen::Basic_TheLastOption' } # fallback authorization method
];
$authen{admin_module} = [
#'WeBWorK::Authen::LTIAdvantage',
#'WeBWorK::Authen::LTIAdvanced',
'WeBWorK::Authen::Basic_TheLastOption'
];
include('conf/authen_LTI_1_3.conf');
$LTIVersion = 'v1p3';
$LTIAccountCreationCutoff = 'professor';
$LMSManageUserData = 1;
$external_auth = 0;
$LTIGradeMode = 'homework';
$LTIGradeOnSubmit = 1;
$LTICheckPrior = 0;
$LTIMassUpdateInterval = 86400;
------------------
** Settings in authen_LTI_1_3.3_conf:
$LTI{v1p3}{LMS_name} = 'Brightspace';
$LTI{v1p3}{LMS_url} = 'https://cunytest.brightspace.com';
$LTI{v1p3}{preferred_source_of_username} = 'ext_d2l_orgdefinedid';
$LTI{v1p3}{fallback_source_of_username} = 'email';
$LTI{v1p3}{strip_domain_from_email} = 1;
$LTI{v1p3}{lowercase_username} = 0;
$LTI{v1p3}{preferred_source_of_student_id} = 'ext_d2l_orgdefinedid';
$LTI{v1p3}{PlatformID} = 'https://cunytest.brightspace.com';
$LTI{v1p3}{ClientID} = 'd2f5a284-4b52-46be-960c-61a347afe524';
$LTI{v1p3}{DeploymentID} = 'd1810a4a-fb3a-4c4c-a7c7-bb56050c4c97';
$LTI{v1p3}{PublicKeysetURL} = 'https://cunytest.brightspace.com/d2l/.well-known/jwks';
$LTI{v1p3}{AccessTokenURL} = 'https://auth.brightspace.com/core/connect/token';
$LTI{v1p3}{AccessTokenAUD} = 'https://api.brightspace.com/auth/token';
$LTI{v1p3}{AuthReqURL} = 'https://cunytest.brightspace.com/d2l/lti/authenticate';
$LTI{v1p3}{StateKeyLifetime} = 60;
$LTI{v1p3}{LMSrolesToWeBWorKroles} = {
'librarian' => 'guest',
'observer' => 'guest',
'visitor' => 'guest',
'Guest' => 'guest',
'Administrator' => 'professor',
'Designer' => 'professor',
'instructor' => 'professor',
'Instructor' => 'professor',
'Faculty' => 'professor',
'Teacher' => 'professor',
'Student' => 'student',
'Learner' => 'student',
'student' => 'student',
'AI/TA' => 'ta',
'TA' => 'ta',
'Teaching Assistant' => 'ta',
'Teaching Assistant (TA)' => 'ta',
'Non-editing teacher' => 'ta',
'Grader' => 'ta',
};
# Do not change this.
$LTI{v1p3}{grader} = 'WeBWorK::Authen::LTIAdvantage::SubmitGrade';
------------------
** Debug message:
===> Begin WeBWorK::dispatch() <===
[Fri Apr 11 00:56:29.636715 2025] (eval): Hi, I'm the new dispatcher!
[Fri Apr 11 00:56:29.636787 2025] (eval): --------------------------------------------------------------------------------
[Fri Apr 11 00:56:29.636884 2025] (eval): Okay, I got some basic information:
[Fri Apr 11 00:56:29.636939 2025] (eval): The site location is /webwork2
[Fri Apr 11 00:56:29.636984 2025] (eval): The request method is POST
[Fri Apr 11 00:56:29.637107 2025] (eval): The URI is /webwork2/ltiadvantage/login
[Fri Apr 11 00:56:29.637162 2025] (eval): The argument string is iss=https%3A%2F%2Fcunytest.brightspace.com&login_hint=329eacc0-17be-481c-9089-1ec42e1e44bc_30131&target_link_uri=https%3A%2F%2Fwebwork.qcc.cuny.edu%2Fwebwork2%2Fbsosnovski_MA119%2FMA10ALP_1_Order_of_Operations_and_Substitution<i_deployment_id=d1810a4a-fb3a-4c4c-a7c7-bb56050c4c97&client_id=d2f5a284-4b52-46be-960c-61a347afe524<i_message_hint=G39Wk34MlGYDD4KP9ZP2ylMvzFnG1KTWsQpVTU4xcDw%7E
[Fri Apr 11 00:56:29.637211 2025] (eval): --------------------------------------------------------------------------------
[Fri Apr 11 00:56:29.637295 2025] (eval): The path is /ltiadvantage/login/
[Fri Apr 11 00:56:29.637369 2025] (eval): The current route is ltiadvantage_login
[Fri Apr 11 00:56:29.637417 2025] (eval): Here is some information about this route:
[Fri Apr 11 00:56:29.637471 2025] (eval): The display module for this route is WeBWorK::ContentGenerator::LTIAdvantage
[Fri Apr 11 00:56:29.637514 2025] (eval): This route has the following captures:
[Fri Apr 11 00:56:29.637567 2025] (eval): action => login
[Fri Apr 11 00:56:29.637611 2025] (eval): controller => LTIAdvantage
[Fri Apr 11 00:56:29.637653 2025] (eval): --------------------------------------------------------------------------------
[Fri Apr 11 00:56:29.637695 2025] (eval): Now we want to look at the parameters we got.
[Fri Apr 11 00:56:29.637735 2025] (eval): The raw params:
[Fri Apr 11 00:56:29.637897 2025] (eval): login_hint => "329eacc0-17be-481c-9089-1ec42e1e44bc_30131"
[Fri Apr 11 00:56:29.637970 2025] (eval): lti_message_hint => "G39Wk34MlGYDD4KP9ZP2ylMvzFnG1KTWsQpVTU4xcDw~"
[Fri Apr 11 00:56:29.638020 2025] (eval): iss => "https://cunytest.brightspace.com"
[Fri Apr 11 00:56:29.638066 2025] (eval): client_id => "d2f5a284-4b52-46be-960c-61a347afe524"
[Fri Apr 11 00:56:29.638112 2025] (eval): target_link_uri => "https://webwork.qcc.cuny.edu/webwork2/bsosnovski_MA119/MA10ALP_1_Order_of_Operations_and_Substitution"
[Fri Apr 11 00:56:29.638157 2025] (eval): lti_deployment_id => "d1810a4a-fb3a-4c4c-a7c7-bb56050c4c97"
[Fri Apr 11 00:56:29.638200 2025] (eval): --------------------------------------------------------------------------------
[Fri Apr 11 00:56:29.638376 2025] (eval): We need to get a course environment (with or without a courseID!)
[Fri Apr 11 00:56:29.645457 2025] (eval): Here's the course environment: WeBWorK::CourseEnvironment=HASH(0x5f52edb310c0)
[Fri Apr 11 00:56:29.646113 2025] (eval): Using authentication module WeBWorK::Authen::Basic_TheLastOption: WeBWorK::Authen::Basic_TheLastOption=HASH(0x5f52edb34060)
[Fri Apr 11 00:56:29.646224 2025] (eval): We got a courseID from the route, now we can do some stuff:
[Fri Apr 11 00:56:29.646289 2025] (eval): ...we can create a database object...
[Fri Apr 11 00:56:29.657451 2025] (eval): (here's the DB handle: WeBWorK::DB=HASH(0x5f52edaec9a0))
[Fri Apr 11 00:56:29.657582 2025] WeBWorK::Authen::verify: BEGIN VERIFY
[Fri Apr 11 00:56:29.657658 2025] WeBWorK::Authen::do_verify: db ok
[Fri Apr 11 00:56:29.657719 2025] WeBWorK::Authen::get_credentials: self is WeBWorK::Authen::Basic_TheLastOption=HASH(0x5f52edb34060)
[Fri Apr 11 00:56:29.658139 2025] WeBWorK::Authen::fetchCookie: fetchCookie: Session cookie does not contain valid information. Returning nothing.
[Fri Apr 11 00:56:29.658308 2025] WeBWorK::Authen::verify: END VERIFY
[Fri Apr 11 00:56:29.658371 2025] WeBWorK::Authen::verify: result 0
[Fri Apr 11 00:56:29.658460 2025] (eval): Bad news: authentication failed!
[Fri Apr 11 00:56:29.658512 2025] (eval): Rendering WeBWorK::ContentGenerator::Login
[Fri Apr 11 00:56:29.666567 2025] WeBWorK::Authen::store_session: The cookie session is expired.
[Fri Apr 11 00:56:33.683067 2025] (eval):