<!DOCTYPE html> <html> <head> {% for src in js %} <script type="text/javascript" src="{{ src }}"></script> {% endfor %} {% for src in css %} <link type="text/css" rel="stylesheet" href="{{ src }}"> {% endfor %} <script type="text/javascript" src="{{ url_for( 'send_app_files', path = 'webauthn.js' ) }}"></script> <script type="text/javascript" src="{{ url_for( 'send_app_files', path = 'functions.js' ) }}"></script> <link type="text/css" rel="stylesheet" href="{{ url_for( 'send_app_files', path = 'app.css' ) }}"> <script type="text/javascript"> baseurl = "{{ baseurl }}"; </script> </head> <body> <div class="icnml_central"> <h1 style="margin-bottom: 0px">ICNML</h1> <h4 style="margin-top: 0px">International Close Non-Matches Library</h4> <div class="ui-widget-header ui-corner-top icnml_box_top">Please enter your login information</div> <div id="icnml_homepage_form" class="ui-widget-content ui-corner-bottom icnml_box_content"> <div id="icnml_box_fields" class="icnml_box_fields"> <div style="text-align: right;"> <label for="username">Username</label> </div> <div> <input id="username" name="username" type="text" /> </div> <div style="text-align: right;"> <label for="password">Password</label> </div> <div> <input id="password" name="password" type="password" /> </div> </div> <div id="icnml_login_error" class="icnml_box_error"></div> <div id="warning" class="icnml_box_warning"></div> <div class="icnml_button"> <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" id="login_button" role="button" aria-disabled="false"> <span class="ui-button-text">Login</span> </a> </div> <div class="icnml_shybox" id="password_reset"> <a href="{{ url_for( 'password_reset' ) }}">Forgotten password ?</a> <br> <a href="{{ url_for( 'new_user' ) }}">Sign-in</a> </div> </div> </div> </body> <script type="text/javascript"> var login_action_password = async function() { $( '#icnml_login_error' ).html( '' ); $( '#login_button > span' ).text( "Please wait..." ); var username = $( '#username' ).val(); var password = $( '#password' ).val(); var password_local = $( '#password' ).val(); password = await generateKey( password, "icnml_" + username, 20000 ); password = password.substring( 0, 128 ); password = "pbkdf2$sha512$icnml_" + username + "$20000$" + password; password_local = await generateKey( password_local, "icnml_" + username + "_localpassword", 50000 ); password_local = password_local.substring( 0, 128 ); var e = encrypt( password_local, "{{ session_security_key }}" ); sessionStorage.setItem( "session_key", e ); $.ajax( { url: '{{ url_for( 'do_login' ) }}', dataType: 'json', method: 'POST', data: { username: username, password: password }, success: function( data ) { if( ! data.error ) { if( data.logged ) { if( data.redirect ) location.href = data.redirect; else location.href = "{{ url_for( 'home' ) }}"; } else if( data.next_step === 'totp' ) { build_totp_form(); } else if( data.next_step === 'securitykey' ) { build_securitykey_form(); } else { if( typeof data.message !== 'undefined' ) var message = data.message; else var message = 'Invalid username/password'; $( '#icnml_login_error' ).text( message ); } $( '#login_button > span' ).text( "Login" ); } } } ); } var login_action_totp = function() { $( '#icnml_login_error' ).html( '' ); $( '#login_button > span' ).text( "Please wait..." ); $.ajax( { url: '{{ url_for( 'do_login' ) }}', dataType: 'json', method: 'POST', data: { totp: $( '#totp' ).val() }, success: function( data ) { if( ! data.error ) { if( data.logged ) { location.href = "{{ url_for( 'home' ) }}"; } else if( data.next_step === 'securitykey' ) { build_securitykey_form(); } else { if( typeof data.message !== 'undefined' ) $( '#icnml_login_error' ).text( data.message ); } } } } ); } var build_totp_form = function() { $( '#icnml_login_error' ).html( '' ); $( '#icnml_box_fields' ).html( '' ); $( '#icnml_box_fields' ) .append( $( '<div />' ) .text( "TOTP" ) .css( "text-align", "right" ) ) .append( $( '<div />' ).append( $( '<input />' ) .attr( "id", "totp" ) .attr( "name", "totp" ) .css( "width", "100%" ) .on( 'keyup', function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_totp(); } } ) ) ); $( '#totp' ).focus(); } var build_securitykey_form = function() { $( '#icnml_login_error' ).html( '' ); $( '#icnml_box_fields' ).html( '' ); $( '#icnml_box_fields' ) .removeClass( 'icnml_box_fields' ) .addClass( 'icnml_auto' ); $( '#login_button' ).remove(); $( '#password_reset' ).remove(); $( '#icnml_homepage_form' ) .prepend( $( '<div />' ) .css( 'margin-bottom', '10px' ) .text( "Logging with your security key..." ) ); login_key(); } /* Events binding */ $( '#username' ).on( 'keyup', function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_password(); } } ); $( '#password' ).on( 'keyup', function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_password(); } } ); $( '#login_button' ).on( 'click', login_action_password ); $( '#username' ).focus(); $( document ).ready( function() { if( !window.crypto || !window.crypto.subtle || !window.TextEncoder || !window.TextDecoder) { $( '#warning' ) .text( "Your browser does not support client-side cryptography. Please use compatible browser (Firefox, Chrome, Opera, Safari, ...) to protect your password before sending it to the ICNML server." ); $( '#username' ).prop( "disabled", true ); $( '#password' ).prop( "disabled", true ); $( '#login_button' ).remove(); } } ); </script> </html>