diff options
author | Lukas Reschke <lukas@statuscode.ch> | 2016-11-14 13:54:03 +0300 |
---|---|---|
committer | Lukas Reschke <lukas@statuscode.ch> | 2016-11-14 15:47:30 +0300 |
commit | 314ae475f67051e84b99732d55026550de802552 (patch) | |
tree | f3f82f6397f6f8c4907090e15f2e0090e8890ec7 /lib | |
parent | 5855e6e2ccb352ea8aa8637e17c885e21be76e81 (diff) |
Add support for environment variable login
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AppInfo/Application.php | 21 | ||||
-rw-r--r-- | lib/Controller/SAMLController.php (renamed from lib/controller/samlcontroller.php) | 96 | ||||
-rw-r--r-- | lib/Exceptions/NoUserFoundException.php | 30 | ||||
-rw-r--r-- | lib/Settings/Admin.php | 19 | ||||
-rw-r--r-- | lib/Settings/Section.php | 2 | ||||
-rw-r--r-- | lib/samlsettings.php | 3 | ||||
-rw-r--r-- | lib/userbackend.php | 6 |
7 files changed, 136 insertions, 41 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 9f052996..cc292505 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -34,27 +34,6 @@ class Application extends App { $container = $this->getContainer(); /** - * Controller - */ - $container->registerService('SAMLController', function(IAppContainer $c) { - /** @var \OC\Server $server */ - $server = $c->query('ServerContainer'); - return new SAMLController( - $c->getAppName(), - $server->getRequest(), - $server->getSession(), - $server->getUserSession(), - new SAMLSettings($server->getURLGenerator(), $server->getConfig()), - new UserBackend( - $server->getConfig(), - $server->getURLGenerator(), - $server->getSession(), - $server->getDb() - ) - ); - }); - - /** * Middleware */ $container->registerService('OnlyLoggedInMiddleware', function(IAppContainer $c){ diff --git a/lib/controller/samlcontroller.php b/lib/Controller/SAMLController.php index 7dc59f2f..88bc02e2 100644 --- a/lib/controller/samlcontroller.php +++ b/lib/Controller/SAMLController.php @@ -21,12 +21,16 @@ namespace OCA\User_SAML\Controller; +use OCA\User_SAML\Exceptions\NoUserFoundException; use OCA\User_SAML\SAMLSettings; use OCA\User_SAML\UserBackend; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\IConfig; use OCP\IRequest; use OCP\ISession; +use OCP\IURLGenerator; +use OCP\IUserManager; use OCP\IUserSession; class SAMLController extends Controller { @@ -38,6 +42,12 @@ class SAMLController extends Controller { private $SAMLSettings; /** @var UserBackend */ private $userBackend; + /** @var IConfig */ + private $config; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IUserManager */ + private $userManager; /** * @param string $appName @@ -46,29 +56,92 @@ class SAMLController extends Controller { * @param IUserSession $userSession * @param SAMLSettings $SAMLSettings * @param UserBackend $userBackend + * @param IConfig $config + * @param IURLGenerator $urlGenerator + * @param IUserManager $userManager */ public function __construct($appName, IRequest $request, ISession $session, IUserSession $userSession, SAMLSettings $SAMLSettings, - UserBackend $userBackend) { + UserBackend $userBackend, + IConfig $config, + IURLGenerator $urlGenerator, + IUserManager $userManager) { parent::__construct($appName, $request); $this->session = $session; $this->userSession = $userSession; $this->SAMLSettings = $SAMLSettings; $this->userBackend = $userBackend; + $this->config = $config; + $this->urlGenerator = $urlGenerator; + $this->userManager = $userManager; + } + + /** + * @param array $auth + * @throws NoUserFoundException + */ + private function autoprovisionIfPossible(array $auth) { + $uidMapping = $this->config->getAppValue('user_saml', 'general-uid_mapping'); + if(isset($auth[$uidMapping])) { + if(is_array($auth[$uidMapping])) { + $uid = $auth[$uidMapping][0]; + } else { + $uid = $auth[$uidMapping]; + } + + $userExists = $this->userManager->userExists($uid); + if($userExists === true) { + return; + } + + $autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed(); + if(!$userExists && !$autoProvisioningAllowed) { + throw new NoUserFoundException(); + } elseif(!$userExists && $autoProvisioningAllowed) { + $this->userBackend->createUserIfNotExists($uid); + return; + } + } + + throw new NoUserFoundException(); } /** * @PublicPage * @UseSession * @OnlyUnauthenticatedUsers + * + * @return Http\RedirectResponse + * @throws \Exception */ public function login() { - $auth = new \OneLogin_Saml2_Auth($this->SAMLSettings->getOneLoginSettingsArray()); - $ssoUrl = $auth->login(null, array(), false, false, true); - $this->session->set('user_saml.AuthNRequestID', $auth->getLastRequestID()); + $type = $this->config->getAppValue($this->appName, 'type'); + switch($type) { + case 'saml': + $auth = new \OneLogin_Saml2_Auth($this->SAMLSettings->getOneLoginSettingsArray()); + $ssoUrl = $auth->login(null, [], false, false, true); + $this->session->set('user_saml.AuthNRequestID', $auth->getLastRequestID()); + break; + case 'environment-variable': + $ssoUrl = $this->urlGenerator->getAbsoluteURL('/'); + try { + $this->autoprovisionIfPossible($this->session->get('user_saml.samlUserData')); + } catch (NoUserFoundException $e) { + $ssoUrl = $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'); + } + break; + default: + throw new \Exception( + sprintf( + 'Type of "%s" is not supported for user_saml', + $type + ) + ); + } + return new Http\RedirectResponse($ssoUrl); } @@ -111,6 +184,7 @@ class SAMLController extends Controller { if (!empty($errors)) { print_r('<p>'.implode(', ', $errors).'</p>'); } + if (!$auth->isAuthenticated()) { echo "<p>Not authenticated</p>"; exit(); @@ -118,15 +192,11 @@ class SAMLController extends Controller { // Check whether the user actually exists, if not redirect to an error page // explaining the issue. - $uidMapping = \OC::$server->getConfig()->getAppValue('user_saml', 'general-uid_mapping', ''); - if(isset($auth->getAttributes()[$uidMapping])) { - $uid = $auth->getAttributes()[$uidMapping][0]; - $userExists = \OC::$server->getUserManager()->userExists($uid); - if(!$userExists && !$this->userBackend->autoprovisionAllowed()) { - return new Http\RedirectResponse(\OC::$server->getURLGenerator()->linkToRouteAbsolute('user_saml.SAML.notProvisioned')); - } elseif(!$userExists && $this->userBackend->autoprovisionAllowed()) { - $this->userBackend->createUserIfNotExists($uid); - } + try { + $this->autoprovisionIfPossible($auth->getAttributes()); + } catch (NoUserFoundException $e) { + return new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned')); + } $this->session->set('user_saml.samlUserData', $auth->getAttributes()); diff --git a/lib/Exceptions/NoUserFoundException.php b/lib/Exceptions/NoUserFoundException.php new file mode 100644 index 00000000..19b4fc2a --- /dev/null +++ b/lib/Exceptions/NoUserFoundException.php @@ -0,0 +1,30 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Exceptions; + +/** + * Class NoUserFoundException is thrown when no user has been found + * + * @package OCA\User_SAML\Exceptions + */ +class NoUserFoundException extends \Exception { +} diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 4824d959..279aee02 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -25,6 +25,7 @@ namespace OCA\User_SAML\Settings; use OCP\AppFramework\Http\TemplateResponse; use OCP\Defaults; +use OCP\IConfig; use OCP\IL10N; use OCP\Settings\ISettings; @@ -33,15 +34,20 @@ class Admin implements ISettings { private $l10n; /** @var Defaults */ private $defaults; + /** @var IConfig */ + private $config; /** * @param IL10N $l10n * @param Defaults $defaults + * @param IConfig $config */ public function __construct(IL10N $l10n, - Defaults $defaults) { + Defaults $defaults, + IConfig $config) { $this->l10n = $l10n; $this->defaults = $defaults; + $this->config = $config; } /** @@ -77,17 +83,22 @@ class Admin implements ISettings { 'text' => $this->l10n->t('Only allow authentication if an account is existent on some other backend. (e.g. LDAP)'), 'type' => 'checkbox', ], - 'use_saml_auth_for_desktop' => [ + ]; + + $type = $this->config->getAppValue('user_saml', 'type'); + if($type === 'saml') { + $generalSettings['use_saml_auth_for_desktop'] = [ 'text' => $this->l10n->t('Use SAML auth for the %s desktop clients (requires user re-authentication)', [$this->defaults->getName()]), 'type' => 'checkbox', - ], - ]; + ]; + } $params = [ 'sp' => $serviceProviderFields, 'security-offer' => $securityOfferFields, 'security-required' => $securityRequiredFields, 'general' => $generalSettings, + 'type' => $type, ]; return new TemplateResponse('user_saml', 'admin', $params); diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index 5fed8cd2..c31568be 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -48,7 +48,7 @@ class Section implements ISection { * {@inheritdoc} */ public function getName() { - return $this->l->t('SAML authentication'); + return $this->l->t('SSO & SAML authentication'); } /** diff --git a/lib/samlsettings.php b/lib/samlsettings.php index 9e4a0547..0b3d43de 100644 --- a/lib/samlsettings.php +++ b/lib/samlsettings.php @@ -43,7 +43,7 @@ class SAMLSettings { public function getOneLoginSettingsArray() { $settings = [ - // 'debug' => true, + 'debug' => true, // 'strict' => true, 'security' => [ 'nameIdEncrypted' => ($this->config->getAppValue('user_saml', 'security-nameIdEncrypted', '0') === '1') ? true : false, @@ -57,6 +57,7 @@ class SAMLSettings { 'wantNameId' => ($this->config->getAppValue('user_saml', 'security-wantNameId', '0') === '1') ? true : false, 'wantNameIdEncrypted' => ($this->config->getAppValue('user_saml', 'security-wantNameIdEncrypted', '0') === '1') ? true : false, 'wantXMLValidation' => ($this->config->getAppValue('user_saml', 'security-wantXMLValidation', '0') === '1') ? true : false, + 'requestedAuthnContext' => false, ], 'sp' => [ 'entityId' => $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.getMetadata'), diff --git a/lib/userbackend.php b/lib/userbackend.php index 2967078b..de68a52f 100644 --- a/lib/userbackend.php +++ b/lib/userbackend.php @@ -301,7 +301,11 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend { $uidMapping = $this->config->getAppValue('user_saml', 'general-uid_mapping', ''); if($uidMapping !== '' && isset($samlData[$uidMapping])) { - $uid = $samlData[$uidMapping][0]; + if(is_array($samlData[$uidMapping])) { + $uid = $samlData[$uidMapping][0]; + } else { + $uid = $samlData[$uidMapping]; + } if($this->userExists($uid)) { return $uid; } |