[pmg-devel] [PATCH pmg-gui v1] add OIDC configuration panel

Markus Frank m.frank at proxmox.com
Thu Feb 27 15:17:02 CET 2025


This is based on AuthEditOpenId from the proxmox-widget-toolkit and
adds additional configuration options for autocreate-role-assignment.

Signed-off-by: Markus Frank <m.frank at proxmox.com>
---
 js/AuthEditOIDC.js | 271 +++++++++++++++++++++++++++++++++++++++++++++
 js/Makefile        |   1 +
 js/Utils.js        |   1 +
 3 files changed, 273 insertions(+)
 create mode 100644 js/AuthEditOIDC.js

diff --git a/js/AuthEditOIDC.js b/js/AuthEditOIDC.js
new file mode 100644
index 0000000..ddd173e
--- /dev/null
+++ b/js/AuthEditOIDC.js
@@ -0,0 +1,271 @@
+Ext.define('PMG.OIDCInputPanel', {
+    extend: 'Proxmox.panel.InputPanel',
+    xtype: 'pmgAuthOIDCPanel',
+    mixins: ['Proxmox.Mixin.CBind'],
+
+    showDefaultRealm: false,
+
+    type: 'oidc',
+
+    viewModel: {
+	data: {
+	    roleSource: '__default__',
+	    autocreate: 0,
+	},
+	formulas: {
+	    hideRoleAssignment: function(get) {
+		let autocreate = get('autocreate');
+		if (!autocreate) {
+		    return 1;
+		}
+		return autocreate === 0;
+	    },
+	    hideFixedRoleAssignment: function(get) {
+		return get('roleSource') !== 'fixed' || get('hideRoleAssignment');
+	    },
+	    hideClaimRoleAssignment: function(get) {
+		return get('roleSource') !== 'from-claim' || get('hideRoleAssignment');
+	    },
+	},
+    },
+
+    onGetValues: function(values) {
+	let me = this;
+
+	if (me.isCreate && !me.useTypeInUrl) {
+	    values.type = me.type;
+	}
+
+	if (values.source) {
+	    let autocreateRoleAssignment = {};
+	    autocreateRoleAssignment.source = values.source;
+	    if (values.source === 'fixed') {
+		autocreateRoleAssignment['fixed-role'] = values['fixed-role'];
+	    } else if (values.source === 'from-claim') {
+		autocreateRoleAssignment['role-claim'] = values['role-claim'];
+	    }
+	    values['autocreate-role-assignment'] =
+		Proxmox.Utils.printPropertyString(autocreateRoleAssignment);
+	}
+
+	if (!values.autocreate || !values.source) {
+	    if (values.delete) {
+		if (Ext.isArray(values.delete)) {
+		    values.delete.push('autocreate-role-assignment');
+		} else {
+		    values.delete += ',autocreate-role-assignment';
+		}
+	    } else {
+		values.delete = 'autocreate-role-assignment';
+	    }
+	}
+	delete values.source;
+	delete values['fixed-role'];
+	delete values['role-claim'];
+
+	return values;
+    },
+
+    setValues: function(values) {
+	let autocreateRoleAssignment =
+	    Proxmox.Utils.parsePropertyString(values['autocreate-role-assignment']);
+
+	if (autocreateRoleAssignment.source) {
+	    values.source = autocreateRoleAssignment.source;
+	} else {
+	    values.source = '__default__';
+	}
+
+	if (autocreateRoleAssignment.source === 'fixed') {
+	    values['fixed-role'] = autocreateRoleAssignment['fixed-role'];
+	}
+	if (autocreateRoleAssignment.source === 'from-claim') {
+	    values['role-claim'] = autocreateRoleAssignment['role-claim'];
+	}
+
+	this.callParent(arguments);
+    },
+
+
+    columnT: [
+	{
+	    xtype: 'textfield',
+	    name: 'issuer-url',
+	    fieldLabel: gettext('Issuer URL'),
+	    allowBlank: false,
+	},
+    ],
+
+    column1: [
+	{
+	    xtype: 'pmxDisplayEditField',
+	    name: 'realm',
+	    cbind: {
+		value: '{realm}',
+		editable: '{isCreate}',
+	    },
+	    fieldLabel: gettext('Realm'),
+	    allowBlank: false,
+	},
+	{
+	    xtype: 'proxmoxcheckbox',
+	    fieldLabel: gettext('Default realm'),
+	    name: 'default',
+	    value: 0,
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+		hidden: '{!showDefaultRealm}',
+		disabled: '{!showDefaultRealm}',
+	    },
+	    autoEl: {
+		tag: 'div',
+		'data-qtip': gettext('Set realm as default for login'),
+	    },
+	},
+	{
+	    xtype: 'proxmoxtextfield',
+	    fieldLabel: gettext('Client ID'),
+	    name: 'client-id',
+	    allowBlank: false,
+	},
+	{
+	    xtype: 'proxmoxtextfield',
+	    fieldLabel: gettext('Client Key'),
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	    name: 'client-key',
+	},
+	{
+	    xtype: 'pmxDisplayEditField',
+	    name: 'username-claim',
+	    fieldLabel: gettext('Username Claim'),
+	    editConfig: {
+		xtype: 'proxmoxKVComboBox',
+		editable: true,
+		comboItems: [
+		    ['__default__', Proxmox.Utils.defaultText],
+		    ['subject', 'subject'],
+		    ['username', 'username'],
+		    ['email', 'email'],
+		],
+	    },
+	    cbind: {
+		value: get => get('isCreate') ? '__default__' : Proxmox.Utils.defaultText,
+		deleteEmpty: '{!isCreate}',
+		editable: '{isCreate}',
+	    },
+	},
+    ],
+
+    column2: [
+	{
+	    xtype: 'proxmoxtextfield',
+	    name: 'scopes',
+	    fieldLabel: gettext('Scopes'),
+	    emptyText: `${Proxmox.Utils.defaultText} (email profile)`,
+	    submitEmpty: false,
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	},
+	{
+	    xtype: 'proxmoxKVComboBox',
+	    name: 'prompt',
+	    fieldLabel: gettext('Prompt'),
+	    editable: true,
+	    emptyText: gettext('Auth-Provider Default'),
+	    comboItems: [
+		['__default__', gettext('Auth-Provider Default')],
+		['none', 'none'],
+		['login', 'login'],
+		['consent', 'consent'],
+		['select_account', 'select_account'],
+	    ],
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	},
+    ],
+
+    columnB: [
+	{
+	    xtype: 'proxmoxtextfield',
+	    name: 'comment',
+	    fieldLabel: gettext('Comment'),
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	},
+	{
+	    xtype: 'displayfield',
+	    value: gettext('Autocreate Options'),
+	},
+	{
+	    xtype: 'proxmoxcheckbox',
+	    fieldLabel: gettext('Autocreate Users'),
+	    name: 'autocreate',
+	    bind: {
+		value: '{autocreate}',
+	    },
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	},
+	{
+	    xtype: 'proxmoxKVComboBox',
+	    name: 'source',
+	    fieldLabel: gettext('Source for Role Assignment'),
+	    allowBlank: false,
+	    deleteEmpty: false,
+	    comboItems: [
+		[
+		    '__default__',
+		    Proxmox.Utils.defaultText
+			+ ' (' + gettext('All auto-created users get audit role') + ')',
+		],
+		['fixed', 'Fixed role for all auto-created users'],
+		['from-claim', 'Get role from OIDC claim'],
+	    ],
+	    bind: {
+		value: '{roleSource}',
+		disabled: '{hideRoleAssignment}',
+		hidden: '{hideRoleAssignment}',
+	    },
+	},
+	{
+	    xtype: 'pmgRoleSelector',
+	    name: 'fixed-role',
+	    allowBlank: false,
+	    deleteEmpty: false,
+	    fieldLabel: gettext('Fixed Role'),
+	    bind: {
+		disabled: '{hideFixedRoleAssignment}',
+		hidden: '{hideFixedRoleAssignment}',
+	    },
+	},
+	{
+	    xtype: 'proxmoxtextfield',
+	    name: 'role-claim',
+	    allowBlank: false,
+	    deleteEmpty: false,
+	    fieldLabel: gettext('Role Claim'),
+	    bind: {
+		disabled: '{hideClaimRoleAssignment}',
+		hidden: '{hideClaimRoleAssignment}',
+	    },
+	},
+    ],
+
+    advancedColumnB: [
+	{
+	    xtype: 'proxmoxtextfield',
+	    name: 'acr-values',
+	    fieldLabel: gettext('ACR Values'),
+	    submitEmpty: false,
+	    cbind: {
+		deleteEmpty: '{!isCreate}',
+	    },
+	},
+    ],
+});
diff --git a/js/Makefile b/js/Makefile
index d1fab9b..c984bf3 100644
--- a/js/Makefile
+++ b/js/Makefile
@@ -78,6 +78,7 @@ JSSRC=							\
 	LDAPConfig.js					\
 	UserEdit.js					\
 	UserView.js					\
+	AuthEditOIDC.js					\
 	TFAView.js					\
 	FetchmailEdit.js				\
 	FetchmailView.js				\
diff --git a/js/Utils.js b/js/Utils.js
index d4a55a8..9dbc76f 100644
--- a/js/Utils.js
+++ b/js/Utils.js
@@ -871,6 +871,7 @@ Ext.define('PMG.Utils', {
 	// use oidc instead of openid
 	Proxmox.Schema.authDomains.oidc = Proxmox.Schema.authDomains.openid;
 	Proxmox.Schema.authDomains.oidc.useTypeInUrl = false;
+	Proxmox.Schema.authDomains.oidc.ipanel = 'pmgAuthOIDCPanel';
 	delete Proxmox.Schema.authDomains.openid;
 
 	// Disable LDAP/AD as a realm until LDAP/AD login is implemented
-- 
2.39.5





More information about the pmg-devel mailing list