View | Details | Raw Unified | Return to bug 28998
Collapse All | Expand All

(-)a/C4/Auth.pm (-1 / +4 lines)
Lines 33-38 use Koha::Logger; Link Here
33
use Koha::Caches;
33
use Koha::Caches;
34
use Koha::AuthUtils qw( get_script_name hash_password );
34
use Koha::AuthUtils qw( get_script_name hash_password );
35
use Koha::Auth::TwoFactorAuth;
35
use Koha::Auth::TwoFactorAuth;
36
use Koha::Encryption;
36
use Koha::Checkouts;
37
use Koha::Checkouts;
37
use Koha::DateUtils qw( dt_from_string );
38
use Koha::DateUtils qw( dt_from_string );
38
use Koha::Library::Groups;
39
use Koha::Library::Groups;
Lines 890-896 sub checkauth { Link Here
890
            && ( my $otp_token = $query->param('otp_token') ) )
891
            && ( my $otp_token = $query->param('otp_token') ) )
891
        {
892
        {
892
            my $patron    = Koha::Patrons->find( { userid => $userid } );
893
            my $patron    = Koha::Patrons->find( { userid => $userid } );
893
            my $auth      = Koha::Auth::TwoFactorAuth::get_auth( { patron => $patron } );
894
            my $secret32 = Koha::Encryption->new->decrypt_hex($patron->secret);
895
            my $auth = Koha::Auth::TwoFactorAuth->new(
896
                { patron => $patron, secret32 => $secret32 } );
894
            my $verified = $auth->verify($otp_token);
897
            my $verified = $auth->verify($otp_token);
895
            $auth->clear;
898
            $auth->clear;
896
            if ( $verified ) {
899
            if ( $verified ) {
(-)a/Koha/Auth/TwoFactorAuth.pm (-7 / +4 lines)
Lines 38-58 It's based on Auth::GoogleAuth Link Here
38
38
39
=cut
39
=cut
40
40
41
sub get_auth {
41
sub new {
42
    my ($params) = @_;
42
    my ($class, $params) = @_;
43
43
    my $patron   = $params->{patron};
44
    my $patron   = $params->{patron};
44
    my $secret   = $params->{secret};
45
    my $secret   = $params->{secret};
45
    my $secret32 = $params->{secret32};
46
    my $secret32 = $params->{secret32};
46
47
47
    if (!$secret && !$secret32){
48
        $secret32 = $patron->secret;
49
    }
50
51
    my $issuer = $patron->library->branchname;
48
    my $issuer = $patron->library->branchname;
52
    my $key_id = sprintf "%s_%s",
49
    my $key_id = sprintf "%s_%s",
53
      $issuer, ( $patron->email || $patron->userid );
50
      $issuer, ( $patron->email || $patron->userid );
54
51
55
    return Auth::GoogleAuth->new(
52
    return $class->SUPER::new(
56
        {
53
        {
57
            ( $secret   ? ( secret   => $secret )   : () ),
54
            ( $secret   ? ( secret   => $secret )   : () ),
58
            ( $secret32 ? ( secret32 => $secret32 ) : () ),
55
            ( $secret32 ? ( secret32 => $secret32 ) : () ),
(-)a/Koha/Encryption.pm (+47 lines)
Line 0 Link Here
1
package Koha::Encryption;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use base qw( Crypt::CBC );
21
22
=head1 NAME
23
24
Koha::Encryption - Koha class to encrypt or decrypt strings
25
26
=head1 SYNOPSIS
27
28
use Koha::Encryption;
29
my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
30
my $crypt = Koha::Encryption->new;
31
my $encrypted = $crypt->encrypt_hex($secret);
32
my $decrypted = crypt->decrypt_hex($encrypted);
33
34
It's based on Crypt::CBC
35
36
=cut
37
38
sub new {
39
    my ( $class ) = @_;
40
    my $key = C4::Context->config('encryption_key');
41
    return $class->SUPER::new(
42
        -key    => $key,
43
        -cipher => 'Cipher::AES'
44
    );
45
}
46
47
1;
(-)a/members/two_factor_auth.pl (-3 / +4 lines)
Lines 48-54 my $op = $cgi->param('op') // ''; Link Here
48
if ( $op eq 'register-2FA' ) {
48
if ( $op eq 'register-2FA' ) {
49
    my $pin_code = $cgi->param('pin_code');
49
    my $pin_code = $cgi->param('pin_code');
50
    my $secret32 = $cgi->param('secret32');
50
    my $secret32 = $cgi->param('secret32');
51
    my $auth     = Koha::Auth::TwoFactorAuth::get_auth(
51
    my $auth     = Koha::Auth::TwoFactorAuth->new(
52
        { patron => $logged_in_user, secret32 => $secret32 } );
52
        { patron => $logged_in_user, secret32 => $secret32 } );
53
53
54
    my $verified = $auth->verify(
54
    my $verified = $auth->verify(
Lines 60-66 if ( $op eq 'register-2FA' ) { Link Here
60
    );
60
    );
61
61
62
    if ($verified) {
62
    if ($verified) {
63
        $logged_in_user->secret($secret32);
63
        my $encrypted_secret = Koha::Encryption->new->encrypt_hex($secret32);
64
        $logged_in_user->secret($encrypted_secret);
64
        $op = 'registered';
65
        $op = 'registered';
65
66
66
        # FIXME Generate a (new?) secret
67
        # FIXME Generate a (new?) secret
Lines 75-81 if ( $op eq 'register-2FA' ) { Link Here
75
if ( $op eq 'enable-2FA' ) {
76
if ( $op eq 'enable-2FA' ) {
76
77
77
    my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
78
    my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
78
    my $auth = Koha::Auth::TwoFactorAuth::get_auth(
79
    my $auth = Koha::Auth::TwoFactorAuth->new(
79
        { patron => $logged_in_user, secret => $secret } );
80
        { patron => $logged_in_user, secret => $secret } );
80
81
81
    my $secret32 = $auth->generate_secret32;
82
    my $secret32 = $auth->generate_secret32;
(-)a/t/db_dependent/Koha/Encryption.t (+17 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
use Test::More tests => 1;
4
use Koha::Encryption;
5
use t::lib::Mocks;
6
7
t::lib::Mocks::mock_config('encryption_key', 'my secret passphrase');
8
9
my $string = 'a string to encrypt';
10
11
my $crypt = Koha::Encryption->new();
12
my $encrypted_string = $crypt->encrypt($string);
13
is( $crypt->decrypt_hex($encrypted_string), $string );
14
15
use Koha::AuthUtils;
16
my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
17
my $encrypted_secret = Koha::Encryption->new->encrypt_hex($secret);
(-)a/t/db_dependent/selenium/authentication_2fa.t (-4 / +7 lines)
Lines 21-26 use Test::More tests => 2; Link Here
21
use C4::Context;
21
use C4::Context;
22
use Koha::AuthUtils;
22
use Koha::AuthUtils;
23
use Koha::Auth::TwoFactorAuth;
23
use Koha::Auth::TwoFactorAuth;
24
use Koha::Encryption;
24
use t::lib::Mocks;
25
use t::lib::Mocks;
25
use t::lib::Selenium;
26
use t::lib::Selenium;
26
use t::lib::TestBuilder;
27
use t::lib::TestBuilder;
Lines 80-86 SKIP: { Link Here
80
        $s->submit_form;
81
        $s->submit_form;
81
        is( $driver->find_element('//div[@class="two-factor-status"]')->get_text(), 'Status: Enabled', '2FA is enabled' );
82
        is( $driver->find_element('//div[@class="two-factor-status"]')->get_text(), 'Status: Enabled', '2FA is enabled' );
82
        $patron = $patron->get_from_storage;
83
        $patron = $patron->get_from_storage;
83
        is( $patron->secret, $secret32, 'secret is set in DB' );
84
        is( Koha::Encryption->new->decrypt_hex($patron->secret), $secret32, 'encrypted secret is set in DB' );
84
85
85
    };
86
    };
86
87
Lines 89-94 SKIP: { Link Here
89
90
90
        my $mainpage = $s->base_url . q|mainpage.pl|;
91
        my $mainpage = $s->base_url . q|mainpage.pl|;
91
92
93
        my $secret32 = Koha::Encryption->new->decrypt_hex($patron->secret);
92
        { # ok first try
94
        { # ok first try
93
            $driver->get($mainpage . q|?logout.x=1|);
95
            $driver->get($mainpage . q|?logout.x=1|);
94
            $driver->get($s->base_url . q|circ/circulation.pl?borrowernumber=|.$patron->borrowernumber);
96
            $driver->get($s->base_url . q|circ/circulation.pl?borrowernumber=|.$patron->borrowernumber);
Lines 98-104 SKIP: { Link Here
98
            like( $driver->get_title, qr(Two-factor authentication), 'Must be on the second auth screen' );
100
            like( $driver->get_title, qr(Two-factor authentication), 'Must be on the second auth screen' );
99
            is( login_error($s), undef );
101
            is( login_error($s), undef );
100
102
101
            my $auth = Koha::Auth::TwoFactorAuth->new({patron => $patron});
103
            my $auth = Koha::Auth::TwoFactorAuth->new(
104
                { patron => $patron, secret32 => $secret32 } );
102
            my $code = $auth->code();
105
            my $code = $auth->code();
103
            $auth->clear;
106
            $auth->clear;
104
            $driver->find_element('//form[@id="loginform"]//input[@id="otp_token"]')->send_keys($code);
107
            $driver->find_element('//form[@id="loginform"]//input[@id="otp_token"]')->send_keys($code);
Lines 139-145 SKIP: { Link Here
139
            $driver->find_element('//input[@type="submit"]')->click;
142
            $driver->find_element('//input[@type="submit"]')->click;
140
            ok($driver->find_element('//div[@class="dialog error"][contains(text(), "Invalid two-factor code")]'));
143
            ok($driver->find_element('//div[@class="dialog error"][contains(text(), "Invalid two-factor code")]'));
141
144
142
            my $auth = Koha::Auth::TwoFactorAuth->new({patron => $patron});
145
            my $auth = Koha::Auth::TwoFactorAuth->new(
146
                { patron => $patron, secret32 => $secret32 } );
143
            my $code = $auth->code();
147
            my $code = $auth->code();
144
            $auth->clear;
148
            $auth->clear;
145
            $driver->find_element('//form[@id="loginform"]//input[@id="otp_token"]')->send_keys($code);
149
            $driver->find_element('//form[@id="loginform"]//input[@id="otp_token"]')->send_keys($code);
146
- 

Return to bug 28998