[pve-devel] [PATCH v2 manager] ui: auth: add api token authentication to login window
Tim Marx
t.marx at proxmox.com
Thu May 7 14:28:25 CEST 2020
Signed-off-by: Tim Marx <t.marx at proxmox.com>
---
Notes:
changed since v1:
* store token including the product prefix
* add token id to username to make it more obvious that it's note the actual user
www/manager6/Workspace.js | 5 ++
www/manager6/window/LoginWindow.js | 129 ++++++++++++++++++++++-------
2 files changed, 105 insertions(+), 29 deletions(-)
diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js
index 57cb1bb9..b03443cb 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -73,6 +73,11 @@ Ext.define('PVE.Workspace', {
me.callParent();
+ var storedUser = Proxmox.Utils.getStoredUser();
+ if (storedUser.username) {
+ Proxmox.UserName = storedUser.username;
+ }
+
if (!Proxmox.Utils.authOK()) {
me.showLogin();
} else {
diff --git a/www/manager6/window/LoginWindow.js b/www/manager6/window/LoginWindow.js
index e29b7352..223ad581 100644
--- a/www/manager6/window/LoginWindow.js
+++ b/www/manager6/window/LoginWindow.js
@@ -12,6 +12,8 @@ Ext.define('PVE.window.LoginWindow', {
var form = this.lookupReference('loginForm');
var unField = this.lookupReference('usernameField');
var saveunField = this.lookupReference('saveunField');
+ var tField = this.lookupReference('apitokenField');
+
var view = this.getView();
if (!form.isValid()) {
@@ -20,38 +22,60 @@ Ext.define('PVE.window.LoginWindow', {
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());
+ if (tField.value !== '') {
+ var splitToken = tField.value.match(/^(.*)=(.*)$/);
+ Proxmox.Utils.API2Request({
+ url: '/api2/extjs/access/uicapabilities',
+ headers:{
+ Authorization: 'PVEAPIToken=' + tField.value
+ },
+ success: function(response, opts) {
+ var data = {
+ username: splitToken[1],
+ token: 'PVEAPIToken=' + tField.value,
+ cap: response.result.data.cap
+ };
+ me.success(data);
+ },
+
+ failure: function(response, opts) {
+ me.failure(response);
+ }
+ });
} else {
- sp.clear(unField.getStateId());
- }
- sp.set(saveunField.getStateId(), saveunField.getValue());
+ // 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){
- me.failure(resp);
- },
- success: function(f, resp){
- view.el.unmask();
+ form.submit({
+ failure: function(f, resp){
+ me.failure(resp);
+ },
+ success: function(f, resp){
+ view.el.unmask();
- var data = resp.result.data;
- if (Ext.isDefined(data.NeedTFA)) {
- // Store first factor login information first:
- data.LoggedOut = true;
- Proxmox.Utils.setAuthData(data);
+ var data = resp.result.data;
+ if (Ext.isDefined(data.NeedTFA)) {
+ // Store first factor login information first:
+ data.LoggedOut = true;
+ Proxmox.Utils.setAuthData(data);
- if (Ext.isDefined(data.U2FChallenge)) {
- me.perform_u2f(data);
+ if (Ext.isDefined(data.U2FChallenge)) {
+ me.perform_u2f(data);
+ } else {
+ me.perform_otp();
+ }
} else {
- me.perform_otp();
+ me.success(data);
}
- } else {
- me.success(data);
}
- }
- });
+ });
+ }
},
failure: function(resp) {
@@ -143,6 +167,31 @@ Ext.define('PVE.window.LoginWindow', {
}
});
},
+ onUsetokenChange: function(value) {
+ var uField = this.lookupReference('usernameField');
+ var svunField = this.lookupReference('saveunField');
+ var pField = this.lookupReference('passwordField');
+ var rField = this.lookupReference('realmField');
+ var tField = this.lookupReference('apitokenField');
+
+ uField.setVisible(!value.checked);
+ uField.setDisabled(value.checked);
+
+ svunField.setVisible(!value.checked);
+ svunField.setDisabled(value.checked);
+
+ pField.setVisible(!value.checked);
+ pField.setDisabled(value.checked);
+
+ rField.setVisible(!value.checked);
+ rField.setDisabled(value.checked);
+
+
+
+ tField.setVisible(value.checked);
+ tField.setDisabled(!value.checked);
+
+ },
control: {
'field[name=username]': {
@@ -198,7 +247,20 @@ Ext.define('PVE.window.LoginWindow', {
defaultFocus: 'usernameField',
defaultButton: 'loginButton',
-
+ tools: [
+ {
+ xtype: 'checkbox',
+ fieldLabel: gettext('Use API Token'),
+ name: 'usetoken',
+ reference: 'usetoken',
+ stateId: 'login-usetoken',
+ labelAlign: 'right',
+ submitValue: false,
+ listeners: {
+ change: 'onUsetokenChange'
+ }
+ }
+ ],
items: [{
xtype: 'form',
layout: 'form',
@@ -209,7 +271,6 @@ Ext.define('PVE.window.LoginWindow', {
labelAlign: 'right',
allowBlank: false
},
-
items: [
{
xtype: 'textfield',
@@ -228,7 +289,17 @@ Ext.define('PVE.window.LoginWindow', {
},
{
xtype: 'pveRealmComboBox',
- name: 'realm'
+ name: 'realm',
+ reference: 'realmField'
+ },
+ {
+ xtype: 'textfield',
+ fieldLabel: gettext('API Token'),
+ name: 'apitoken',
+ reference: 'apitokenField',
+ emptyText: 'USER at REALM!TOKENID=UUID',
+ hidden: true,
+ disabled: true
},
{
xtype: 'proxmoxLanguageSelector',
@@ -246,8 +317,8 @@ Ext.define('PVE.window.LoginWindow', {
name: 'saveusername',
reference: 'saveunField',
stateId: 'login-saveusername',
- labelWidth: 250,
labelAlign: 'right',
+ labelWidth: 250,
submitValue: false
},
{
--
2.20.1
More information about the pve-devel
mailing list