public inbox for pmg-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG
@ 2025-03-03  8:49 Markus Frank
  2025-03-03  8:58 ` Markus Frank
  2025-03-10 14:37 ` Dominik Csapak
  0 siblings, 2 replies; 4+ messages in thread
From: Markus Frank @ 2025-03-03  8:49 UTC (permalink / raw)
  To: pmg-devel

AuthEditOIDC.js is based on AuthEditOpenId from widget-toolkit and
adds additional configuration options for autocreate-role-assignment.

It uses sub/preferred_username for username-claim instead of the old
names (subject/username/email). Removed email option entirely as it is
incompatible with the username scheme.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
v2:
* renamed subject to sub
* renamed username to preferred_username
* removed email entirely

 js/AuthEditOIDC.js | 270 +++++++++++++++++++++++++++++++++++++++++++++
 js/Makefile        |   1 +
 js/Utils.js        |   1 +
 3 files changed, 272 insertions(+)
 create mode 100644 js/AuthEditOIDC.js

diff --git a/js/AuthEditOIDC.js b/js/AuthEditOIDC.js
new file mode 100644
index 0000000..cda9d68
--- /dev/null
+++ b/js/AuthEditOIDC.js
@@ -0,0 +1,270 @@
+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) && !me.isCreate) {
+	    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',
+	},
+    ],
+
+    column2: [
+	{
+	    xtype: 'pmxDisplayEditField',
+	    name: 'username-claim',
+	    fieldLabel: gettext('Username Claim'),
+	    editConfig: {
+		xtype: 'proxmoxKVComboBox',
+		editable: true,
+		comboItems: [
+		    ['__default__', Proxmox.Utils.defaultText],
+		    ['sub', 'sub (subject)'],
+		    ['preferred_username', 'preferred_username'],
+		],
+	    },
+	    cbind: {
+		value: get => get('isCreate') ? '__default__' : Proxmox.Utils.defaultText,
+		deleteEmpty: '{!isCreate}',
+		editable: '{isCreate}',
+	    },
+	},
+	{
+	    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



_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG
  2025-03-03  8:49 [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG Markus Frank
@ 2025-03-03  8:58 ` Markus Frank
  2025-03-10 14:37 ` Dominik Csapak
  1 sibling, 0 replies; 4+ messages in thread
From: Markus Frank @ 2025-03-03  8:58 UTC (permalink / raw)
  To: pmg-devel


On  2025-03-03 09:49, Markus Frank wrote:
> AuthEditOIDC.js is based on AuthEditOpenId from widget-toolkit and
> adds additional configuration options for autocreate-role-assignment.
> 
> It uses sub/preferred_username for username-claim instead of the old
> names (subject/username/email). Removed email option entirely as it is
> incompatible with the username scheme.
I am sorry.
This part should be:

Use sub/preferred_username for username-claim instead of the old names
(subject/username/email). Remove the email option entirely as it is
incompatible with the username scheme.

> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
> v2:
> * renamed subject to sub
> * renamed username to preferred_username
> * removed email entirely
> 
>   js/AuthEditOIDC.js | 270 +++++++++++++++++++++++++++++++++++++++++++++
>   js/Makefile        |   1 +
>   js/Utils.js        |   1 +
>   3 files changed, 272 insertions(+)
>   create mode 100644 js/AuthEditOIDC.js
> 
> diff --git a/js/AuthEditOIDC.js b/js/AuthEditOIDC.js
> new file mode 100644
> index 0000000..cda9d68
> --- /dev/null
> +++ b/js/AuthEditOIDC.js
> @@ -0,0 +1,270 @@
> +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) && !me.isCreate) {
> +	    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',
> +	},
> +    ],
> +
> +    column2: [
> +	{
> +	    xtype: 'pmxDisplayEditField',
> +	    name: 'username-claim',
> +	    fieldLabel: gettext('Username Claim'),
> +	    editConfig: {
> +		xtype: 'proxmoxKVComboBox',
> +		editable: true,
> +		comboItems: [
> +		    ['__default__', Proxmox.Utils.defaultText],
> +		    ['sub', 'sub (subject)'],
> +		    ['preferred_username', 'preferred_username'],
> +		],
> +	    },
> +	    cbind: {
> +		value: get => get('isCreate') ? '__default__' : Proxmox.Utils.defaultText,
> +		deleteEmpty: '{!isCreate}',
> +		editable: '{isCreate}',
> +	    },
> +	},
> +	{
> +	    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



_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG
  2025-03-03  8:49 [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG Markus Frank
  2025-03-03  8:58 ` Markus Frank
@ 2025-03-10 14:37 ` Dominik Csapak
  2025-03-11 10:22   ` Markus Frank
  1 sibling, 1 reply; 4+ messages in thread
From: Dominik Csapak @ 2025-03-10 14:37 UTC (permalink / raw)
  To: pmg-devel

Works fine during testing, but noticed some things in the code,
see comments inline:

On 3/3/25 09:49, Markus Frank wrote:
> AuthEditOIDC.js is based on AuthEditOpenId from widget-toolkit and
> adds additional configuration options for autocreate-role-assignment.
> 
> It uses sub/preferred_username for username-claim instead of the old
> names (subject/username/email). Removed email option entirely as it is
> incompatible with the username scheme.
> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
> v2:
> * renamed subject to sub
> * renamed username to preferred_username
> * removed email entirely
> 
>   js/AuthEditOIDC.js | 270 +++++++++++++++++++++++++++++++++++++++++++++
>   js/Makefile        |   1 +
>   js/Utils.js        |   1 +
>   3 files changed, 272 insertions(+)
>   create mode 100644 js/AuthEditOIDC.js
> 
> diff --git a/js/AuthEditOIDC.js b/js/AuthEditOIDC.js
> new file mode 100644
> index 0000000..cda9d68
> --- /dev/null
> +++ b/js/AuthEditOIDC.js
> @@ -0,0 +1,270 @@
> +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;

in one branch you return 1, but later true/false
also if 'autocreate' === 0, '!autocreate' is already true..

couldn't you simply use '!autocreate' in the bindings then?


> +	    },
> +	    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'];
> +	    }

if the content of 'source' would match the indices ('fixed-role' and 'role-claim') you could do
something like this (psuedo-code & untested!)

if (values.source) {
	let assignment = {};
	assignment[values.source] = values[values.source];
	values['aut...'] = printPropertyString(assignment);
}

no?


> +	    values['autocreate-role-assignment'] =
> +		Proxmox.Utils.printPropertyString(autocreateRoleAssignment);
> +	}
> +
> +	if ((!values.autocreate || !values.source) && !me.isCreate) {
> +	    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';
> +	    }
> +	}
AFAIR, we already have this behavior factored out in proxmox-widget-toolkit:

'delete_if_default'

> +	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__';
> +	}

could be simplified to

values.source = autocreateRoleAssignment.source ?? '__default__';

> +
> +	if (autocreateRoleAssignment.source === 'fixed') {
> +	    values['fixed-role'] = autocreateRoleAssignment['fixed-role'];
> +	}
> +	if (autocreateRoleAssignment.source === 'from-claim') {
> +	    values['role-claim'] = autocreateRoleAssignment['role-claim'];
> +	}

same here but reversed:

values[assignment.source] = assignment[assignment.source];

> +
> +	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',
> +	},
> +    ],
> +
> +    column2: [
> +	{
> +	    xtype: 'pmxDisplayEditField',
> +	    name: 'username-claim',
> +	    fieldLabel: gettext('Username Claim'),
> +	    editConfig: {
> +		xtype: 'proxmoxKVComboBox',
> +		editable: true,
> +		comboItems: [
> +		    ['__default__', Proxmox.Utils.defaultText],
> +		    ['sub', 'sub (subject)'],
> +		    ['preferred_username', 'preferred_username'],

if you're changing the text vs widget-toolkit, why not got the full length
and localize the description?

e.g. `gettext('sub (Subject)')`

?

(preexisting) maybe i just overlooked that with the recent patches, but why are the
claims different than the other products (sub vs subject, preferred_username vs username) ?

> +		],
> +	    },
> +	    cbind: {
> +		value: get => get('isCreate') ? '__default__' : Proxmox.Utils.defaultText,
> +		deleteEmpty: '{!isCreate}',
> +		editable: '{isCreate}',
> +	    },
> +	},
> +	{
> +	    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'],

IMHO those should be put in 'gettext'

> +	    ],
> +	    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}',
> +	    },

side question: did you got that to work with keycloak? i couldn't in my tests...

> +	},
> +    ],
> +
> +    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



_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG
  2025-03-10 14:37 ` Dominik Csapak
@ 2025-03-11 10:22   ` Markus Frank
  0 siblings, 0 replies; 4+ messages in thread
From: Markus Frank @ 2025-03-11 10:22 UTC (permalink / raw)
  To: Dominik Csapak, pmg-devel

I will address most of your comments in v3, thanks.

Some comments/answers inline:

On  2025-03-10 15:37, Dominik Csapak wrote:
> Works fine during testing, but noticed some things in the code,
> see comments inline:
> 
> On 3/3/25 09:49, Markus Frank wrote:
>> AuthEditOIDC.js is based on AuthEditOpenId from widget-toolkit and
>> adds additional configuration options for autocreate-role-assignment.
>>
>> It uses sub/preferred_username for username-claim instead of the old
>> names (subject/username/email). Removed email option entirely as it is
>> incompatible with the username scheme.
>>
>> Signed-off-by: Markus Frank <m.frank@proxmox.com>
>> ---
>> v2:
>> * renamed subject to sub
>> * renamed username to preferred_username
>> * removed email entirely
>>
>>   js/AuthEditOIDC.js | 270 +++++++++++++++++++++++++++++++++++++++++++++
>>   js/Makefile        |   1 +
>>   js/Utils.js        |   1 +
>>   3 files changed, 272 insertions(+)
>>   create mode 100644 js/AuthEditOIDC.js
>>
>> diff --git a/js/AuthEditOIDC.js b/js/AuthEditOIDC.js
>> new file mode 100644
>> index 0000000..cda9d68
>> --- /dev/null
>> +++ b/js/AuthEditOIDC.js
>> @@ -0,0 +1,270 @@
>> +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;
> 
> in one branch you return 1, but later true/false
> also if 'autocreate' === 0, '!autocreate' is already true..
> 
> couldn't you simply use '!autocreate' in the bindings then?
> 
> 
>> +        },
>> +        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'];
>> +        }
> 
> if the content of 'source' would match the indices ('fixed-role' and 'role-claim') you could do
> something like this (psuedo-code & untested!)
> 
> if (values.source) {
>      let assignment = {};
>      assignment[values.source] = values[values.source];
>      values['aut...'] = printPropertyString(assignment);
> }
> 
> no?
Sadly not.

If the content of 'source' would match the indices ('fixed-role' and 'role-claim'),
I would still need to use an if to change the source variable:

if (values.source) {
       let assignment = {};
       assignment[values.source] = values[values.source];
       if (values.source === 'fixed-role') {
           assignment.source = 'fixed';
       } else if (values.source === 'role-claim') {
           assignment.source = 'from-claim';
       }
       values['aut...'] = printPropertyString(assignment);
}

I am not sure if that would be better.
> 
> 
>> +        values['autocreate-role-assignment'] =
>> +        Proxmox.Utils.printPropertyString(autocreateRoleAssignment);
>> +    }
>> +
>> +    if ((!values.autocreate || !values.source) && !me.isCreate) {
>> +        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';
>> +        }
>> +    }
> AFAIR, we already have this behavior factored out in proxmox-widget-toolkit:
> 
> 'delete_if_default'
> 
>> +    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__';
>> +    }
> 
> could be simplified to
> 
> values.source = autocreateRoleAssignment.source ?? '__default__';
> 
>> +
>> +    if (autocreateRoleAssignment.source === 'fixed') {
>> +        values['fixed-role'] = autocreateRoleAssignment['fixed-role'];
>> +    }
>> +    if (autocreateRoleAssignment.source === 'from-claim') {
>> +        values['role-claim'] = autocreateRoleAssignment['role-claim'];
>> +    }
> 
> same here but reversed:
> 
> values[assignment.source] = assignment[assignment.source];
> 
>> +
>> +    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',
>> +    },
>> +    ],
>> +
>> +    column2: [
>> +    {
>> +        xtype: 'pmxDisplayEditField',
>> +        name: 'username-claim',
>> +        fieldLabel: gettext('Username Claim'),
>> +        editConfig: {
>> +        xtype: 'proxmoxKVComboBox',
>> +        editable: true,
>> +        comboItems: [
>> +            ['__default__', Proxmox.Utils.defaultText],
>> +            ['sub', 'sub (subject)'],
>> +            ['preferred_username', 'preferred_username'],
> 
> if you're changing the text vs widget-toolkit, why not got the full length
> and localize the description?
> 
> e.g. `gettext('sub (Subject)')`
> 
> ?
> 
> (preexisting) maybe i just overlooked that with the recent patches, but why are the
> claims different than the other products (sub vs subject, preferred_username vs username) ?
subject and username do not exist (anymore).

We use something like this in our backends:

} elsif ($user_attr eq 'subject') { # stay compat with old versions
	$unique_name = $info->{'sub'};
} elsif ($user_attr eq 'username') { # stay compat with old versions
	my $username = $info->{'preferred_username'};
	die "missing claim 'preferred_username'\n" if !defined($username);
	$unique_name =  $username;

I guess it was the plan to update these names in the PVE & PBS WebUIs, but it never happened.

> 
>> +        ],
>> +        },
>> +        cbind: {
>> +        value: get => get('isCreate') ? '__default__' : Proxmox.Utils.defaultText,
>> +        deleteEmpty: '{!isCreate}',
>> +        editable: '{isCreate}',
>> +        },
>> +    },
>> +    {
>> +        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'],
> 
> IMHO those should be put in 'gettext'
> 
>> +        ],
>> +        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}',
>> +        },
> 
> side question: did you got that to work with keycloak? i couldn't in my tests...
I tried it with keycloak and authentik. I was also unsuccessful.
> 
>> +    },
>> +    ],
>> +
>> +    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
> 
> 
> 
> _______________________________________________
> pmg-devel mailing list
> pmg-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel
> 
> 



_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-03-11 10:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-03  8:49 [pmg-devel] [PATCH pmg-gui v2] add OIDC configuration panel for PMG Markus Frank
2025-03-03  8:58 ` Markus Frank
2025-03-10 14:37 ` Dominik Csapak
2025-03-11 10:22   ` Markus Frank

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal