mirror of
https://github.com/netzbegruenung/user_saml.git
synced 2024-05-11 13:16:06 +02:00
Allow to configure multiple SAML providers
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
parent
9cdcae4bd5
commit
ee5308382b
|
@ -58,5 +58,13 @@ return [
|
||||||
'url' => '/saml/selectUserBackEnd',
|
'url' => '/saml/selectUserBackEnd',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Settings#getSamlProviderSettings',
|
||||||
|
'url' => '/settings/providerSettings/{providerId}',
|
||||||
|
'verb' => 'GET',
|
||||||
|
'defaults' => [
|
||||||
|
'providerId' => '1'
|
||||||
|
]
|
||||||
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -26,6 +26,25 @@
|
||||||
clear: both;
|
clear: both;
|
||||||
padding: 7px 0;
|
padding: 7px 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
|
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#user-saml .account-list {
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
overflow:hidden;
|
||||||
|
padding: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
#user-saml .account-list li {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-saml .account-list li a:not(.button) {
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
#user-saml .account-list li a.button {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
#user-saml .account-list li.active a {
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
99
js/admin.js
99
js/admin.js
|
@ -5,6 +5,22 @@
|
||||||
* @namespace OCA.User_SAML.Admin
|
* @namespace OCA.User_SAML.Admin
|
||||||
*/
|
*/
|
||||||
OCA.User_SAML.Admin = {
|
OCA.User_SAML.Admin = {
|
||||||
|
currentConfig: '1',
|
||||||
|
providerIds: '1',
|
||||||
|
|
||||||
|
_getAppConfig: function (key) {
|
||||||
|
return $.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: OC.linkToOCS('apps/provisioning_api/api/v1', 2) + 'config/apps' + '/user_saml/' + key + '?format=json'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
init: function() {
|
||||||
|
this._getAppConfig('providerIds').done(function (data){
|
||||||
|
if (data.ocs.data.data !== '') {
|
||||||
|
OCA.User_SAML.Admin.providerIds = data.ocs.data.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
chooseEnv: function() {
|
chooseEnv: function() {
|
||||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.chooseEnv, this));
|
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.chooseEnv, this));
|
||||||
|
@ -23,6 +39,32 @@
|
||||||
OCP.AppConfig.setValue('user_saml', 'type', 'saml', {success: function() {location.reload();}});
|
OCP.AppConfig.setValue('user_saml', 'type', 'saml', {success: function() {location.reload();}});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getConfigIdentifier: function() {
|
||||||
|
if (this.currentConfig === '1') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return this.currentConfig + '-';
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new provider
|
||||||
|
* @returns {number} id of the provider
|
||||||
|
*/
|
||||||
|
addProvider: function(callback) {
|
||||||
|
var providerIds = OCA.User_SAML.Admin.providerIds.split(',');
|
||||||
|
var nextId = 2;
|
||||||
|
while($.inArray('' + nextId, providerIds) >= 0) {
|
||||||
|
nextId++;
|
||||||
|
}
|
||||||
|
console.log(nextId);
|
||||||
|
OCP.AppConfig.setValue('user_saml', 'providerIds', OCA.User_SAML.Admin.providerIds + ',' + nextId, {
|
||||||
|
success: function () {
|
||||||
|
OCA.User_SAML.Admin.providerIds += ',' + nextId;
|
||||||
|
callback(nextId)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setSamlConfigValue: function(category, setting, value) {
|
setSamlConfigValue: function(category, setting, value) {
|
||||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.setSamlConfigValue, this, category, setting, value));
|
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.setSamlConfigValue, this, category, setting, value));
|
||||||
|
@ -30,13 +72,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
OC.msg.startSaving('#user-saml-save-indicator');
|
OC.msg.startSaving('#user-saml-save-indicator');
|
||||||
OC.AppConfig.setValue('user_saml', category+'-'+setting, value);
|
OCP.AppConfig.setValue('user_saml', this.getConfigIdentifier() + category + '-' + setting, value);
|
||||||
OC.msg.finishedSaving('#user-saml-save-indicator', {status: 'success', data: {message: t('user_saml', 'Saved')}});
|
OC.msg.finishedSaving('#user-saml-save-indicator', {status: 'success', data: {message: t('user_saml', 'Saved')}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})(OCA);
|
})(OCA);
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
OCA.User_SAML.Admin.init();
|
||||||
// Hide depending on the setup state
|
// Hide depending on the setup state
|
||||||
var type = $('#user-saml').data('type');
|
var type = $('#user-saml').data('type');
|
||||||
if(type !== '') {
|
if(type !== '') {
|
||||||
|
@ -68,6 +111,53 @@ $(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var switchProvider = function(providerId) {
|
||||||
|
$('.account-list li').removeClass('active');
|
||||||
|
$('.account-list li[data-id="' + providerId + '"]').addClass('active');
|
||||||
|
OCA.User_SAML.Admin.currentConfig = providerId;
|
||||||
|
$.get(OC.generateUrl('/apps/user_saml/settings/providerSettings/' + providerId)).done(function(data) {
|
||||||
|
Object.keys(data).forEach(function(category, index){
|
||||||
|
var entries = data[category];
|
||||||
|
Object.keys(entries).forEach(function (configKey) {
|
||||||
|
var element = $('*[data-key="' + configKey + '"]');
|
||||||
|
if ($('#user-saml-' + configKey).length) {
|
||||||
|
element = $('#user-saml-' + configKey);
|
||||||
|
}
|
||||||
|
if ($('[name="' + configKey + '"]').length) {
|
||||||
|
element = $('[name="' + configKey + '"]');
|
||||||
|
}
|
||||||
|
if(element.is('input') && element.prop('type') === 'text') {
|
||||||
|
element.val(entries[configKey])
|
||||||
|
}
|
||||||
|
else if(element.is('textarea')) {
|
||||||
|
element.val(entries[configKey]);
|
||||||
|
}
|
||||||
|
else if(element.prop('type') === 'checkbox') {
|
||||||
|
var value = entries[configKey] === '1' ? '1' : '0';
|
||||||
|
element.val(value);
|
||||||
|
} else {
|
||||||
|
console.log('unable to find element for ' + configKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$('input:checkbox[value="1"]').attr('checked', true);
|
||||||
|
$('input:checkbox[value="0"]').attr('checked', false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$('.account-list').on('click', 'li:not(.add-provider)', function() {
|
||||||
|
var providerId = '' + $(this).data('id');
|
||||||
|
switchProvider(providerId);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.account-list .add-provider').on('click', function() {
|
||||||
|
OCA.User_SAML.Admin.addProvider(function (nextId) {
|
||||||
|
$('<li data-id="' + nextId + '"><a>' + t('user_saml', 'Provider') + ' ' + nextId + '</a></li>').insertBefore('.account-list .add-provider');
|
||||||
|
switchProvider(nextId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Enable tabs
|
// Enable tabs
|
||||||
$('input:checkbox[value="1"]').attr('checked', true);
|
$('input:checkbox[value="1"]').attr('checked', true);
|
||||||
|
|
||||||
|
@ -105,6 +195,13 @@ $(function() {
|
||||||
var key = $(this).attr('name');
|
var key = $(this).attr('name');
|
||||||
OCA.User_SAML.Admin.setSamlConfigValue('general', key, $(this).val());
|
OCA.User_SAML.Admin.setSamlConfigValue('general', key, $(this).val());
|
||||||
}
|
}
|
||||||
|
if(el.data('key') === 'idp0_display_name') {
|
||||||
|
if ($(this).val() !== '') {
|
||||||
|
$('.account-list li[data-id=' + OCA.User_SAML.Admin.currentConfig + '] a').text($(this).val())
|
||||||
|
} else {
|
||||||
|
$('.account-list li[data-id=' + OCA.User_SAML.Admin.currentConfig + '] a').text(t('user_saml', 'Provider') + ' ' + OCA.User_SAML.Admin.currentConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#user-saml-general input[type="checkbox"]').change(function(e) {
|
$('#user-saml-general input[type="checkbox"]').change(function(e) {
|
||||||
|
|
81
lib/Controller/SettingsController.php
Normal file
81
lib/Controller/SettingsController.php
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||||
|
*
|
||||||
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\User_SAML\Controller;
|
||||||
|
|
||||||
|
use OCA\User_SAML\Settings\Admin;
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\IConfig;
|
||||||
|
use OCP\IRequest;
|
||||||
|
|
||||||
|
class SettingsController extends Controller {
|
||||||
|
|
||||||
|
/** @var IConfig */
|
||||||
|
private $config;
|
||||||
|
/** @var Admin */
|
||||||
|
private $admin;
|
||||||
|
|
||||||
|
public function __construct($appName,
|
||||||
|
IRequest $request,
|
||||||
|
IConfig $config,
|
||||||
|
Admin $admin) {
|
||||||
|
parent::__construct($appName, $request);
|
||||||
|
$this->config = $config;
|
||||||
|
$this->admin = $admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $providerId
|
||||||
|
* @return array of categories containing entries for each config parameter with their value
|
||||||
|
*/
|
||||||
|
public function getSamlProviderSettings($providerId) {
|
||||||
|
/**
|
||||||
|
* This uses the list of available config parameters from the admin section
|
||||||
|
* and extends it with fields that are not coming from \OCA\User_SAML\Settings\Admin
|
||||||
|
*/
|
||||||
|
$params = $this->admin->getForm()->getParams();
|
||||||
|
$params['idp'] = [
|
||||||
|
'singleLogoutService.url' => null,
|
||||||
|
'singleSignOnService.url' => null,
|
||||||
|
'idp-entityId' => null,
|
||||||
|
];
|
||||||
|
/* Fetch all config values for the given providerId */
|
||||||
|
$settings = [];
|
||||||
|
foreach ($params as $category => $content) {
|
||||||
|
if (empty($content) || $category === 'providers') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($content as $setting => $details) {
|
||||||
|
$prefix = $providerId === '1' ? '' : $providerId . '-';
|
||||||
|
$key = $prefix . $category . '-' . $setting;
|
||||||
|
/* use security as category instead of security-* */
|
||||||
|
if (strpos($category, 'security-') === 0) {
|
||||||
|
$category = 'security';
|
||||||
|
}
|
||||||
|
$settings[$category][$setting] = $this->config->getAppValue('user_saml', $key, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -54,6 +54,13 @@ class Admin implements ISettings {
|
||||||
* @return TemplateResponse
|
* @return TemplateResponse
|
||||||
*/
|
*/
|
||||||
public function getForm() {
|
public function getForm() {
|
||||||
|
$providerIds = explode(',', $this->config->getAppValue('user_saml', 'providerIds', '1'));
|
||||||
|
$providers = [];
|
||||||
|
foreach ($providerIds as $id) {
|
||||||
|
$prefix = $id === '1' ? '' : $id .'-';
|
||||||
|
$name = $this->config->getAppValue('user_saml', $prefix . 'general-idp0_display_name', '');
|
||||||
|
$providers[$id] = $name === '' ? $this->l10n->t('Provider ') . $id : $name;
|
||||||
|
}
|
||||||
$serviceProviderFields = [
|
$serviceProviderFields = [
|
||||||
'x509cert' => $this->l10n->t('X.509 certificate of the Service Provider'),
|
'x509cert' => $this->l10n->t('X.509 certificate of the Service Provider'),
|
||||||
'privateKey' => $this->l10n->t('Private key of the Service Provider'),
|
'privateKey' => $this->l10n->t('Private key of the Service Provider'),
|
||||||
|
@ -135,6 +142,7 @@ class Admin implements ISettings {
|
||||||
'general' => $generalSettings,
|
'general' => $generalSettings,
|
||||||
'attributeMappings' => $attributeMappingSettings,
|
'attributeMappings' => $attributeMappingSettings,
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
|
'providers' => $providers
|
||||||
];
|
];
|
||||||
|
|
||||||
return new TemplateResponse('user_saml', 'admin', $params);
|
return new TemplateResponse('user_saml', 'admin', $params);
|
||||||
|
|
|
@ -10,6 +10,29 @@ style('user_saml', 'admin');
|
||||||
title="<?php p($l->t('Open documentation'));?>"
|
title="<?php p($l->t('Open documentation'));?>"
|
||||||
href="<?php p(link_to_docs('admin-sso')); ?>"></a>
|
href="<?php p(link_to_docs('admin-sso')); ?>"></a>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="warning hidden" id="user-saml-warning-admin-user">
|
||||||
|
<?php p(
|
||||||
|
$l->t(
|
||||||
|
'Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account won\'t be possible anymore, unless you enabled "%s"',
|
||||||
|
[
|
||||||
|
$theme->getEntity(),
|
||||||
|
$_['general']['allow_multiple_user_back_ends']['text']
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="account-list">
|
||||||
|
<?php foreach ($_['providers'] as $id => $name) { ?>
|
||||||
|
<li data-id="<?php p($id); ?>" class="<?php if ((string)$id === '1') { p('active'); } ?>">
|
||||||
|
<a href="#"><?php p($name); ?></a>
|
||||||
|
</li>
|
||||||
|
<?php } ?>
|
||||||
|
<li class="add-provider"><a href="#" class="button"><span class="icon-add"></span> Add another account</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div id="user-saml-save-indicator" class="msg success inlineblock" style="display: none;">Saved</div>
|
<div id="user-saml-save-indicator" class="msg success inlineblock" style="display: none;">Saved</div>
|
||||||
|
|
||||||
<div id="user-saml-settings">
|
<div id="user-saml-settings">
|
||||||
|
@ -20,18 +43,6 @@ style('user_saml', 'admin');
|
||||||
<button id="user-saml-choose-env"><?php p($l->t('Use environment variable')) ?></button>
|
<button id="user-saml-choose-env"><?php p($l->t('Use environment variable')) ?></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="warning hidden" id="user-saml-warning-admin-user">
|
|
||||||
<?php p(
|
|
||||||
$l->t(
|
|
||||||
'Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account won\'t be possible anymore, unless you enabled "%s"',
|
|
||||||
[
|
|
||||||
$theme->getEntity(),
|
|
||||||
$_['general']['allow_multiple_user_back_ends']['text']
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="user-saml-general">
|
<div id="user-saml-general">
|
||||||
<h3><?php p($l->t('General')) ?></h3>
|
<h3><?php p($l->t('General')) ?></h3>
|
||||||
|
|
Loading…
Reference in a new issue