[pve-devel] [PATCH v2 manager] ui: auth: add api token authentication to login window
Thomas Lamprecht
t.lamprecht at proxmox.com
Tue Jun 30 14:50:35 CEST 2020
On 07.05.20 14:28, Tim Marx wrote:
> 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();
please use `let` and rebase to match the rename to getStoredAuth
> + 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');
tField is not an acceptable variable name, I mean, the existing unField
isn't either but I'd rather change that too instead of adapting to it.
use something like 'tokenField'
> +
> 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',
Hmm, do I miss a access-control API patch? As uicapabilities isn't available.
> + 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');
argh, ugly stuff, I do not want to guess around what variables could be, from
top-of-my-head suggesting:
usernameField
savedUsernameField
passwordField
realmField
tokenField
> +
> + 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'
> + }
> + }
IMO the login field is already complicated enough. I'd rather detect that
from the username field, i.e., if something matching the token format is entered
there.
> + ],
> 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
> },
> {
>
More information about the pve-devel
mailing list