mirror of
https://github.com/netzbegruenung/user_saml.git
synced 2024-05-11 13:16:06 +02:00
Add support for mapping attributes
This adds support for mapping attributes for full name and email Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
This commit is contained in:
parent
e8e3a513a3
commit
1a1a11c8e9
|
@ -42,7 +42,8 @@ $userBackend = new \OCA\User_SAML\UserBackend(
|
|||
$config,
|
||||
$urlGenerator,
|
||||
\OC::$server->getSession(),
|
||||
\OC::$server->getDatabaseConnection()
|
||||
\OC::$server->getDatabaseConnection(),
|
||||
\OC::$server->getUserManager()
|
||||
);
|
||||
$userBackend->registerBackends(\OC::$server->getUserManager()->getBackends());
|
||||
OC_User::useBackend($userBackend);
|
||||
|
|
26
js/admin.js
26
js/admin.js
|
@ -53,6 +53,10 @@ $(function() {
|
|||
$('#user-saml-settings .button').addClass('hidden');
|
||||
}
|
||||
|
||||
if($('#user-saml-general-require_provisioned_account').val() === '0') {
|
||||
$('#user-saml-attribute-mapping').toggleClass('hidden');
|
||||
}
|
||||
|
||||
$('#user-saml-choose-saml').click(function(e) {
|
||||
e.preventDefault();
|
||||
OCA.User_SAML.Admin.chooseSaml();
|
||||
|
@ -110,6 +114,9 @@ $(function() {
|
|||
} else {
|
||||
$(this).val("0");
|
||||
}
|
||||
if(key === 'require_provisioned_account') {
|
||||
$('#user-saml-attribute-mapping').toggleClass('hidden');
|
||||
}
|
||||
OCA.User_SAML.Admin.setSamlConfigValue('general', key, $(this).val());
|
||||
});
|
||||
});
|
||||
|
@ -127,6 +134,18 @@ $(function() {
|
|||
});
|
||||
});
|
||||
|
||||
$('#user-saml-attribute-mapping input[type="text"], #user-saml-attribute-mapping textarea').change(function(e) {
|
||||
var el = $(this);
|
||||
$.when(el.focusout()).then(function() {
|
||||
var key = $(this).attr('name');
|
||||
OCA.User_SAML.Admin.setSamlConfigValue('saml-attribute-mapping', key, $(this).val());
|
||||
});
|
||||
if (e.keyCode === 13) {
|
||||
var key = $(this).attr('name');
|
||||
OCA.User_SAML.Admin.setSamlConfigValue('saml-attribute-mapping', key, $(this).val());
|
||||
}
|
||||
});
|
||||
|
||||
$('#user-saml').change(function() {
|
||||
if(type === 'saml') {
|
||||
// Checks on each request whether the settings make sense or not
|
||||
|
@ -172,6 +191,13 @@ $(function() {
|
|||
text = 'Show Service Provider settings ...';
|
||||
}
|
||||
break;
|
||||
case 'user-saml-attribute-mapping':
|
||||
if (nextSibling.hasClass('hidden')) {
|
||||
text = 'Hide attribute mapping settings ...';
|
||||
} else {
|
||||
text = 'Show attribute mapping settings ...';
|
||||
}
|
||||
break;
|
||||
}
|
||||
el.html(t('user_saml', text));
|
||||
|
||||
|
|
|
@ -99,15 +99,19 @@ class SAMLController extends Controller {
|
|||
}
|
||||
|
||||
$userExists = $this->userManager->userExists($uid);
|
||||
$autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed();
|
||||
if($userExists === true) {
|
||||
if($autoProvisioningAllowed) {
|
||||
$this->userBackend->updateAttributes($uid, $auth);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed();
|
||||
if(!$userExists && !$autoProvisioningAllowed) {
|
||||
throw new NoUserFoundException();
|
||||
} elseif(!$userExists && $autoProvisioningAllowed) {
|
||||
$this->userBackend->createUserIfNotExists($uid);
|
||||
$this->userBackend->updateAttributes($uid, $auth);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,18 @@ class Admin implements ISettings {
|
|||
'type' => 'checkbox',
|
||||
],
|
||||
];
|
||||
$attributeMappingSettings = [
|
||||
'displayName_mapping' => [
|
||||
'text' => $this->l10n->t('Attribute to map the displayname to.'),
|
||||
'type' => 'line',
|
||||
'required' => true,
|
||||
],
|
||||
'email_mapping' => [
|
||||
'text' => $this->l10n->t('Attribute to map the email address to.'),
|
||||
'type' => 'line',
|
||||
'required' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$type = $this->config->getAppValue('user_saml', 'type');
|
||||
if($type === 'saml') {
|
||||
|
@ -102,6 +114,7 @@ class Admin implements ISettings {
|
|||
'security-required' => $securityRequiredFields,
|
||||
'security-general' => $securityGeneral,
|
||||
'general' => $generalSettings,
|
||||
'attributeMappings' => $attributeMappingSettings,
|
||||
'type' => $type,
|
||||
];
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace OCA\User_SAML;
|
|||
use OCP\Authentication\IApacheBackend;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserManager;
|
||||
use OCP\UserInterface;
|
||||
use OCP\IUserBackend;
|
||||
use OCP\IConfig;
|
||||
|
@ -39,6 +40,8 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
private $session;
|
||||
/** @var IDBConnection */
|
||||
private $db;
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
/** @var \OCP\UserInterface[] */
|
||||
private $backends;
|
||||
|
||||
|
@ -47,15 +50,18 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
* @param IURLGenerator $urlGenerator
|
||||
* @param ISession $session
|
||||
* @param IDBConnection $db
|
||||
* @param IUserManager $userManager
|
||||
*/
|
||||
public function __construct(IConfig $config,
|
||||
IURLGenerator $urlGenerator,
|
||||
ISession $session,
|
||||
IDBConnection $db) {
|
||||
IDBConnection $db,
|
||||
IUserManager $userManager) {
|
||||
$this->config = $config;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->session = $session;
|
||||
$this->db = $db;
|
||||
$this->userManager = $userManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,8 +115,14 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
* @since 4.5.0
|
||||
*/
|
||||
public function implementsActions($actions) {
|
||||
return (bool)((\OC_User_Backend::CHECK_PASSWORD)
|
||||
& $actions);
|
||||
$availableActions = \OC_User_Backend::CHECK_PASSWORD;
|
||||
if($this->autoprovisionAllowed()
|
||||
&& $this->config->getAppValue('user_saml', 'saml-attribute-mapping-displayName_mapping', '') !== '') {
|
||||
|
||||
$availableActions |= \OC_User_Backend::GET_DISPLAYNAME;
|
||||
}
|
||||
|
||||
return (bool)($availableActions & $actions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,13 +219,48 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
}
|
||||
}
|
||||
|
||||
public function setDisplayName($uid, $displayName) {
|
||||
if($backend = $this->getActualUserBackend($uid)) {
|
||||
return $backend->setDisplayName($uid, $displayName);
|
||||
}
|
||||
|
||||
if ($this->userExistsInDatabase($uid)) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->update('user_saml_users')
|
||||
->set('displayname', $qb->createNamedParameter($displayName))
|
||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
|
||||
->execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get display name of the user
|
||||
* Get display name of the user
|
||||
*
|
||||
* @param string $uid user ID of the user
|
||||
* @return string display name
|
||||
* @since 4.5.0
|
||||
*/
|
||||
public function getDisplayName($uid) {
|
||||
if($backend = $this->getActualUserBackend($uid)) {
|
||||
return $backend->getDisplayName($uid);
|
||||
} else {
|
||||
if($this->userExistsInDatabase($uid)) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('displayname')
|
||||
->from('user_saml_users')
|
||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
|
||||
->setMaxResults(1);
|
||||
$result = $qb->execute();
|
||||
$users = $result->fetchAll();
|
||||
if (isset($users[0]['displayname'])) {
|
||||
return $users[0]['displayname'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -233,6 +280,9 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
->where(
|
||||
$qb->expr()->iLike('uid', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($search) . '%'))
|
||||
)
|
||||
->orWhere(
|
||||
$qb->expr()->iLike('displayname', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($search) . '%'))
|
||||
)
|
||||
->setMaxResults($limit);
|
||||
if($offset !== null) {
|
||||
$qb->setFirstResult($offset);
|
||||
|
@ -360,4 +410,58 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
|
|||
$this->backends = $backends;
|
||||
}
|
||||
|
||||
private function getAttributeValue($name, array $attributes) {
|
||||
$keys = explode(' ', $this->config->getAppValue('user_saml', $name, ''));
|
||||
|
||||
if(count($keys) === 1 && $keys[1] === '') {
|
||||
throw new \InvalidArgumentException('Attribute is not configured');
|
||||
}
|
||||
|
||||
$value = '';
|
||||
foreach($keys as $key) {
|
||||
if (isset($attributes[$key])) {
|
||||
if (is_array($attributes[$key])) {
|
||||
if($value !== '') {
|
||||
$value .= ' ';
|
||||
}
|
||||
$value .= $attributes[$key][0];
|
||||
} else {
|
||||
if($value !== '') {
|
||||
$value .= ' ';
|
||||
}
|
||||
$value .= $attributes[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function updateAttributes($uid,
|
||||
array $attributes) {
|
||||
$user = $this->userManager->get($uid);
|
||||
try {
|
||||
$newEmail = $this->getAttributeValue('saml-attribute-mapping-email_mapping', $attributes);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$newEmail = null;
|
||||
}
|
||||
try {
|
||||
$newDisplayname = $this->getAttributeValue('saml-attribute-mapping-displayName_mapping', $attributes);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$newDisplayname = null;
|
||||
}
|
||||
|
||||
if ($user !== null) {
|
||||
$currentEmail = (string)$user->getEMailAddress();
|
||||
if ($newEmail !== null
|
||||
&& $currentEmail !== $newEmail) {
|
||||
$user->setEMailAddress($newEmail);
|
||||
}
|
||||
$currentDisplayname = (string)$this->getDisplayName($uid);
|
||||
if($newDisplayname !== null
|
||||
&& $currentDisplayname !== $newDisplayname) {
|
||||
$this->setDisplayName($uid, $newDisplayname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,26 @@ style('user_saml', 'admin');
|
|||
<p><textarea name="x509cert" placeholder="<?php p($l->t('Public X.509 certificate of the IdP')) ?>"><?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'idp-x509cert', '')) ?></textarea></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="user-saml-attribute-mapping" class="hidden">
|
||||
<h3><?php p($l->t('Attribute mapping')) ?></h3>
|
||||
<p>
|
||||
<?php print_unescaped($l->t('If you want to optionally map SAML attributes to the user you can configure these here.')) ?>
|
||||
<span class="toggle"><?php p($l->t('Show attribute mapping settings ...')) ?></span>
|
||||
</p>
|
||||
|
||||
<div class="hidden">
|
||||
<?php foreach($_['attributeMappings'] as $key => $attribute): ?>
|
||||
<?php
|
||||
if($attribute['type'] === 'line'): ?>
|
||||
<p>
|
||||
<input name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'saml-attribute-mapping-'.$key, '')) ?>" type="text" <?php if(isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="user-saml-security">
|
||||
<h3><?php p($l->t('Security settings')) ?></h3>
|
||||
<p>
|
||||
|
|
|
@ -6,7 +6,7 @@ Feature: EnvironmentVariable
|
|||
And The environment variable "REMOTE_USER" is set to "not-provisioned-user"
|
||||
When I send a GET request to "http://localhost/index.php/login"
|
||||
Then I should be redirected to "http://localhost/index.php/apps/files/"
|
||||
Then I should be logged-in to Nextcloud as user "not-provisioned-user"
|
||||
Then The user value "id" should be "not-provisioned-user"
|
||||
|
||||
Scenario: Authenticating using environment variable with SSO and successful check if user exists on backend
|
||||
Given A local user with uid "provisioned-user" exists
|
||||
|
@ -16,7 +16,7 @@ Feature: EnvironmentVariable
|
|||
And The environment variable "REMOTE_USER" is set to "provisioned-user"
|
||||
When I send a GET request to "http://localhost/index.php/login"
|
||||
Then I should be redirected to "http://localhost/index.php/apps/files/"
|
||||
Then I should be logged-in to Nextcloud as user "provisioned-user"
|
||||
Then The user value "id" should be "provisioned-user"
|
||||
|
||||
Scenario: Authenticating using environment variable with SSO and unsuccessful check if user exists on backend
|
||||
Given The setting "type" is set to "environment-variable"
|
||||
|
|
|
@ -18,7 +18,7 @@ Feature: Shibboleth
|
|||
|student1 |password | |
|
||||
And The response should be a SAML redirect page that gets submitted
|
||||
And I should be redirected to "http://localhost/index.php/apps/files/"
|
||||
And I should be logged-in to Nextcloud as user "student1"
|
||||
And The user value "id" should be "student1"
|
||||
|
||||
Scenario: Authenticating using Shibboleth with SAML and check if user exists on backend and not existing user
|
||||
Given The setting "type" is set to "saml"
|
||||
|
@ -50,6 +50,7 @@ Feature: Shibboleth
|
|||
And The setting "idp-x509cert" is set to "MIIDnTCCAoWgAwIBAgIUGPx9uPjCu7c172IUgV84Tm94pBcwDQYJKoZIhvcNAQEL BQAwNzE1MDMGA1UEAwwsc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xvdWQu bG9jYWxkb21haW4wHhcNMTcwMTA0MTAxMTI3WhcNMzcwMTA0MTAxMTI3WjA3MTUw MwYDVQQDDCxzaGliYm9sZXRoLWludGVncmF0aW9uLW5leHRjbG91ZC5sb2NhbGRv bWFpbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH+bPu45tk8/JRk XOxkyfbxocWZlY4mRumEUxscd3fn0oVzOrdWbHH7lCZV4bus4KxvJljc0Nm2K+Zr LoiRUUnf/LQ4LlehWVm5Kbc4kRgOXS0iGZN3SslAWPKyIg0tywg+TLOBPoS6EtST 1WuYg1JPMFxPfeFDWQ0dQYPlXIJWBFh6F2JMTb0FLECqA5l/ryYE13QisX5l+Mqo 6y3Dh7qIgaH0IJNobXoAcEWza7Kb2RnfhZRh9e0qjZIwBqTJUFM/6I86RYXn829s INUvYQQbez6VkGTdUQJ/GuXb/dD5sMQfOyK8hrRY5MozOmK32cz3JaAzSXpiSRS9 NxFwvicCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUKn8+TV0WXSDeavvF0M8mWn1o8ukw fAYDVR0RBHUwc4Isc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xvdWQubG9j YWxkb21haW6GQ2h0dHBzOi8vc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xv dWQubG9jYWxkb21haW4vaWRwL3NoaWJib2xldGgwDQYJKoZIhvcNAQELBQADggEB ABI6uzoIeLZT9Az2KTlLxIc6jZ4MDmhaVja4ZuBxTXEb7BFLfeASEJmQm1wgIMOn pJId3Kh3njW+3tOBWKm7lj8JxVVpAu4yMFSoQGPaVUgYB1AVm+pmAyPLzfJ/XGhf esCU2F/b0eHWcaIb3x+BZFX089Cd/PBtP84MNXdo+TccibxC8N39sr45qJM/7SC7 TfDYU0L4q2WZHJr4S7+0F+F4KaxLx9NzCvN4h6XaoWofZWir2iHO4NzbrVQGC0ei QybS/neBfni4A2g1lyzCb6xFB58JBvNCn7AAnDJULOE7S5XWUKsDAQVQrxTNkUq7 pnhlCQqZDwUdgmIXd1KB1So="
|
||||
And The setting "security-authnRequestsSigned" is set to "1"
|
||||
And The setting "security-wantAssertionsEncrypted" is set to "1"
|
||||
And The setting "saml-attribute-mapping-email_mapping" is set to "urn:oid:0.9.2342.19200300.100.1.3"
|
||||
And The setting "sp-x509cert" is set to "-----BEGIN CERTIFICATE-----MIIC+zCCAeOgAwIBAgIJAIgZuvWDBIrdMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzAxMDQxMTM5MjFaFw0yNzAxMDIxMTM5MjFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3ESWaDH1JiJTy9yRJQV7kahPOxgBkIH2xwcYDL1k9deKNhSKLx7aGfxE244+HBcC6WLHKVUnOm0ld2qxQ4bMYiJXzZuqL67r07L5wxGAssv12lO92qohGmlHy3+VzRYUBmovu6upqOv3R2F8HBbo7Jc7Hvt7hOEJn/jPuFuF/fHit3mqU8l6IkrIZjpaW8T9fIWOXRq98U4+hkgWpqEZWsqlfE8BxAs9DeIMZab0GxO9stHLp+GYKx10uE4ezFcaDS8W+g2C8enCTt1HXGvcnj4o5zkC1lITGvcFTsiFqfIWyXeSufcxdc0W7HoG6J3ks0WJyK38sfFn0t2Ao6kX0CAwEAAaNQME4wHQYDVR0OBBYEFAoJzX6TVYAwC1GSPe6nObBG54zaMB8GA1UdIwQYMBaAFAoJzX6TVYAwC1GSPe6nObBG54zaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJia9R70uXdUZtgujUPjLas4+sVajzlBFmqhBqpLAo934vljf9HISsHrPtdBcbS0d0rucqXwabDf0MlR18ksnT/NYpsTwMbMx76CrXi4zYEEW5lISKEO65aIkzVTcqKWSuhjtSnRdB6iOLsFiKmNMWXaIKMR5T0+AbR9wdQgn08W+3EEeHGvafVQfE3STVsSgNb1ft7DvcSUnfPXGU7KzvmTpZa0Hfmc7uY4vpdEEhLAdRhgLReS7USZskov7ooiPSoD+JRFi2gM4klBxTemHdNUa9oFnHMXuYKOkLbkgFvHxyy+QlLq2ELQTga5e7I83ZyOfGctyf8Ul6vGw10vbQ=-----END CERTIFICATE-----"
|
||||
And The setting "sp-privateKey" is set to "-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA3cRJZoMfUmIlPL3JElBXuRqE87GAGQgfbHBxgMvWT114o2FIovHtoZ/ETbjj4cFwLpYscpVSc6bSV3arFDhsxiIlfNm6ovruvTsvnDEYCyy/XaU73aqiEaaUfLf5XNFhQGai+7q6mo6/dHYXwcFujslzse+3uE4Qmf+M+4W4X98eK3eapTyXoiSshmOlpbxP18hY5dGr3xTj6GSBamoRlayqV8TwHECz0N4gxlpvQbE72y0cun4ZgrHXS4Th7MVxoNLxb6DYLx6cJO3Udca9yePijnOQLWUhMa9wVOyIWp8hbJd5K59zF1zRbsegboneSzRYnIrfyx8WfS3YCjqRfQIDAQABAoIBAQC5CQAdcqZ9vLpJNilBCJxJLCFmm+HAAREHD8MErg9A5UK1P4S1wJp/0qieGPi68wXBOTgY2xKSwMycgb04/+NyZidVRu388takOW/+KNBg8pMxdZ6/05GqnI0kivSbR3CXpYuz8hekwhpo9+fWmKjApsHL47ItK6WaeKmPbAFsq1YJGzfp/DXg7LIvh9GA3C1LWWGV7SuCGOyX/2Moi8xRa7qBtH4hDo/0NRhTx7zjYjlBgNEr330pJUopc3+AtHE40R+xMr2zkGvq9RsCZxYxD2VWbLwQW0yNjWmQ2OTuMgJJvk2+N73QLHcB+tea82ZTszsNzRS9DLtc6qbsKEPZAoGBAO78U3vEuRyY56f/1hpo0xuCDwOkWGzgBQWkjJl6dlyVz/zKkhXBHpEYImyt8XRN0W3iGZYpZ2hCFJGTcDp32R6UiEyGLz0Uc8R/tva/TiRVW1FdNczzSHcB24b9OMK4vE9JLs8mA8Rp8YBgtLr5DDuMfYt/a/rZJbg/HIfIN98nAoGBAO2OInCX93t2I6zzRPIqKtI6q6FYNp64VIQjvw9Y8l0x3IdJZRP9H5C8ZhCeYPsgEqTXcXa4j5hL4rQzoUtxfxflBUUH60bcnd4LGaTCMYLS14G011E3GZlIP0sJi5OjEhy8fq3zt6jVzS9V/lPHB8i+w1D7CbPrMpW7B3k32vC7AoGAX/HvdkYhZyjAAEOG6m1hK68IZhbp5TP+8CgCxm9S65K9wKh3A8LXibrdvzIKOP4w8WOPkCipOkMlTNibeu24vj01hztr5aK7Y40+oEtnjNCz67N3MQQO+LBHOSeaTRqrh01DPKjvZECAU2D/zfzEe3fIw2Nxr3DUYub7hkvMmosCgYAzxbVVypjiLGYsDDyrdmsstCKxoDMPNmcdAVljc+QmUXaZeXJw/8qAVb78wjeqo1vM1zNgR2rsKyW2VkZB1fN39q7GU6qAIBa7zLmDAduegmr7VrlSduq6UFeS9/qWa4TIBICrUqFlR2tXdKtgANF+e6y/mmaL8qdsoH1JetXZfwKBgQC1vscRpdAXivjOOZAh+mzJWzS4BUl4CTJLYYIuOEXikmN5g0EdV2fhUEdkewmyKnXHsd0x83167bYgpTDNs71jUxDHy5NXlg2qIjLkf09X9wr19gBzDApfWzfh3vUqttyMZuQMLVNepGCWM2vjlY9KGl5OvZqY6d+7yO0mLV9GmQ==-----END RSA PRIVATE KEY-----"
|
||||
And The setting "security-wantAssertionsSigned" is set to "1"
|
||||
|
@ -60,4 +61,29 @@ Feature: Shibboleth
|
|||
|student1 |password | |
|
||||
And The response should be a SAML redirect page that gets submitted
|
||||
And I should be redirected to "http://localhost/index.php/apps/files/"
|
||||
And I should be logged-in to Nextcloud as user "student1"
|
||||
Then The user value "id" should be "student1"
|
||||
Then The user value "email" should be ""
|
||||
|
||||
Scenario: Authenticating using Shibboleth with SAML in provisioning mode and custom mapped attributes
|
||||
Given The setting "type" is set to "saml"
|
||||
And The setting "general-uid_mapping" is set to "urn:oid:0.9.2342.19200300.100.1.1"
|
||||
And The setting "idp-entityId" is set to "https://shibboleth-integration-nextcloud.localdomain/idp/shibboleth"
|
||||
And The setting "idp-singleSignOnService.url" is set to "https://localhost:4443/idp/profile/SAML2/Redirect/SSO"
|
||||
And The setting "idp-x509cert" is set to "MIIDnTCCAoWgAwIBAgIUGPx9uPjCu7c172IUgV84Tm94pBcwDQYJKoZIhvcNAQEL BQAwNzE1MDMGA1UEAwwsc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xvdWQu bG9jYWxkb21haW4wHhcNMTcwMTA0MTAxMTI3WhcNMzcwMTA0MTAxMTI3WjA3MTUw MwYDVQQDDCxzaGliYm9sZXRoLWludGVncmF0aW9uLW5leHRjbG91ZC5sb2NhbGRv bWFpbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH+bPu45tk8/JRk XOxkyfbxocWZlY4mRumEUxscd3fn0oVzOrdWbHH7lCZV4bus4KxvJljc0Nm2K+Zr LoiRUUnf/LQ4LlehWVm5Kbc4kRgOXS0iGZN3SslAWPKyIg0tywg+TLOBPoS6EtST 1WuYg1JPMFxPfeFDWQ0dQYPlXIJWBFh6F2JMTb0FLECqA5l/ryYE13QisX5l+Mqo 6y3Dh7qIgaH0IJNobXoAcEWza7Kb2RnfhZRh9e0qjZIwBqTJUFM/6I86RYXn829s INUvYQQbez6VkGTdUQJ/GuXb/dD5sMQfOyK8hrRY5MozOmK32cz3JaAzSXpiSRS9 NxFwvicCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUKn8+TV0WXSDeavvF0M8mWn1o8ukw fAYDVR0RBHUwc4Isc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xvdWQubG9j YWxkb21haW6GQ2h0dHBzOi8vc2hpYmJvbGV0aC1pbnRlZ3JhdGlvbi1uZXh0Y2xv dWQubG9jYWxkb21haW4vaWRwL3NoaWJib2xldGgwDQYJKoZIhvcNAQELBQADggEB ABI6uzoIeLZT9Az2KTlLxIc6jZ4MDmhaVja4ZuBxTXEb7BFLfeASEJmQm1wgIMOn pJId3Kh3njW+3tOBWKm7lj8JxVVpAu4yMFSoQGPaVUgYB1AVm+pmAyPLzfJ/XGhf esCU2F/b0eHWcaIb3x+BZFX089Cd/PBtP84MNXdo+TccibxC8N39sr45qJM/7SC7 TfDYU0L4q2WZHJr4S7+0F+F4KaxLx9NzCvN4h6XaoWofZWir2iHO4NzbrVQGC0ei QybS/neBfni4A2g1lyzCb6xFB58JBvNCn7AAnDJULOE7S5XWUKsDAQVQrxTNkUq7 pnhlCQqZDwUdgmIXd1KB1So="
|
||||
And The setting "security-authnRequestsSigned" is set to "1"
|
||||
And The setting "security-wantAssertionsEncrypted" is set to "1"
|
||||
And The setting "sp-x509cert" is set to "-----BEGIN CERTIFICATE-----MIIC+zCCAeOgAwIBAgIJAIgZuvWDBIrdMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzAxMDQxMTM5MjFaFw0yNzAxMDIxMTM5MjFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3ESWaDH1JiJTy9yRJQV7kahPOxgBkIH2xwcYDL1k9deKNhSKLx7aGfxE244+HBcC6WLHKVUnOm0ld2qxQ4bMYiJXzZuqL67r07L5wxGAssv12lO92qohGmlHy3+VzRYUBmovu6upqOv3R2F8HBbo7Jc7Hvt7hOEJn/jPuFuF/fHit3mqU8l6IkrIZjpaW8T9fIWOXRq98U4+hkgWpqEZWsqlfE8BxAs9DeIMZab0GxO9stHLp+GYKx10uE4ezFcaDS8W+g2C8enCTt1HXGvcnj4o5zkC1lITGvcFTsiFqfIWyXeSufcxdc0W7HoG6J3ks0WJyK38sfFn0t2Ao6kX0CAwEAAaNQME4wHQYDVR0OBBYEFAoJzX6TVYAwC1GSPe6nObBG54zaMB8GA1UdIwQYMBaAFAoJzX6TVYAwC1GSPe6nObBG54zaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJia9R70uXdUZtgujUPjLas4+sVajzlBFmqhBqpLAo934vljf9HISsHrPtdBcbS0d0rucqXwabDf0MlR18ksnT/NYpsTwMbMx76CrXi4zYEEW5lISKEO65aIkzVTcqKWSuhjtSnRdB6iOLsFiKmNMWXaIKMR5T0+AbR9wdQgn08W+3EEeHGvafVQfE3STVsSgNb1ft7DvcSUnfPXGU7KzvmTpZa0Hfmc7uY4vpdEEhLAdRhgLReS7USZskov7ooiPSoD+JRFi2gM4klBxTemHdNUa9oFnHMXuYKOkLbkgFvHxyy+QlLq2ELQTga5e7I83ZyOfGctyf8Ul6vGw10vbQ=-----END CERTIFICATE-----"
|
||||
And The setting "sp-privateKey" is set to "-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA3cRJZoMfUmIlPL3JElBXuRqE87GAGQgfbHBxgMvWT114o2FIovHtoZ/ETbjj4cFwLpYscpVSc6bSV3arFDhsxiIlfNm6ovruvTsvnDEYCyy/XaU73aqiEaaUfLf5XNFhQGai+7q6mo6/dHYXwcFujslzse+3uE4Qmf+M+4W4X98eK3eapTyXoiSshmOlpbxP18hY5dGr3xTj6GSBamoRlayqV8TwHECz0N4gxlpvQbE72y0cun4ZgrHXS4Th7MVxoNLxb6DYLx6cJO3Udca9yePijnOQLWUhMa9wVOyIWp8hbJd5K59zF1zRbsegboneSzRYnIrfyx8WfS3YCjqRfQIDAQABAoIBAQC5CQAdcqZ9vLpJNilBCJxJLCFmm+HAAREHD8MErg9A5UK1P4S1wJp/0qieGPi68wXBOTgY2xKSwMycgb04/+NyZidVRu388takOW/+KNBg8pMxdZ6/05GqnI0kivSbR3CXpYuz8hekwhpo9+fWmKjApsHL47ItK6WaeKmPbAFsq1YJGzfp/DXg7LIvh9GA3C1LWWGV7SuCGOyX/2Moi8xRa7qBtH4hDo/0NRhTx7zjYjlBgNEr330pJUopc3+AtHE40R+xMr2zkGvq9RsCZxYxD2VWbLwQW0yNjWmQ2OTuMgJJvk2+N73QLHcB+tea82ZTszsNzRS9DLtc6qbsKEPZAoGBAO78U3vEuRyY56f/1hpo0xuCDwOkWGzgBQWkjJl6dlyVz/zKkhXBHpEYImyt8XRN0W3iGZYpZ2hCFJGTcDp32R6UiEyGLz0Uc8R/tva/TiRVW1FdNczzSHcB24b9OMK4vE9JLs8mA8Rp8YBgtLr5DDuMfYt/a/rZJbg/HIfIN98nAoGBAO2OInCX93t2I6zzRPIqKtI6q6FYNp64VIQjvw9Y8l0x3IdJZRP9H5C8ZhCeYPsgEqTXcXa4j5hL4rQzoUtxfxflBUUH60bcnd4LGaTCMYLS14G011E3GZlIP0sJi5OjEhy8fq3zt6jVzS9V/lPHB8i+w1D7CbPrMpW7B3k32vC7AoGAX/HvdkYhZyjAAEOG6m1hK68IZhbp5TP+8CgCxm9S65K9wKh3A8LXibrdvzIKOP4w8WOPkCipOkMlTNibeu24vj01hztr5aK7Y40+oEtnjNCz67N3MQQO+LBHOSeaTRqrh01DPKjvZECAU2D/zfzEe3fIw2Nxr3DUYub7hkvMmosCgYAzxbVVypjiLGYsDDyrdmsstCKxoDMPNmcdAVljc+QmUXaZeXJw/8qAVb78wjeqo1vM1zNgR2rsKyW2VkZB1fN39q7GU6qAIBa7zLmDAduegmr7VrlSduq6UFeS9/qWa4TIBICrUqFlR2tXdKtgANF+e6y/mmaL8qdsoH1JetXZfwKBgQC1vscRpdAXivjOOZAh+mzJWzS4BUl4CTJLYYIuOEXikmN5g0EdV2fhUEdkewmyKnXHsd0x83167bYgpTDNs71jUxDHy5NXlg2qIjLkf09X9wr19gBzDApfWzfh3vUqttyMZuQMLVNepGCWM2vjlY9KGl5OvZqY6d+7yO0mLV9GmQ==-----END RSA PRIVATE KEY-----"
|
||||
And The setting "security-wantAssertionsSigned" is set to "1"
|
||||
And The setting "saml-attribute-mapping-email_mapping" is set to "urn:oid:0.9.2342.19200300.100.1.3"
|
||||
And The setting "saml-attribute-mapping-displayName_mapping" is set to "urn:oid:2.5.4.42 urn:oid:2.5.4.4"
|
||||
When I send a GET request to "http://localhost/index.php/login"
|
||||
Then I should be redirected to "https://localhost:4443/idp/profile/SAML2/Redirect/SSO"
|
||||
And I send a POST request to "https://localhost:4443/idp/profile/SAML2/Redirect/SSO?execution=e1s1" with the following data
|
||||
|j_username|j_password|_eventId_proceed|
|
||||
|student1 |password | |
|
||||
And The response should be a SAML redirect page that gets submitted
|
||||
And I should be redirected to "http://localhost/index.php/apps/files/"
|
||||
And The user value "id" should be "student1"
|
||||
And The user value "email" should be "student1@idptestbed.edu"
|
||||
And The user value "display-name" should be "Stud Ent"
|
||||
|
|
|
@ -181,10 +181,13 @@ class FeatureContext implements Context {
|
|||
}
|
||||
|
||||
/**
|
||||
* @Then I should be logged-in to Nextcloud as user :userId
|
||||
* @Then The user value :key should be :value
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public function iShouldBeLoggedInToNextcloudAsUser($userId) {
|
||||
public function thUserValueShouldBe($key, $value) {
|
||||
$this->response = $this->client->request(
|
||||
'GET',
|
||||
'http://localhost/ocs/v1.php/cloud/user',
|
||||
|
@ -196,17 +199,24 @@ class FeatureContext implements Context {
|
|||
);
|
||||
|
||||
$xml = simplexml_load_string($this->response->getBody());
|
||||
/** @var array $responseArray */
|
||||
$responseArray = json_decode(json_encode((array)$xml), true);
|
||||
if($responseArray['data']['display-name'] !== $userId) {
|
||||
foreach($responseArray['data'] as $arrayKey => $arrayValue) {
|
||||
if(count($responseArray['data'][$arrayKey]) === 0) {
|
||||
$responseArray['data'][$arrayKey] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$actualValue = $responseArray['data'][$key];
|
||||
if($actualValue !== $value) {
|
||||
throw new UnexpectedValueException(
|
||||
sprintf(
|
||||
'Expected %s as value but got %s',
|
||||
$userId,
|
||||
$responseArray['data']['display-name']
|
||||
$value,
|
||||
$actualValue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,6 +95,18 @@ class AdminTest extends \Test\TestCase {
|
|||
'type' => 'checkbox',
|
||||
],
|
||||
];
|
||||
$attributeMappingSettings = [
|
||||
'displayName_mapping' => [
|
||||
'text' => $this->l10n->t('Attribute to map the displayname to.'),
|
||||
'type' => 'line',
|
||||
'required' => true,
|
||||
],
|
||||
'email_mapping' => [
|
||||
'text' => $this->l10n->t('Attribute to map the email address to.'),
|
||||
'type' => 'line',
|
||||
'required' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$params = [
|
||||
'sp' => $serviceProviderFields,
|
||||
|
@ -102,6 +114,7 @@ class AdminTest extends \Test\TestCase {
|
|||
'security-required' => $securityRequiredFields,
|
||||
'security-general' => $securityGeneral,
|
||||
'general' => $generalSettings,
|
||||
'attributeMappings' => $attributeMappingSettings,
|
||||
];
|
||||
|
||||
return $params;
|
||||
|
|
|
@ -27,6 +27,7 @@ use OCP\IDBConnection;
|
|||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserBackend;
|
||||
use OCP\IUserManager;
|
||||
use Test\TestCase;
|
||||
|
||||
class UserBackendTest extends TestCase {
|
||||
|
@ -38,7 +39,9 @@ class UserBackendTest extends TestCase {
|
|||
private $session;
|
||||
/** @var IDBConnection|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $db;
|
||||
/** @var IUserBackend|\PHPUnit_Framework_MockObject_MockObject */
|
||||
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $userManager;
|
||||
/** @var IUserBackend */
|
||||
private $userBackend;
|
||||
|
||||
public function setUp() {
|
||||
|
@ -48,12 +51,14 @@ class UserBackendTest extends TestCase {
|
|||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->session = $this->createMock(ISession::class);
|
||||
$this->db = $this->createMock(IDBConnection::class);
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
|
||||
$this->userBackend = new UserBackend(
|
||||
$this->config,
|
||||
$this->urlGenerator,
|
||||
$this->session,
|
||||
$this->db
|
||||
$this->db,
|
||||
$this->userManager
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue