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:
Lukas Reschke 2017-02-16 11:47:45 +01:00
parent e8e3a513a3
commit 1a1a11c8e9
No known key found for this signature in database
GPG key ID: B9F6980CF6E759B1
11 changed files with 240 additions and 18 deletions

View file

@ -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);

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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,
];

View file

@ -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);
}
}
}
}

View file

@ -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>

View file

@ -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"

View file

@ -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"

View file

@ -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
)
);
}
}
/**

View file

@ -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;

View file

@ -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
);
}