]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/window/LoginWindow.js
ui: support u2f authentication and configuration
[pve-manager.git] / www / manager6 / window / LoginWindow.js
index 5967c92f307329b848d19f4df4573b926f2cb8e6..93b060611a23e7480c38fda82757fa490e74a9f4 100644 (file)
@@ -13,39 +13,108 @@ Ext.define('PVE.window.LoginWindow', {
            var saveunField = this.lookupReference('saveunField');
            var view = this.getView();
 
-           if(form.isValid()){
-               view.el.mask(gettext('Please wait...'), 'x-mask-loading');
+           if (!form.isValid()) {
+               return;
+           }
+
+           var perform_u2f_fn;
+           var finish_u2f_fn;
+
+           var failure_fn = function(resp) {
+               view.el.unmask();
+               var handler = function() {
+                   var uf = me.lookupReference('usernameField');
+                   uf.focus(true, true);
+               };
+
+               Ext.MessageBox.alert(gettext('Error'),
+                                    gettext("Login failed. Please try again"),
+                                    handler);
+           };
+
+           var success_fn = function(data) {
+               var handler = view.handler || Ext.emptyFn;
+               handler.call(me, data);
+               view.close();
+           };
+
+           view.el.mask(gettext('Please wait...'), 'x-mask-loading');
+
+           // set or clear username
+           var sp = Ext.state.Manager.getProvider();
+           if (saveunField.getValue() === true) {
+               sp.set(unField.getStateId(), unField.getValue());
+           } else {
+               sp.clear(unField.getStateId());
+           }
+           sp.set(saveunField.getStateId(), saveunField.getValue());
+
+           form.submit({
+               failure: function(f, resp){
+                   failure_fn(resp);
+               },
+               success: function(f, resp){
+                   view.el.unmask();
 
-               // set or clear username
-               var sp = Ext.state.Manager.getProvider();
-               if (saveunField.getValue() === true) {
-                   sp.set(unField.getStateId(), unField.getValue());
-               } else {
-                   sp.clear(unField.getStateId());
+                   var data = resp.result.data;
+                   if (Ext.isDefined(data.U2FChallenge)) {
+                       perform_u2f_fn(data);
+                   } else {
+                       success_fn(data);
+                   }
                }
-               sp.set(saveunField.getStateId(), saveunField.getValue());
+           });
+
+           perform_u2f_fn = function(data) {
+               // Store first factor login information first:
+               data.LoggedOut = true;
+               Proxmox.Utils.setAuthData(data);
+               // Show the message:
+               var msg = Ext.Msg.show({
+                   title: 'U2F: '+gettext('Verification'),
+                   message: gettext('Please press the button on your U2F Device'),
+                   buttons: []
+               });
+               var chlg = data.U2FChallenge;
+               var key = {
+                   version: chlg.version,
+                   keyHandle: chlg.keyHandle
+               };
+               u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
+                   msg.close();
+                   if (res.errorCode) {
+                       Proxmox.Utils.authClear();
+                       Ext.Msg.alert(gettext('Error'), "U2F Error: "+res.errorCode);
+                       return;
+                   }
+                   delete res.errorCode;
+                   finish_u2f_fn(res);
+               });
+           };
 
-               form.submit({
-                   failure: function(f, resp){
+           finish_u2f_fn = function(res) {
+               view.el.mask(gettext('Please wait...'), 'x-mask-loading');
+               var params = { response: JSON.stringify(res) };
+               Proxmox.Utils.API2Request({
+                   url: '/api2/extjs/access/tfa',
+                   params: params,
+                   method: 'POST',
+                   timeout: 5000, // it'll delay both success & failure
+                   success: function(resp, opts) {
                        view.el.unmask();
-                       var handler = function() {
-                           var uf = me.lookupReference('usernameField');
-                           uf.focus(true, true);
-                       };
-
-                       Ext.MessageBox.alert(gettext('Error'),
-                                            gettext("Login failed. Please try again"),
-                                            handler);
+                       // Fill in what we copy over from the 1st factor:
+                       var data = resp.result.data;
+                       data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
+                       data.username = Proxmox.UserName;
+                       // Finish logging in:
+                       success_fn(data);
                    },
-                   success: function(f, resp){
-                       view.el.unmask();
-
-                       var handler = view.handler || Ext.emptyFn;
-                       handler.call(me, resp.result.data);
-                       view.close();
+                   failure: function(resp, opts) {
+                       Proxmox.Utils.authClear();
+                       failure_fn(resp);
                    }
                });
-           }
+           };
        },
 
        control: {