From 276b33a782d061cd10b43b79e425add258e6a539 Mon Sep 17 00:00:00 2001
From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Date: Thu, 13 Jan 2022 14:27:36 +0000
Subject: [PATCH] Bug 29873: Create QR code

Instead of using deprecated Google Charts API, and exposing our
secret in a GET parameter, we generate QR data ourselves.

Test plan:
[1] Enable two factor authentication in the prefs.
[2] Login in staff. Go to account. Select Manage 2FA.
[3] Verify that QR code is displayed.
[4] Register the QR in your authenticator app and test 2FA
    by logging in again.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Tested with Google Authenticator and FreeOTP.

Bug 29873: (follow-up) Rename qr_dataurl

As requested by a QA team member.
We're moving to qr_code as method name. This is the same name as
the method in the underlying base class.
Apart from one sed statement, changing to self->SUPER on one line.

Test plan:
Can you still register, logout and login?

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>

Bug 29873: (follow-up) Switch to GD

We do not need a new module, we could use GD instead.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
---
 Koha/Auth/TwoFactorAuth.pm                    | 22 +++++++++++++++++++
 .../en/modules/members/two_factor_auth.tt     |  2 +-
 members/two_factor_auth.pl                    |  6 ++---
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/Koha/Auth/TwoFactorAuth.pm b/Koha/Auth/TwoFactorAuth.pm
index 81ddf06a3d..e2cff4487f 100644
--- a/Koha/Auth/TwoFactorAuth.pm
+++ b/Koha/Auth/TwoFactorAuth.pm
@@ -17,6 +17,8 @@ package Koha::Auth::TwoFactorAuth;
 
 use Modern::Perl;
 use Auth::GoogleAuth;
+use GD::Barcode;
+use MIME::Base64 qw( encode_base64 );
 
 use base qw( Auth::GoogleAuth );
 
@@ -66,4 +68,24 @@ sub new {
     );
 }
 
+=head3 qr_code
+
+    my $image_src = $auth->qr_code;
+
+    Replacement for (unsafer) Auth::GoogleAuth::qr_code.
+    Returns the data URL to fill the src attribute of the
+    image tag on the registration form.
+
+=cut
+
+sub qr_code {
+    my ( $self ) = @_;
+
+    my $otpauth = $self->SUPER::qr_code( undef, undef, undef, 1);
+        # no need to pass secret, key and issuer again
+    my $qrcode = GD::Barcode->new( 'QRcode', $otpauth, { Ecc => 'M', Version => 8, ModuleSize => 4 } );
+    my $data = $qrcode->plot->png;
+    return "data:image/png;base64,". encode_base64( $data, q{} ); # does not contain newlines
+}
+
 1;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt
index cddac9f1b4..feb86b9586 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt
@@ -55,7 +55,7 @@
                             <ol>
                                 <li>
                                     <label for="qr_code">QR code: </label>
-                                    <img id="qr_code" src="[% qr_code_url | $raw %]" />
+                                    <img id="qr_code" src="[% qr_code | $raw %]" />
                                 </li>
                                 <li>
                                     <label for="pin_code">Pin code: </label>
diff --git a/members/two_factor_auth.pl b/members/two_factor_auth.pl
index d5157dfd8a..b874a6f97d 100755
--- a/members/two_factor_auth.pl
+++ b/members/two_factor_auth.pl
@@ -86,14 +86,12 @@ if ( $op eq 'enable-2FA' ) {
     my $auth = Koha::Auth::TwoFactorAuth->new(
         { patron => $logged_in_user, secret => $secret } );
 
-    my $qr_code_url =
-      $auth->qr_code( undef, $auth->key_id, $auth->issuer ); # no need to pass secret32
-
     $template->param(
         issuer      => $auth->issuer,
         key_id      => $auth->key_id,
+        qr_code  => $auth->qr_code,
         secret32    => $auth->secret32,
-        qr_code_url => $qr_code_url,
+            # IMPORTANT: get secret32 after qr_code call !
     );
     $auth->clear;
     $op = 'register';
-- 
2.20.1