Merge pull request #196 from nextcloud/multiple-user-back-ends

Multiple user back ends
This commit is contained in:
Roeland Jago Douma 2018-03-19 14:01:07 +01:00 committed by GitHub
commit 82102c6f18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 206 additions and 1 deletions

View file

@ -94,6 +94,10 @@ if(!$cli &&
!$userSession->isLoggedIn() &&
\OC::$server->getRequest()->getPathInfo() === '/login' &&
$type !== '') {
$params = $request->getParams();
if (isset($params['direct'])) {
return;
}
$redirectSituation = true;
}
@ -114,6 +118,26 @@ if($useSamlForDesktopClients === '1') {
}
}
$multipleUserBackEnds = $config->getAppValue('user_saml', 'general-allow_multiple_user_back_ends', '0');
if ($redirectSituation === true && $multipleUserBackEnds === '1') {
$params = $request->getParams();
$redirectUrl = '';
if(isset($params['redirect_url'])) {
$redirectUrl = $params['redirect_url'];
}
$targetUrl = $urlGenerator->linkToRouteAbsolute(
'user_saml.SAML.selectUserBackEnd',
[
'redirectUrl' => $redirectUrl
]
);
header('Location: '.$targetUrl);
exit();
}
if($redirectSituation === true) {
$params = $request->getParams();
$originalUrl = '';

View file

@ -53,5 +53,10 @@ return [
'url' => '/saml/error',
'verb' => 'GET',
],
[
'name' => 'SAML#selectUserBackEnd',
'url' => '/saml/selectUserBackEnd',
'verb' => 'GET',
],
],
];

View file

@ -5,6 +5,7 @@
#user-saml input[type="checkbox"] {
vertical-align:middle;
cursor: pointer;
}
#user-saml h4 {
@ -27,4 +28,4 @@
cursor: pointer;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
opacity: .5;
}
}

36
css/selectUserBackEnd.css Normal file
View file

@ -0,0 +1,36 @@
#saml-select-user-back-end {
color: white;
}
#saml-select-user-back-end h1 {
font-size: 16px;
padding: 20px 0;
}
.login-option {
background-color: #0082c9;
border: 1px solid #fff;
font-weight: 600;
/*padding: 13px 20px;*/
height: 40px;
margin: 15px 0;
min-width: 269px;
border-radius: 3px;
font-size: 20px;
color: white;
}
.login-option a {
display:inline-block;
width:100%;
line-height:40px;
color: #fff;
cursor: pointer;
}
.login-option .icon-confirm-white {
float: right;
line-height: 40px;
}

View file

@ -316,4 +316,77 @@ class SAMLController extends Controller {
}
return new Http\TemplateResponse($this->appName, 'error', ['message' => $message], 'guest');
}
/**
* @PublicPage
* @NoCSRFRequired
* @OnlyUnauthenticatedUsers
* @param string $redirectUrl
* @return Http\TemplateResponse
*/
public function selectUserBackEnd($redirectUrl) {
$loginUrls = [
'directLogin' => [
'url' => $this->getDirectLoginUrl(),
'display-name' => $this->l->t('Direct log in')
],
'ssoLogin' => [
'url' => $this->getSSOUrl($redirectUrl),
'display-name' => $this->getSSODisplayName(),
]
];
return new Http\TemplateResponse($this->appName, 'selectUserBackEnd', $loginUrls, 'guest');
}
/**
* get SSO URL
*
* @param $redirectUrl
* @return string
*/
private function getSSOUrl($redirectUrl) {
$originalUrl = '';
if(!empty($redirectUrl)) {
$originalUrl = $this->urlGenerator->getAbsoluteURL($redirectUrl);
}
$csrfToken = \OC::$server->getCsrfTokenManager()->getToken();
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute(
'user_saml.SAML.login',
[
'requesttoken' => $csrfToken->getEncryptedValue(),
'originalUrl' => $originalUrl,
]
);
return $ssoUrl;
}
/**
* return the display name of the SSO identity provider
*
* @return string
*/
protected function getSSODisplayName() {
$displayName = $this->config->getAppValue('user_saml', 'general-idp0_display_name');
if (empty($displayName)) {
$displayName = $this->l->t('SSO & SAML log in');
}
return $displayName;
}
/**
* get Nextcloud login URL
*
* @return string
*/
private function getDirectLoginUrl() {
$directUrl = $this->urlGenerator->linkToRouteAbsolute('core.login.tryLogin', ['direct' => '1']);
return $directUrl;
}
}

View file

@ -77,6 +77,11 @@ class Admin implements ISettings {
'lowercaseUrlencoding' => $this->l10n->t('ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification.'),
];
$generalSettings = [
'idp0_display_name' => [
'text' => $this->l10n->t('Optional display name of the identity provider (default: "SSO & SAML log in")'),
'type' => 'line',
'required' => false,
],
'uid_mapping' => [
'text' => $this->l10n->t('Attribute to map the UID to.'),
'type' => 'line',
@ -86,6 +91,10 @@ class Admin implements ISettings {
'text' => $this->l10n->t('Only allow authentication if an account exists on some other backend. (e.g. LDAP)'),
'type' => 'checkbox',
],
'allow_multiple_user_back_ends' => [
'text' => $this->l10n->t('Allow the use of multiple user back-ends (e.g. LDAP)'),
'type' => 'checkbox',
],
];
$attributeMappingSettings = [
'displayName_mapping' => [

View file

@ -0,0 +1,20 @@
<?php
style('user_saml', 'selectUserBackEnd');
/** @var array $_ */
/** @var $l \OCP\IL10N */
?>
<div id="saml-select-user-back-end">
<h1>Chose login option:</h1>
<div class="login-option">
<a href="<?php p($_['directLogin']['url']); ?>"><?php p($_['directLogin']['display-name']); ?></a>
</div>
<div class="login-option">
<a href="<?php p($_['ssoLogin']['url']); ?>"><?php p($_['ssoLogin']['display-name']); ?></a>
</div>
</div>

View file

@ -59,6 +59,11 @@ class Test extends TestCase {
'url' => '/saml/error',
'verb' => 'GET',
],
[
'name' => 'SAML#selectUserBackEnd',
'url' => '/saml/selectUserBackEnd',
'verb' => 'GET',
],
],
];
$this->assertSame($expected, $routes);

View file

@ -458,4 +458,27 @@ class SAMLControllerTest extends TestCase {
['messageSend' => 'test message', 'messageExpected' => 'test message'],
];
}
/**
* @dataProvider dataTestGetSSODisplayName
*
* @param string $configuredDisplayName
* @param string $expected
*/
public function testGetSSODisplayName($configuredDisplayName, $expected) {
$this->config->expects($this->any())->method('getAppValue')
->with('user_saml', 'general-idp0_display_name')
->willReturn($configuredDisplayName);
$result = $this->invokePrivate($this->samlController, 'getSSODisplayName');
$this->assertSame($expected, $result);
}
public function dataTestGetSSODisplayName() {
return [
['My identity provider', 'My identity provider'],
['', 'SSO & SAML log in']
];
}
}

View file

@ -81,6 +81,11 @@ class AdminTest extends \Test\TestCase {
'lowercaseUrlencoding' => 'ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification.',
];
$generalSettings = [
'idp0_display_name' => [
'text' => $this->l10n->t('Optional display name of the identity provider (default: "SSO & SAML log in")'),
'type' => 'line',
'required' => false,
],
'uid_mapping' => [
'text' => 'Attribute to map the UID to.',
'type' => 'line',
@ -94,6 +99,10 @@ class AdminTest extends \Test\TestCase {
'text' => 'Use SAML auth for the Nextcloud desktop clients (requires user re-authentication)',
'type' => 'checkbox',
],
'allow_multiple_user_back_ends' => [
'text' => $this->l10n->t('Allow the use of multiple user back-ends (e.g. LDAP)'),
'type' => 'checkbox',
],
];
$attributeMappingSettings = [
'displayName_mapping' => [