| Lines 20-25
          use C4::Members;
      
      
        Link Here | 
        
          | 20 | use Koha::AuthUtils qw/hash_password/; | 20 | use Koha::AuthUtils qw/hash_password/; | 
        
          | 21 | use Koha::Database; | 21 | use Koha::Database; | 
        
          | 22 | use Koha::Patrons; | 22 | use Koha::Patrons; | 
            
              |  |  | 23 | use Koha::Auth::TwoFactorAuth; | 
        
          | 23 |  | 24 |  | 
        
          | 24 | BEGIN { | 25 | BEGIN { | 
        
          | 25 |     use_ok('C4::Auth', qw( checkauth haspermission track_login_daily checkpw get_template_and_user checkpw_hash )); | 26 |     use_ok('C4::Auth', qw( checkauth haspermission track_login_daily checkpw get_template_and_user checkpw_hash )); | 
  
    | Lines 38-44
          $schema->storage->txn_begin;
      
      
        Link Here | 
        
          | 38 |  | 39 |  | 
        
          | 39 | subtest 'checkauth() tests' => sub { | 40 | subtest 'checkauth() tests' => sub { | 
        
          | 40 |  | 41 |  | 
          
            
              | 41 |     plan tests => 4; | 42 |     plan tests => 5; | 
        
          | 42 |  | 43 |  | 
        
          | 43 |     my $patron = $builder->build_object({ class => 'Koha::Patrons', value => { flags => undef } }); | 44 |     my $patron = $builder->build_object({ class => 'Koha::Patrons', value => { flags => undef } }); | 
        
          | 44 |  | 45 |  | 
  
    | Lines 108-113
          subtest 'checkauth() tests' => sub {
      
      
        Link Here | 
        
          | 108 |         is( $userid, undef, 'If librarian user is used and password with GET, they should not be logged in' ); | 109 |         is( $userid, undef, 'If librarian user is used and password with GET, they should not be logged in' ); | 
        
          | 109 |     }; | 110 |     }; | 
        
          | 110 |  | 111 |  | 
            
              |  |  | 112 |     subtest 'Two-factor authentication' => sub { | 
            
              | 113 |  | 
            
              | 114 |         my $patron = $builder->build_object( | 
            
              | 115 |             { class => 'Koha::Patrons', value => { flags => 1 } } ); | 
            
              | 116 |         my $password = 'password'; | 
            
              | 117 |         $patron->set_password( { password => $password } ); | 
            
              | 118 |         $cgi = Test::MockObject->new(); | 
            
              | 119 |  | 
            
              | 120 |         my $otp_token; | 
            
              | 121 |         our ( $logout, $sessionID, $verified ); | 
            
              | 122 |         $cgi->mock( | 
            
              | 123 |             'param', | 
            
              | 124 |             sub { | 
            
              | 125 |                 my ( $self, $param ) = @_; | 
            
              | 126 |                 if    ( $param eq 'userid' )    { return $patron->userid; } | 
            
              | 127 |                 elsif ( $param eq 'password' )  { return $password; } | 
            
              | 128 |                 elsif ( $param eq 'otp_token' ) { return $otp_token; } | 
            
              | 129 |                 elsif ( $param eq 'logout.x' )  { return $logout; } | 
            
              | 130 |                 else                            { return; } | 
            
              | 131 |             } | 
            
              | 132 |         ); | 
            
              | 133 |         $cgi->mock( 'request_method', sub { return 'POST' } ); | 
            
              | 134 |         $cgi->mock( 'cookie', sub { return $sessionID } ); | 
            
              | 135 |  | 
            
              | 136 |         my $two_factor_auth = Test::MockModule->new( 'Koha::Auth::TwoFactorAuth' ); | 
            
              | 137 |         $two_factor_auth->mock( 'verify', sub {$verified} ); | 
            
              | 138 |  | 
            
              | 139 |         my ( $userid, $cookie, $flags ); | 
            
              | 140 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 141 |  | 
            
              | 142 |         sub logout { | 
            
              | 143 |             my $cgi = shift; | 
            
              | 144 |             $logout = 1; | 
            
              | 145 |             undef $sessionID; | 
            
              | 146 |             C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 147 |             $logout = 0; | 
            
              | 148 |         } | 
            
              | 149 |  | 
            
              | 150 |         t::lib::Mocks::mock_preference( 'TwoFactorAuthentication', 0 ); | 
            
              | 151 |         $patron->auth_method('password')->store; | 
            
              | 152 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 153 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 154 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), undef, 'Second auth not required' ); | 
            
              | 155 |         logout($cgi); | 
            
              | 156 |  | 
            
              | 157 |         $patron->auth_method('two-factor')->store; | 
            
              | 158 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 159 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 160 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), undef, 'Second auth not required' ); | 
            
              | 161 |         logout($cgi); | 
            
              | 162 |  | 
            
              | 163 |         t::lib::Mocks::mock_preference( 'TwoFactorAuthentication', 1 ); | 
            
              | 164 |         $patron->auth_method('password')->store; | 
            
              | 165 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 166 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 167 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), undef, 'Second auth not required' ); | 
            
              | 168 |         logout($cgi); | 
            
              | 169 |  | 
            
              | 170 |         $patron->auth_method('two-factor')->store; | 
            
              | 171 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 172 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 173 |         my $session = C4::Auth::get_session($sessionID); | 
            
              | 174 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), 1, 'Second auth required' ); | 
            
              | 175 |  | 
            
              | 176 |         # Wrong OTP token | 
            
              | 177 |         $otp_token = "wrong"; | 
            
              | 178 |         $verified = 0; | 
            
              | 179 |         $patron->auth_method('two-factor')->store; | 
            
              | 180 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 181 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 182 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), 1, 'Second auth still required after wrong OTP token' ); | 
            
              | 183 |  | 
            
              | 184 |         $otp_token = "good"; | 
            
              | 185 |         $verified = 1; | 
            
              | 186 |         ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth( $cgi, 'authrequired', undef, 'intranet' ); | 
            
              | 187 |         is( $userid, $patron->userid, 'Succesful login' ); | 
            
              | 188 |         is( C4::Auth::get_session($sessionID)->param('waiting-for-2FA'), 0, 'Second auth no longer required if OTP token has been verified' ); | 
            
              | 189 |  | 
            
              | 190 |     }; | 
            
              | 191 |  | 
        
          | 111 |     C4::Context->_new_userenv; # For next tests | 192 |     C4::Context->_new_userenv; # For next tests | 
        
          | 112 |  | 193 |  | 
        
          | 113 | }; | 194 | }; | 
            
              | 114 | -  |  |  |