Bug 30588: Add the option to require 2FA setup on first staff login
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / auth.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE Koha %]
4 [% USE Branches %]
5 [% USE Desks %]
6 [% USE Categories %]
7 [% USE Registers %]
8 [% SET footerjs = 1 %]
9 [% INCLUDE 'doc-head-open.inc' %]
10 <title>
11     [% IF TwoFA_prompt %]Two-factor authentication[% END %]
12     [% IF ( loginprompt ) %]Log in to Koha[% END %]
13     [% IF too_many_login_attempts %]This account has been locked.
14     [% ELSIF invalid_username_or_password %]Invalid username or password[% END %]
15     [% IF ( different_ip ) %]IP address change[% END %]
16     [% IF ( timed_out ) %]Session timed out[% END %]
17     [% IF ( nopermission ) %]Access denied[% END %] &rsaquo; Koha
18 </title>
19 [% INCLUDE 'doc-head-close.inc' %]
20 [% PROCESS 'auth-two-factor.inc' %]
21 </head>
22 <body id="main_auth" class="main_main-auth">
23
24 <div class="main container-fluid">
25
26 <div id="login">
27 <h1><a href="http://koha-community.org">Koha</a></h1>
28 [% IF (Koha.Preference('StaffLoginInstructions')) %]<div id="login_instructions">[% Koha.Preference('StaffLoginInstructions') | $raw %]</div>[% END %]
29 [% IF ( nopermission ) %]
30 <div id="login_error">
31     <strong>Error:</strong>
32     You do not have permission to access this page.
33 </div>
34 <p><strong>Log in as a different user</strong></p></h2>
35 [% END %]
36
37 [% IF ( timed_out ) %]
38 <div id="login_error"><strong>Error: </strong>Session timed out.<br /> Please log in again</div>
39 [% END %]
40
41 [% IF ( different_ip ) %]
42 <div id="login_error"><strong>Error: </strong>IP address has changed. Please log in again </div>
43 [% END %]
44
45 [% IF ( wrongip ) %]
46 <div id="login_error"><strong>Error: </strong>Autolocation is switched on and you are logging in with an IP address that doesn't match your library. </div>
47 [% END %]
48
49 [% IF too_many_login_attempts %]
50     <div id="login_error"><strong>Error: </strong>This account has been locked!</div>
51     [% IF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %]
52         <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>.
53     [% END %]
54 [% ELSIF password_has_expired %]
55     <div id="login_error"><strong>Error: </strong>Your password has expired!</div>
56     [% IF Koha.Preference('EnableExpiredPasswordReset') && Koha.Preference('OpacBaseURL') %]
57         <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-reset-password.pl">You must reset your password</a>.
58     [% ELSIF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %]
59         <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>.
60     [% ELSE %]
61         <p>You must contact the library to reset your password</p>
62     [% END %]
63 [% ELSIF invalid_username_or_password %]
64 <div id="login_error"><strong>Error: </strong>Invalid username or password</div>
65 [% END %]
66
67 [% IF (shibbolethAuthentication) %]
68 <!-- This is what is displayed if shib login has failed -->
69 [% IF (invalidShibLogin ) %]
70 <div id="login_error"><Strong>Error: </strong>Shibboleth login failed</div>
71 [% END %]
72 <p><a href="[% shibbolethLoginUrl | $raw %]">Log in using a Shibboleth account</a>.</p>
73 [% END %]
74
75 [% IF !TwoFA_prompt && !TwoFA_setup && !Koha.Preference('staffShibOnly') %]
76     <!-- login prompt time-->
77     <form action="[% script_name | html %]" method="post" name="loginform" id="loginform">
78         <input type="hidden" name="koha_login_context" value="intranet" />
79     [% FOREACH INPUT IN INPUTS %]
80         <input type="hidden" name="[% INPUT.name | html %]" value="[% INPUT.value | html %]" />
81     [% END %]
82     <p><label for="userid">Username:</label>
83     <input type="text" name="userid" id="userid" class="input focus" value="[% userid | html %]" size="20" tabindex="1" autocomplete="off" />
84     </p>
85     <p><label for="password">Password:</label>
86     <input type="password" name="password" id="password" class="input" value="" size="20" tabindex="2" autocomplete="off" />
87     </p>
88
89     [% UNLESS IndependentBranches %]
90         <p>
91             <label for="branch">Library:</label>
92             <select name="branch" id="branch" class="input" tabindex="3">
93                 <option value="">My library</option>
94                 [% FOREACH l IN Branches.all( unfiltered => 1 ) %]
95                     <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option>
96                  [% END %]
97             </select>
98         </p>
99
100         [% IF Koha.Preference('UseCirculationDesks') && Desks.all %]
101         <p>
102             <label for="desk">Desk:</label>
103             <select name="desk_id" id="desk_id" class="input" tabindex="3">
104                 <option id="nodesk" value="">---</option>
105                     [% FOREACH d IN Desks.all %]
106                     <option class="[% d.branchcode | html %]" value="[% d.desk_id | html %]" disabled >[% d.desk_name | html %]</option>
107                     [% END %]
108             </select>
109         </p>
110         [% END %]
111
112         [% IF Koha.Preference('UseCashRegisters') && Registers.all().size %]
113         <p>
114             <label for="register_id">Cash register:</label>
115             <select name="register_id" id="register_id" class="input" tabindex="4">
116                 <option id="noregister" value="" selected="selected">Library default</option>
117                 [% PROCESS options_for_registers registers => Registers.all() %]
118             </select>
119         </p>
120         [% END %]
121
122     [% END %]
123
124     <!-- <p><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="3" />Remember me</label></p> -->
125
126     <p class="submit"><input id="submit-button" type="submit" value="Log in" tabindex="4" /></p>
127     </form>
128
129     [% IF ( casAuthentication ) %]
130         <h4>Cas login</h4>
131
132         [% IF ( invalidCasLogin ) %]
133         <!-- This is what is displayed if cas login has failed -->
134         <p>Sorry, the CAS login failed.</p>
135         [% END %]
136
137         [% IF ( casServerUrl ) %]
138             <p><a href="[% casServerUrl | $raw %]">If you have a CAS account, please click here to login</a>.<p>
139         [% END %]
140
141         [% IF ( casServersLoop ) %]
142             <p>If you have a CAS account, please choose against which one you would like to authenticate:</p>
143         <ul>
144             [% FOREACH casServer IN casServersLoop %]
145                 <li><a href="[% casServer.value | $raw %]">[% casServer.name | html %]</a></li>
146             [% END %]
147         [% END %]
148     [% END %]
149 [% ELSIF TwoFA_prompt %]
150     <form action="[% script_name | html %]" method="post" name="loginform" id="loginform">
151         <input type="hidden" name="koha_login_context" value="intranet" />
152         [% FOREACH INPUT IN INPUTS %]
153             <input type="hidden" name="[% INPUT.name | html %]" value="[% INPUT.value | html %]" />
154         [% END %]
155         [% IF invalid_otp_token %]
156             <div id="login_error">Invalid two-factor code</div>
157         [% END %]
158
159         <div id="email_error" class="dialog alert" style="display: none;"></div>
160         <div id="email_success" class="dialog message" style="display: none;"></div>
161         <p>
162             <label for="otp_token">Two-factor authentication code:</label>
163             <input type="text" name="otp_token" id="otp_token" class="input focus" value="" size="20" tabindex="1" />
164         </p>
165         <p>
166             <input id="submit-button" type="submit" value="Verify code" />
167             <a class="send_otp" id="send_otp" href="#">Send the code by email</a>
168             <a class="cancel" id="logout" href="/cgi-bin/koha/mainpage.pl?logout.x=1">Cancel</a>
169         </p>
170
171     </form>
172 [% ELSIF TwoFA_setup %]
173     [% PROCESS registration_form %]
174 [% END %]
175
176 [% IF ( nopermission ) %]
177     <p><a id="previous_page" href="javascript:window.history.back()">[Previous page]</a>
178     <a id="mainpage" href="/">[Main page]</a></p>
179 [% END %]
180
181
182 <!--<ul> -->
183 <!--    <li><a href="/cgi-bin/koha/lostpassword.pl" title="Password lost and found">Lost your password?</a></li> -->
184 <!-- </ul> -->
185
186 </div>
187
188 [% MACRO jsinclude BLOCK %]
189     [% Asset.js("js/desk_selection.js") | $raw %]
190     [% Asset.js("js/register_selection.js") | $raw %]
191     <script>
192         $(document).ready( function() {
193             if ( document.location.hash ) {
194                 $( '#loginform' ).append( '<input name="auth_forwarded_hash" type="hidden" value="' + document.location.hash + '"/>' );
195             }
196             // Clear last borrowers, rememberd sql reports, carts, etc.
197             logOut();
198
199             $("#send_otp").on("click", function(e){
200                 e.preventDefault();
201                 [% UNLESS notice_email_address %]
202                     alert("Cannot send the notice, you don't have an email address defined.")
203                 [% ELSE %]
204                 $("#email_success").hide();
205                 $("#email_error").hide();
206                     $.ajax({
207                         url: '/api/v1/auth/otp/token_delivery',
208                         type: 'POST',
209                         success: function(data){
210                             let message = _("The code has been sent by email, please check your inbox.")
211                             $("#email_success").show().html(message);
212                         },
213                         error: function(data){
214                             let error = data.responseJSON && data.responseJSON.error == "email_not_sent"
215                                 ? _("Email not sent, please contact the Koha administrator")
216                                 : _("Something wrong happened, please contact the Koha administrator");
217                             $("#email_error").show().html(error);
218                         }
219                     });
220                 [% END %]
221             });
222
223             if( $("#registration-form").length ) {
224                 $.ajax({
225                     data: {},
226                     type: 'POST',
227                     url: '/api/v1/auth/two-factor/registration',
228                     success: function (data) {
229                         $("#qr_code").attr('src', data.qr_code);
230                         $("#secret32").val(data.secret32);
231                         $("#issuer").html(data.issuer);
232                         $("#key_id").html(data.key_id);
233                         $("#registration-form").show();
234                     },
235                     error: function (data) {
236                         alert(data);
237                     },
238                 });
239             };
240
241             $("#register-2FA").on("click", function(e){
242                 e.preventDefault();
243                 const data = {
244                     secret32: $("#secret32").val(),
245                     pin_code: $("#pin_code").val(),
246                 };
247                 if (!data.pin_code) return;
248
249                 $.ajax({
250                     data: data,
251                     type: 'POST',
252                     url: '/api/v1/auth/two-factor/registration/verification',
253                     success: function (data) {
254                         alert(_("Two-factor authentication correctly configured. You will be redirected to the login screen."));
255                         window.location = "/cgi-bin/koha/mainpage.pl";
256                     },
257                     error: function (data) {
258                         const error = data.responseJSON.error;
259                         if ( error == 'Invalid pin' ) {
260                             $("#errors").html(_("Invalid PIN code")).show();
261                         } else {
262                             alert(error);
263                         }
264                     },
265                 });
266             });
267
268         });
269     </script>
270 [% END %]
271 <!-- the main div is closed in intranet-bottom.inc -->
272 [% INCLUDE 'intranet-bottom.inc' %]