From f363c1c1025ed1952c8ab613e1f9c9ec3e286cd7 Mon Sep 17 00:00:00 2001 From: David Cook Date: Wed, 26 May 2021 08:21:05 +0000 Subject: [PATCH] Bug 24539: Add hooks to allow pluggable authentication modules This patch adds the ability to specify an authentication module to C4::Auth::checkauth(). That module then needs to implement at the very least a do_login() method and optionally do_logout() and get_data() methods if they're needed for that authentication style. --- C4/Auth.pm | 35 ++++++++++++++++++++++++++++++++++- Koha/AuthN/Plugin.pm | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 Koha/AuthN/Plugin.pm diff --git a/C4/Auth.pm b/C4/Auth.pm index f281def2ce..8d4d61b49d 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -48,6 +48,7 @@ use Encode qw( encode is_utf8); use C4::Auth_with_shibboleth; use Net::CIDR; use C4::Log qw/logaction/; +use Koha::AuthN::Plugin; # use utf8; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout); @@ -817,6 +818,11 @@ sub checkauth { my $type = shift; my $emailaddress = shift; my $template_name = shift; + + my $extensions = shift // {}; + + my $auth_plugin = $extensions->{auth_plugin}; + $type = 'opac' unless $type; unless ( C4::Context->preference("OpacPublic") ) { @@ -904,6 +910,7 @@ sub checkauth { if ( ( $query->param('koha_login_context') && ( $q_userid ne $s_userid ) ) || ( $cas && $query->param('ticket') && !C4::Context->userenv->{'id'} ) || ( $shib && $shib_login && !$logout && !C4::Context->userenv->{'id'} ) + || ( $auth_plugin && ! $logout ) ) { #if a user enters an id ne to the id in the current session, we need to log them in... @@ -917,6 +924,10 @@ sub checkauth { $userid = undef; } elsif ($logout) { + #NOTE: Get authentication plugin if we logged in using one + $auth_plugin = Koha::AuthN::Plugin->get_from_session({ + session => $session, + }); # voluntary logout the user # check wether the user was using their shibboleth session or a local one @@ -929,6 +940,14 @@ sub checkauth { $sessionID = undef; $userid = undef; + #NOTE: Logout using authentication plugin + if ( $auth_plugin && $auth_plugin->can('do_logout') ){ + $auth_plugin->do_logout({ + controller => $query, + type => $type, + }); + } + if ($cas and $caslogout) { logout_cas($query, $type); } @@ -1010,6 +1029,7 @@ sub checkauth { } if ( ( $cas && $query->param('ticket') ) || $q_userid + || $auth_plugin || ( $shib && $shib_login ) || $pki_field ne 'None' || $emailaddress ) @@ -1038,7 +1058,14 @@ sub checkauth { $userid = $retuserid; $info{'invalidCasLogin'} = 1 unless ($return); } - + elsif ( $auth_plugin ){ + ($return,$userid) = $auth_plugin->do_login({ + controller => $query, + cookie => $cookie, + session => $session, + info => \%info, + }); + } elsif ( $emailaddress ) { my $value = $emailaddress; @@ -1221,6 +1248,12 @@ sub checkauth { $branchname = $branches->{$br}->{'branchname'}; } } + if ($auth_plugin){ + Koha::AuthN::Plugin->set_login_session({ + auth_plugin => $auth_plugin, + session => $session, + }); + } $session->param( 'number', $borrowernumber ); $session->param( 'id', $userid ); $session->param( 'cardnumber', $cardnumber ); diff --git a/Koha/AuthN/Plugin.pm b/Koha/AuthN/Plugin.pm new file mode 100644 index 0000000000..f0665c4427 --- /dev/null +++ b/Koha/AuthN/Plugin.pm @@ -0,0 +1,49 @@ +package Koha::AuthN::Plugin; + +use Modern::Perl; +use Module::Load::Conditional qw(can_load); + +sub get_from_session { + my ($class,$args) = @); + my $auth_plugin; + my $session = $args->{session}; + if ($session){ + my $auth_plugin_module = $session->param("auth_plugin_module"); + if ( $auth_plugin_module ){ + eval { + if ( can_load( modules => { $auth_plugin_module => undef } ) ){ + my $auth_plugin_data = $session->param("auth_plugin_data"); + $auth_plugin = $auth_plugin_module->new({ + data => $auth_plugin_data, + }); + } + }; + if ($@){ + warn $@; + } + + } + + } + return $auth_plugin; +} + +sub set_login_session { + my ($class,$args) = @_; + my $rv; + my $auth_plugin = $args->{auth_plugin}; + my $session = $args->{session}; + if ( $session && $auth_plugin){ + $session->param( 'auth_plugin_module', ref $auth_plugin ); + if ( $auth_plugin->can('get_data') ){ + my $auth_plugin_data = $auth_plugin->get_data(); + if ($auth_plugin_data){ + $session->param( 'auth_plugin_data', $auth_plugin_data ); + } + } + $rv = 1; + } + return $rv; +} + +1; -- 2.11.0