1 package Koha::REST::V1::TwoFactorAuth;
3 # This file is part of Koha.
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.
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.
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>.
20 use Mojo::Base 'Mojolicious::Controller';
23 use C4::Letters qw( GetPreparedLetter );
27 Koha::REST::V1::TwoFactorAuth
35 Will send an email with the OTP token needed to complete the second authentication step.
42 my $c = shift->openapi->valid_input or return;
44 my $patron = Koha::Patrons->find( $c->stash('koha.user')->borrowernumber );
48 my $code = Koha::Auth::TwoFactorAuth->new({patron => $patron})->code;
49 my $letter = C4::Letters::GetPreparedLetter(
51 letter_code => '2FA_OTP_TOKEN',
52 branchcode => $patron->branchcode,
53 substitute => { otp_token => $code },
55 borrowers => $patron->unblessed,
58 my $message_id = C4::Letters::EnqueueLetter(
61 borrowernumber => $patron->borrowernumber,
62 message_transport_type => 'email'
65 C4::Letters::SendQueuedMessages({message_id => $message_id});
67 my $message = C4::Letters::GetMessage($message_id);
69 if ( $message->{status} eq 'sent' ) {
70 return $c->render(status => 200, openapi => {});
71 } elsif ( $message->{status} eq 'failed' ) {
72 return $c->render(status => 400, openapi => { error => 'email_not_sent'});
76 $c->unhandled_exception($_);
83 Ask for a registration secret. It will return a QR code image and a secret32.
85 The secret must be sent back to the server with the pin code for the verification step.
91 my $c = shift->openapi->valid_input or return;
93 my $patron = Koha::Patrons->find( $c->stash('koha.user')->borrowernumber );
96 my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
97 my $auth = Koha::Auth::TwoFactorAuth->new(
98 { patron => $patron, secret => $secret } );
101 issuer => $auth->issuer,
102 key_id => $auth->key_id,
103 qr_code => $auth->qr_code,
104 secret32 => $auth->secret32,
106 # IMPORTANT: get secret32 after qr_code call !
110 return $c->render(status => 201, openapi => $response);
113 $c->unhandled_exception($_);
120 Verify the registration, get the pin code and the secret retrieved from the registration.
122 The 2FA_ENABLE notice will be generated if the pin code is correct, and the patron will have their two-factor authentication setup completed.
128 my $c = shift->openapi->valid_input or return;
130 my $patron = Koha::Patrons->find( $c->stash('koha.user')->borrowernumber );
134 my $pin_code = $c->validation->param('pin_code');
135 my $secret32 = $c->validation->param('secret32');
137 my $auth = Koha::Auth::TwoFactorAuth->new(
138 { patron => $patron, secret32 => $secret32 } );
140 my $verified = $auth->verify(
144 undef, # timestamp (defaults to now)
145 30, # interval (default 30)
151 openapi => { error => "Invalid pin" }
155 # FIXME Generate a (new?) secret
156 $patron->encode_secret($secret32);
157 $patron->auth_method('two-factor')->store;
158 if ( $patron->notice_email_address ) {
159 $patron->queue_notice(
163 letter_code => '2FA_ENABLE',
164 branchcode => $patron->branchcode,
165 lang => $patron->lang,
167 branches => $patron->branchcode,
168 borrowers => $patron->id
171 message_transports => ['email'],
176 return $c->render(status => 204, openapi => {});
179 $c->unhandled_exception($_);