Installation

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Allen Crowe -
Number of replies: 10

We have a WeBWork 2.20 up and running and we're trying to integrate it with a hosted LMS (BLackboard) LTI 1.1 since there are no clear instructions for LTI 1.3.   When we try to link Blackboard with WeBWork we're getting the error below.  Any help would be appreciated

It looks like its not getting the User_ID info from Blackboard

WeBWorK error
An error occurred while processing your request.

For help, please send mail to this site's webmaster, including all of the following information as well as what what you were doing when the error occurred.

Error record identifier
392c56dd-6b1b-5fd0-bff1-e4cdd3d89c18::01b53287-9329-11f0-9984-805e29ef6474

Error messages
hasPermissions called with 1 arguments instead of the expected 2: 'access_instructor_tools' at /opt/webwork/webwork2/lib/WeBWorK/ContentGenerator/ProblemSets.pm line 33.

Context
28: my $course_info_path = "$ce->{courseDirs}{templates}/$ce->{courseFiles}{course_info}";
29:
30: my $text = DEFAULT_COURSE_INFO_TXT;
31: eval { $text = readFile($course_info_path) } if -f $course_info_path;
32:
33: return $c->authz->hasPermissions($c->param('user'), 'access_instructor_tools')
34: || $text ne DEFAULT_COURSE_INFO_TXT;
35: }
36:
37: return $c->SUPER::can($arg);
38: }
Call stack
in Mojolicious::_die called at line 289 of /usr/lib/x86_64-linux-gnu/perl-base/Carp.pm
in Carp::croak called at line 187 of /opt/webwork/webwork2/lib/WeBWorK/Authz.pm
in WeBWorK::Authz::hasPermissions called at line 33 of /opt/webwork/webwork2/lib/WeBWorK/ContentGenerator/ProblemSets.pm
in WeBWorK::ContentGenerator::ProblemSets::can called at line 112 of /opt/webwork/webwork2/lib/WeBWorK/ContentGenerator.pm
in (eval) called at line 94 of /opt/webwork/webwork2/lib/WeBWorK/ContentGenerator.pm
in WeBWorK::ContentGenerator::go called at line 193 of /usr/share/perl5/Mojolicious.pm
in Mojolicious::_action called at line 15 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::__ANON__ called at line 151 of /opt/webwork/webwork2/lib/Mojolicious/WeBWorK.pm
in (eval) called at line 131 of /opt/webwork/webwork2/lib/Mojolicious/WeBWorK.pm
in Mojolicious::WeBWorK::__ANON__ called at line 15 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::__ANON__ called at line 18 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::emit_chain called at line 88 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::_action called at line 161 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::_controller called at line 44 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::continue called at line 46 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::continue called at line 46 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::continue called at line 52 of /usr/share/perl5/Mojolicious/Routes.pm
in Mojolicious::Routes::dispatch called at line 127 of /usr/share/perl5/Mojolicious.pm
in Mojolicious::dispatch called at line 136 of /usr/share/perl5/Mojolicious.pm
in Mojolicious::__ANON__ called at line 15 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::__ANON__ called at line 203 of /usr/share/perl5/Mojolicious.pm
in (eval) called at line 203 of /usr/share/perl5/Mojolicious.pm
in Mojolicious::_exception called at line 15 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::__ANON__ called at line 18 of /usr/share/perl5/Mojolicious/Plugins.pm
in Mojolicious::Plugins::emit_chain called at line 141 of /usr/share/perl5/Mojolicious.pm
in Mojolicious::handler called at line 72 of /usr/share/perl5/Mojo/Server.pm
in Mojo::Server::__ANON__ called at line 15 of /usr/share/perl5/Mojo/EventEmitter.pm
in Mojo::EventEmitter::emit called at line 103 of /usr/share/perl5/Mojo/Server/Daemon.pm
in Mojo::Server::Daemon::__ANON__ called at line 15 of /usr/share/perl5/Mojo/EventEmitter.pm
in Mojo::EventEmitter::emit called at line 60 of /usr/share/perl5/Mojo/Transaction/HTTP.pm
in Mojo::Transaction::HTTP::server_read called at line 224 of /usr/share/perl5/Mojo/Server/Daemon.pm
in Mojo::Server::Daemon::_read called at line 202 of /usr/share/perl5/Mojo/Server/Daemon.pm
in Mojo::Server::Daemon::__ANON__ called at line 15 of /usr/share/perl5/Mojo/EventEmitter.pm
in Mojo::EventEmitter::emit called at line 109 of /usr/share/perl5/Mojo/IOLoop/Stream.pm
in Mojo::IOLoop::Stream::_read called at line 57 of /usr/share/perl5/Mojo/IOLoop/Stream.pm
in Mojo::IOLoop::Stream::__ANON__ called at line 141 of /usr/share/perl5/Mojo/Reactor/Poll.pm
in (eval) called at line 141 of /usr/share/perl5/Mojo/Reactor/Poll.pm
in Mojo::Reactor::Poll::_try called at line 54 of /usr/share/perl5/Mojo/Reactor/EV.pm
in Mojo::Reactor::EV::__ANON__ called at line 32 of /usr/share/perl5/Mojo/Reactor/EV.pm
in (eval) called at line 32 of /usr/share/perl5/Mojo/Reactor/EV.pm
in Mojo::Reactor::EV::start called at line 134 of /usr/share/perl5/Mojo/IOLoop.pm
in Mojo::IOLoop::start called at line 152 of /usr/share/perl5/Mojo/Server/Prefork.pm
in Mojo::Server::Prefork::_spawn called at line 93 of /usr/share/perl5/Mojo/Server/Prefork.pm
in Mojo::Server::Prefork::_manage called at line 78 of /usr/share/perl5/Mojo/Server/Prefork.pm
in Mojo::Server::Prefork::run called at line 74 of /usr/share/perl5/Mojo/Server/Hypnotoad.pm
in Mojo::Server::Hypnotoad::run called at line 14 of /usr/bin/hypnotoad
Request information
The HTTP request information is included in the following table.

HTTP request information
Item Data
Method POST
URI http://mpt25.math.sc.edu/webwork2/
HTTP Headers
HTTP request headers
Key Value
Accept-Encoding gzip, deflate, br, zstd
sec-fetch-dest iframe
sec-fetch-site cross-site
Content-Type application/x-www-form-urlencoded
priority u=0, i
sec-fetch-storage-access active
Content-Length 2850
sec-ch-ua Chromium;v=140, Not=A?Brand;v=24, Google Chrome;v=140
upgrade-insecure-requests 1
Origin https://usc-stage-saas.blackboard.com
sec-ch-ua-mobile ?0
Cache-Control max-age=0
sec-ch-ua-platform "Windows"
sec-fetch-mode navigate
User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Accept-Language en-US,en;q=0.9
Host mpt25.math.sc.edu
X-Forwarded-For 75.182.7.171
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
referer https://usc-stage-saas.blackboard.com/
X-Forwarded-Proto https
X-Amzn-Trace-Id Root=1-68c9a90d-76a814363cf1497032750d6b
X-Forwarded-Port 443

In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Danny Glin -

Some thoughts:

If you haven't done so already, you should set $debug_lti_parameters=1; in authen_LTI.conf (if you are only testing this for a single course on your server you can set that variable in course.conf for that course).  This will give you more details about what Blackboard is sending to WeBWorK.

If the username is not getting set it could be because WW is not looking for the correct parameter that is sent by Blackboard.  You may need to adjust the $LTI{v1p1}{preferred_source_of_username} variable in authen_LTI_1_1.conf to match what Blackboard is sending.  When you enable debugging you should get a list of the parameters that are being sent, so you can set this accordingly.

I also notice that in the error you posted the URI has http rather than https.  I have run into issues in the past with LTI connections where the tool provider isn't set to https, so that may or may not be related.

In reply to Danny Glin

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Allen Crowe -
Hey Danny,
Thanks for the response, so I do have $debug_lti_parameters=1, turned on. The error included in the original post is all we get, this is the HTML error. The webwork2.log gives me "[2025-09-17 15:04:12.51477] [7113] [error] [NBQmDwLw_4BF] hasPermissions called with 1 arguments instead of the expected 2: 'access_instructor_tools' at /opt/webwork/webwork2/lib/WeBWorK/ContentGenerator/Prob>
[2025-09-17 15:04:12.51709] [7113] [error] [NBQmDwLw_4BF] [392c56dd-6b1b-5fd0-bff1-e4cdd3d89c18::1910f1f7-93f9-11f0-92ee-b35790893752] [http://mpt25.math.sc.edu/webwork2/] {"Error record identifier":"392c56dd>"

Is there another log file, that I'm not aware of?
In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Danny Glin -

If you have $debug_lti_parameters enabled you should get a warning message at the bottom of the WeBWorK page which shows all of the LTI parameters.  If you're not seeing that then it suggests that the LTI process isn't happening.

That usually means that either Blackboard is not sending an LTI request, or WeBWorK does not have the LTI authentication module enabled.  Double check that you are using an LTI link from Blackboard and not a regular web link.  Once that's confirmed, check that the WeBWorK course you are testing is set to use LTI 1.1 authentication.  There are a couple of things to confirm:

  1. Check that $authen{user_module} contains WeBWorK::Authen::LTIAdvanced (along with whatever other authentication methods you are using).  This is set by default in authen_LTI.conf, but if you have enabled other authentication modules later in your configuration it may have been overridden.
  2. Check that $LTIVersion is set to 'v1p1'.  This is also the default in authen_LTI.conf, so it should be fine as long as that hasn't been changed.
In reply to Danny Glin

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Allen Crowe -
This is what I have in the "authen_LTI.conf". It looks like I have those settings correct. We are using the LTI link option in Blackboard ULTRA, not the regular web link. Excuse my lack of knowledge but how do I check the WeBWorK course to make sure it is set to use LTI 1.1?
$authen{user_module} = [
# 'WeBWorK::Authen::LTIAdvantage', # first try LTI 1.3
'WeBWorK::Authen::LTIAdvanced', # next try LTI 1.1
# 'WeBWork::Authen::LDAP', # LDAP
'WeBWorK::Authen::Basic_TheLastOption' # fallback authorization method
];

# List of authentication modules that may be used to enter the admin course.
# This is used instead of $authen{user_module} when logging into the admin course.
# Since the admin course provides overall power to add/delete courses, access
# to this course should be protected by the best possible authentication you
# have available to you.
$authen{admin_module} = [
#'WeBWorK::Authen::LTIAdvantage',
#'WeBWorK::Authen::LTIAdvanced',
'WeBWorK::Authen::Basic_TheLastOption'
];

# Include configurations. You must uncomment at least one of the following. You may uncomment
# both if the site may be using both LTI 1.1 and 1.3 in different courses. After uncommenting
# the LTI_1_x line, you must copy the file authen_LTI_1_x.conf.dist to authen_LTI_1_x.conf and
# then edit that file to fill in the settings for LTI_1_x.
#include('conf/authen_LTI_1_1.conf');
include('conf/authen_LTI_1_1.conf');

# This is the default LTI version that will be used for the site. This must be 'v1p1' for LTI
# 1.1 authentication, 'v1p3' for LTI 1.3 authentication, or '' to disable LTI authentication.
# A course may override this setting to use the other version of LTI authentication or to
# disable LTI authentication for the course.
$LTIVersion = 'v1p1';
In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Glenn Rice -
Check what is is localOverrides.conf. Is authen_LTI.conf included in that file? Also check to make sure that that file does not set $authen{user_module} anywhere (at least not after authen_LTI.conf is included). Also check the course.conf file for the course that you are using and make sure it doesn't change any of these variables.
In reply to Danny Glin

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Allen Crowe -
Thanks with your help, we've resolved the first error by correcting the LTI link from Blackboard, we were not pointing it directly at a class. Now we are getting :
Warning messages
===== parameters received =======
context_title => Artisanal Ice Cream Making
oauth_nonce => 116960823786270
oauth_signature => LhChyAAj8OHRca6/ndvAXclzCls=
lis_person_sourcedid => bba_katie
lis_person_name_full => Katie Vaughan
lti_version => LTI-1p0
launch_presentation_locale => en-US
oauth_signature_method => HMAC-SHA1
tool_consumer_instance_name => REDACTED
oauth_consumer_key => webwork220
launch_presentation_return_url => https://REDACTED.blackboard.com/webapps/blackboard/execute/blti/launchReturn?course_id=_12809…
oauth_callback => about:blank
custom_caliper_profile_url => https://clone-ops-2471958-sc.blackboard.com/learn/api/v1/telemetry/caliper/profile/_24234455_1
ext_fnds_user_id => b049a593-93cc-11ef-b202-0ff226ae1140
custom_caliper_federated_session_id => https://caliper-mapping.cloudbb.blackboard.com/v1/sites/02fd7d5c-c6c6-4a6a-9b5a-41e60a5a68b5/sessio…
context_label => ARTISAN-ICE-CREAM-DEMO
tool_consumer_info_version => 3902.1.0-rel.11+3e868a1
tool_consumer_info_product_family_code => BlackboardLearn
ext_fnds_region => us-east-1
roles => urn:lti:role:ims/lis/Instructor,urn:lti:sysrole:ims/lis/Administrator,urn:lti:role:ims/lis/Administrator
user_id => a8a0dd2489004561842009fdce21239d
context_id => b935b8e35f4e4941bfd33cad65cca59e
lis_person_contact_email_primary => kvaughan@REDACTED
tool_consumer_instance_contact_email => BBSUPTREDACTED
lti_message_type => basic-lti-launch-request
ext_lms => bb-3902.1.0-rel.11+3e868a1
lis_person_name_family => Vaughan
launch_presentation_document_target => window
tool_consumer_instance_description => REDACTED
custom_tc_profile_url => https://REDACTED.blackboard.com/learn/api/v1/lti/profile?lti_version=LTI-1p0
ext_fnds_tenant_id => 8faa23c6-4fb6-4016-a218-3d40b5c6adc1
resource_link_title => WeBWorK2.20 test
ext_launch_id => 517cc5eb-bf02-4e80-9df4-d2fd39bc6fc0
tool_consumer_instance_guid => c15714022dd34ef8a299e47fad034a4b
ext_fnds_site_id => 02fd7d5c-c6c6-4a6a-9b5a-41e60a5a68b5
oauth_timestamp => 1758197843
lis_person_name_given => Katie
oauth_version => 1.0
ext_fnds_course_id => e45fb890-93d2-11ef-b71d-2fc0c1991c9f
ext_launch_presentation_css_url => https://REDACTED.blackboard.com/common/shared.css,https://REDACTED.blackboard.com/theme…
resource_link_id => _24234455_1
============================
===== timestamp info =======
oauth_nonce = 1758197843
WW_server_time = 1758197844
diff(server-oauth) = 1 seconds (0.0166666666666667 minutes)
============================
=========== summary ============
User id is |kvaughan| (obtained from lis_person_contact_email_primary which was preferred_source_of_username)
User mail address is |kvaughan@REDACTED|
strip_domain_from_email is |1|
Student id is |bba_katie|
preferred_source_of_username is |lis_person_contact_email_primary|
fallback_source_of_username is ||
preferred_source_of_student_id is |lis_person_sourcedid|
================================
The following path was reconstructed by WeBWorK. It should match the path in the LMS:
https://mpt25.math.sc.edu
OAuth verification failed. Check the Consumer Secret and that the URL in the LMS exactly matches the WeBWorK URL as defined in site.conf. E.G. Check that if you have https in the LMS url then you have https in $server_root_url in site.conf at /opt/webwork/webwork2/lib/WeBWorK/Authen/LTIAdvanced.pm line 436.
In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Glenn Rice -
Have you verified the things that the last message talks about?

Is the URL in site.conf https://mpt25.math.sc.edu? And is that the base URL of the link you created in Blackboard?

Is the consumer secret in conf/authen_LTI_1_1.conf in the variable $LTI{v1p1}{BasicConsumerSecret} exactly the same as the consumer secret set for the external tool in Blackboard?
In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Glenn Rice -

The error that you are showing is coming from line 33 of ProblemSets.pm.  That is rather odd as that code should never be reached unless authentication was successful.

Do you have any local modifications to the code or something else going on?  If you run "git status" in the /opt/webwork/webwork2 directory, what does it show?

In reply to Glenn Rice

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Allen Crowe -

Nothing has been modified in ProblemSets.pm. 

When I run the "git status" as user UBUNTU, I get -

fatal: detected dubious ownership in repository at '/opt/webwork/webwork2'
To add an exception for this directory, call:

        git config --global --add safe.directory /opt/webwork/webwork2

When I run the same command "git status" as WWADMIN, I get - 

On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        htdocs/USC_site_info.txt
        htdocs/index.hmtl
        lib/WeBWorK.bk
        lib/WebworkWebservice.bk

nothing added to commit but untracked files present (use "git add" to track)

In reply to Allen Crowe

Setting up WeBWork 2.20 with Blackboard using LTI 1.1

by Glenn Rice -

The first error is expected.  Git can only be run as the user that owns the git clone.  Your UBUNTU user does not own /opt/webwork/webwork2.

So it seems that you do not have any modified files.  So on to other debugging.

Another thing that I thought of is the $LTI{v1p1}{modify_user} method.  Do you have that uncommented and use it to modify the user in any way?  And do you by chance modify the parameters in that method?  Or do you modify the $self->{user_id} object in that method?

In any case, the error that you are getting is because $c->param('user') is returning the empty list.  That should not be possible if the code in ProblemSets.pm is reached.  When authentication is successful the "user" parameter is set to $self->{user_id} which is found during the authentication process, and authentication can't possibly succeed unless that user_id is found.  The code in ProblemSets.pm is not executed unless authentication is successful.