[pbs-devel] [PATH proxmox-backup v1 09/12] ui: implement OpenId login

Dietmar Maurer dietmar at proxmox.com
Tue Jun 22 10:56:17 CEST 2021


---
 src/api2/access.rs |   6 +--
 www/Application.js |   8 +++-
 www/LoginView.js   | 100 ++++++++++++++++++++++++++++++++++++++++++++-
 www/Utils.js       |   8 ++++
 4 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/src/api2/access.rs b/src/api2/access.rs
index 5abb5cb4..e95db88b 100644
--- a/src/api2/access.rs
+++ b/src/api2/access.rs
@@ -18,7 +18,7 @@ use crate::api2::types::*;
 use crate::auth_helpers::*;
 use crate::server::ticket::ApiTicket;
 use crate::tools::ticket::{self, Empty, Ticket};
-use crate::config::domains::OpenIdRealmConfig;
+use crate::config::domains::{OPENID_STATE_DIR, OpenIdRealmConfig};)
 
 use crate::config::acl as acl_config;
 use crate::config::acl::{PRIVILEGES, PRIV_PERMISSIONS_MODIFY, PRIV_SYS_AUDIT};
@@ -288,10 +288,8 @@ pub fn openid_login(
 ) -> Result<Value, Error> {
     let user_info = CachedUserInfo::new()?;
 
-    let backup_user = crate::backup::backup_user()?;
-
     let (realm, private_auth_state) =
-        OpenIdAuthenticator::verify_public_auth_state(&state, backup_user.uid)?;
+        OpenIdAuthenticator::verify_public_auth_state(OPENID_STATE_DIR, &state)?;
 
     let (domains, _digest) = crate::config::domains::config()?;
     let config: OpenIdRealmConfig = domains.lookup("openid", &realm)?;
diff --git a/www/Application.js b/www/Application.js
index c4df600e..20ae26bd 100644
--- a/www/Application.js
+++ b/www/Application.js
@@ -49,9 +49,15 @@ Ext.define('PBS.Application', {
 	var provider = new Ext.state.LocalStorageProvider({ prefix: 'ext-pbs-' });
 	Ext.state.Manager.setProvider(provider);
 
+	let openid_login = false;
+	let param = PBS.Utils.openid_login_param();
+	if (param !== undefined) {
+	    openid_login = true;
+	}
+
 	// show login window if not loggedin
 	var loggedin = Proxmox.Utils.authOK();
-	if (!loggedin) {
+	if (openid_login || !loggedin) {
 	    me.changeView('loginview', true);
 	} else {
 	    me.changeView('mainview', true);
diff --git a/www/LoginView.js b/www/LoginView.js
index 6dd09646..f2fc5370 100644
--- a/www/LoginView.js
+++ b/www/LoginView.js
@@ -2,6 +2,21 @@ Ext.define('PBS.LoginView', {
     extend: 'Ext.container.Container',
     xtype: 'loginview',
 
+    viewModel: {
+	data: {
+	    openid: false,
+	},
+	formulas: {
+	    button_text: function(get) {
+		if (get("openid") === true) {
+		    return gettext("Login (OpenID redirect)");
+		} else {
+		    return gettext("Login");
+		}
+	    },
+	},
+    },
+
     controller: {
 	xclass: 'Ext.app.ViewController',
 
@@ -15,8 +30,33 @@ Ext.define('PBS.LoginView', {
 		return;
 	    }
 
+	    let redirect_url = location.origin;
+
 	    let params = loginForm.getValues();
 
+	    if (this.getViewModel().data.openid === true) {
+		let realm = params.realm;
+		try {
+		    let resp = await PBS.Async.api2({
+			url: '/api2/extjs/access/domains',
+			params: {
+			    realm: realm,
+			    "redirect-url": redirect_url,
+			},
+			method: 'POST',
+		    });
+		    window.location = resp.result.data;
+		} catch (error) {
+		    Proxmox.Utils.authClear();
+		    loginForm.unmask();
+		    Ext.MessageBox.alert(
+			gettext('Error'),
+			gettext('OpenId redirect failed. Please try again<br>Error: ' + error),
+		    );
+		}
+		return;
+	    }
+
 	    params.username = params.username + '@' + params.realm;
 	    delete params.realm;
 
@@ -98,6 +138,14 @@ Ext.define('PBS.LoginView', {
 		    window.location.reload();
 		},
 	    },
+	    'field[name=realm]': {
+		change: function(f, value) {
+		    let record = f.store.getById(value);
+		    if (record === undefined) return;
+		    let data = record.data;
+		    this.getViewModel().set("openid", data.type === "openid");
+		},
+	    },
 	    'button[reference=loginButton]': {
 		click: 'submitForm',
 	    },
@@ -116,6 +164,43 @@ Ext.define('PBS.LoginView', {
 			var pwField = this.lookupReference('passwordField');
 			pwField.focus();
 		    }
+
+		    let param = PBS.Utils.openid_login_param();
+		    if (param !== undefined) {
+			Proxmox.Utils.authClear();
+
+			let loginForm = this.lookupReference('loginForm');
+			loginForm.mask(gettext('OpenID login - please wait...'), 'x-mask-loading');
+
+			let redirect_url = location.origin;
+
+			Proxmox.Utils.API2Request({
+			    url: '/api2/extjs/access/openid-login',
+			    params: {
+				state: param.state,
+				code: param.code,
+				"redirect-url": redirect_url,
+			    },
+			    method: 'POST',
+			    failure: function(response) {
+				loginForm.unmask();
+				Ext.MessageBox.alert(
+				    gettext('Error'),
+				    gettext('Login failed. Please try again<br>Error: ' + response.htmlStatus),
+				    function() {
+					window.location = redirect_url;
+				    },
+				);
+			    },
+			    success: function(response, options) {
+				loginForm.unmask();
+				let data = response.result.data;
+				PBS.Utils.updateLoginData(data);
+				PBS.app.changeView('mainview');
+				history.replaceState(null, '', redirect_url + '#pbsDashboard');
+			    },
+			});
+		    }
 		},
 	    },
 	},
@@ -191,6 +276,10 @@ Ext.define('PBS.LoginView', {
 			    itemId: 'usernameField',
 			    reference: 'usernameField',
 			    stateId: 'login-username',
+			    bind: {
+				visible: "{!openid}",
+				disabled: "{openid}",
+			    },
 			},
 			{
 			    xtype: 'textfield',
@@ -199,6 +288,10 @@ Ext.define('PBS.LoginView', {
 			    name: 'password',
 			    itemId: 'passwordField',
 			    reference: 'passwordField',
+			    bind: {
+				visible: "{!openid}",
+				disabled: "{openid}",
+			    },
 			},
 			{
 			    xtype: 'pmxRealmComboBox',
@@ -223,9 +316,14 @@ Ext.define('PBS.LoginView', {
 			    labelWidth: 250,
 			    labelAlign: 'right',
 			    submitValue: false,
+			    bind: {
+				visible: "{!openid}",
+			    },
 			},
 			{
-			    text: gettext('Login'),
+			    bind: {
+				text: "{button_text}",
+			    },
 			    reference: 'loginButton',
 			    formBind: true,
 			},
diff --git a/www/Utils.js b/www/Utils.js
index 6b378355..677f2204 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -326,6 +326,14 @@ Ext.define('PBS.Utils', {
         };
     },
 
+    openid_login_param: function() {
+	let param = Ext.Object.fromQueryString(window.location.search);
+	if (param.state !== undefined && param.code !== undefined) {
+	    return param;
+	}
+	return undefined;
+    },
+
     calculate_dedup_factor: function(gcstatus) {
 	let dedup = 1.0;
 	if (gcstatus['disk-bytes'] > 0) {
-- 
2.30.2





More information about the pbs-devel mailing list