From 936520dc8f22dc0945ffb9ec88d1e5db29331a7c Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Fri, 18 Apr 2025 17:05:21 -0500 Subject: [PATCH] Reset the cookie session before Mojolicious saves it. Currently the session parameters are set at the beginning of each request. However, if another request occurs for the same process before the first request completes, then the session for the first request gets saved with the parameters of the second request. This is because there is only one Mojoicious session setup for the entire app and the session parameters are global for the process. To fix this the session parameters need to be set again at the end of the request just before the session is saved. This is only an issue if there are multiple clients per worker process. Of course that is not the case at this point, but hopefully will be some day. --- lib/WeBWorK/Authen.pm | 4 ++++ lib/WeBWorK/Controller.pm | 33 +++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/WeBWorK/Authen.pm b/lib/WeBWorK/Authen.pm index 626eff938c..db565f21f0 100644 --- a/lib/WeBWorK/Authen.pm +++ b/lib/WeBWorK/Authen.pm @@ -844,6 +844,10 @@ sub store_session { } } + # The session parameters need to be set again, because another request may have occured during this + # request in which case the session parameters for the app will now be set for that request. + $self->{c}->setSessionParams; + return; } diff --git a/lib/WeBWorK/Controller.pm b/lib/WeBWorK/Controller.pm index 237cf67880..8a1d1e3a68 100644 --- a/lib/WeBWorK/Controller.pm +++ b/lib/WeBWorK/Controller.pm @@ -45,6 +45,24 @@ sub param ($c, @opts) { return wantarray ? @{ $c->{paramcache}{$name} } : $c->{paramcache}{$name}[0]; } +sub setSessionParams ($c) { + $c->app->sessions->cookie_name( + $c->stash('courseID') ? 'WeBWorKCourseSession.' . $c->stash('courseID') : 'WeBWorKGeneralSession'); + + # If the hostname is 'localhost' or '127.0.0.1', then the cookie domain must be omitted. + my $hostname = $c->req->url->to_abs->host; + $c->app->sessions->cookie_domain($hostname) if $hostname ne 'localhost' && $hostname ne '127.0.0.1'; + + $c->app->sessions->cookie_path($c->ce->{webworkURLRoot}); + $c->app->sessions->secure($c->ce->{CookieSecure}); + + # If this is a session for LTI content selection, then always use SameSite None. Otherwise cookies will not be + # sent since this is in an iframe embedded in the LMS. + $c->app->sessions->samesite($c->stash->{isContentSelection} ? 'None' : $c->ce->{CookieSameSite}); + + return; +} + # Override the Mojolicious::Controller session method to set the cookie parameters # from the course environment the first time it is called. sub session ($c, @args) { @@ -53,20 +71,7 @@ sub session ($c, @args) { # Initialize the cookie session the first time this is called. unless ($c->stash->{'webwork2.cookie_session_initialized'}) { $c->stash->{'webwork2.cookie_session_initialized'} = 1; - - $c->app->sessions->cookie_name( - $c->stash('courseID') ? 'WeBWorKCourseSession.' . $c->stash('courseID') : 'WeBWorKGeneralSession'); - - # If the hostname is 'localhost' or '127.0.0.1', then the cookie domain must be omitted. - my $hostname = $c->req->url->to_abs->host; - $c->app->sessions->cookie_domain($hostname) if $hostname ne 'localhost' && $hostname ne '127.0.0.1'; - - $c->app->sessions->cookie_path($c->ce->{webworkURLRoot}); - $c->app->sessions->secure($c->ce->{CookieSecure}); - - # If this is a session for LTI content selection, then always use SameSite None. Otherwise cookies will not be - # sent since this is in an iframe embedded in the LMS. - $c->app->sessions->samesite($c->stash->{isContentSelection} ? 'None' : $c->ce->{CookieSameSite}); + $c->setSessionParams; } return $c->SUPER::session(@args);