From f47b2769b611fc755c2e11b3a17cc87ffbc54096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Pe=CC=81rez=20Crespo?= <jaime.perez@uninett.no> Date: Wed, 17 Oct 2018 16:36:11 +0200 Subject: [PATCH] Add tests for SimpleSAML\Module\core\Controller. --- tests/modules/core/lib/ControllerTest.php | 243 ++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 tests/modules/core/lib/ControllerTest.php diff --git a/tests/modules/core/lib/ControllerTest.php b/tests/modules/core/lib/ControllerTest.php new file mode 100644 index 000000000..ec77b3651 --- /dev/null +++ b/tests/modules/core/lib/ControllerTest.php @@ -0,0 +1,243 @@ +<?php + +namespace SimpleSAML\Test\Module\core; + +use SimpleSAML\Auth\Simple; +use SimpleSAML\Auth\AuthenticationFactory; +use SimpleSAML\Configuration; +use SimpleSAML\Error\Exception; +use SimpleSAML\HTTP\RunnableResponse; +use SimpleSAML\Locale\Localization; +use SimpleSAML\Module\core\Controller; +use SimpleSAML\Session; +use SimpleSAML\Test\Utils\ClearStateTestCase; +use SimpleSAML\XHTML\Template; + +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; + +/** + * Set of tests for the controllers in the "core" module. + * + * For now, this test extends ClearStateTestCase so that it doesn't interfere with other tests. Once every class has + * been made PSR-7-aware, that won't be necessary any longer. + * + * @package SimpleSAML\Test + */ +class ControllerTest extends ClearStateTestCase +{ + + /** @var array */ + protected $authSources; + + /** @var \SimpleSAML\Configuration */ + protected $config; + + /** @var \SimpleSAML\Configuration[] */ + protected $loadedConfigs; + + /** @var \SimpleSAML\HTTP\Router */ + protected $router; + + + /** + * Set up for each test. + */ + protected function setUp() + { + parent::setUp(); + $this->authSources = [ + 'admin' => [ + 'core:adminPassword' + ], + 'example-userpass' => [ + 'exampleauth:UserPass', + 'username:password' => [ + 'uid' => ['test'] + ] + ] + ]; + $this->config = Configuration::loadFromArray( + [ + 'baseurlpath' => 'https://example.org/simplesaml', + 'module.enable' => ['exampleauth' => true], + 'language.i18n.backend' => Localization::GETTEXT_I18N_BACKEND, + ], + '[ARRAY]', + 'simplesaml' + ); + Configuration::setPreLoadedConfig($this->config, 'config.php'); + } + + + /** + * Test that authentication is started immediately if we hit the login endpoint and there's only one non-admin + * source configured. + */ + public function testAutomaticLoginWhenOnlyOneSource() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $request = new Request(); + $session = Session::getSessionFromRequest(); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + $response = $c->login($request); + $this->assertInstanceOf(RunnableResponse::class, $response); + list($object, $method) = $response->getCallable(); + $this->assertInstanceOf(Simple::class, $object); + $this->assertEquals('login', $method); + $arguments = $response->getArguments(); + $this->assertArrayHasKey('ErrorURL', $arguments[0]); + $this->assertArrayHasKey('ReturnTo', $arguments[0]); + } + + + /** + * Test that the user can choose what auth source to use when there are multiple defined (admin excluded). + */ + public function testMultipleAuthSources() + { + $asConfig = Configuration::loadFromArray( + array_merge( + $this->authSources, + [ + 'example-static' => [ + 'exampleauth:StaticSource', + 'uid' => ['test'] + ] + ] + ) + ); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $request = new Request(); + $session = Session::getSessionFromRequest(); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + $response = $c->login($request); + $this->assertInstanceOf(Template::class, $response); + $this->assertEquals('core:login.twig', $response->getTemplateName()); + $this->assertArrayHasKey('sources', $response->data); + $this->assertArrayHasKey('example-userpass', $response->data['sources']); + $this->assertArrayHasKey('example-static', $response->data['sources']); + } + + + /** + * Test that specifying an invalid auth source while trying to login raises an exception. + */ + public function testLoginWithInvalidAuthSource() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $request = new Request(); + $session = Session::getSessionFromRequest(); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + $this->setExpectedException(Exception::class); + $c->login($request, 'invalid-auth-source'); + } + + + /** + * Test that we get redirected to /account/authsource when accessing the login endpoint while being already + * authenticated. + */ + public function testLoginWhenAlreadyAuthenticated() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $request = new Request(); + $session = Session::getSessionFromRequest(); + $session->setConfiguration($this->config); + $class = new \ReflectionClass($session); + $authData = $class->getProperty('authData'); + $authData->setAccessible(true); + $authData->setValue($session, [ + 'example-userpass' => [ + 'exampleauth:UserPass', + 'Attributes' => ['uid' => ['test']], + 'Authority' => 'example-userpass', + 'AuthnInstant' => time(), + 'Expire' => time() + 8 * 60* 60 + ] + ]); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + $response = $c->login($request); + $this->assertInstanceOf(RedirectResponse::class, $response); + $this->assertEquals( + 'https://example.org/simplesaml/module.php/core/account/example-userpass', + $response->getTargetUrl() + ); + } + + + /** + * Test that triggering the logout controller actually proceeds to log out from the specified source. + */ + public function testLogout() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $session = Session::getSessionFromRequest(); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + $response = $c->logout('example-userpass'); + $this->assertInstanceOf(RunnableResponse::class, $response); + list($object, $method) = $response->getCallable(); + $this->assertInstanceOf(Simple::class, $object); + $this->assertEquals('logout', $method); + $this->assertEquals('/simplesaml/logout.php', $response->getArguments()[0]); + } + + + /** + * Test that accessing the "account" endpoint without being authenticated gets you redirected to the "login" + * endpoint. + */ + public function testNotAuthenticated() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $session = Session::getSessionFromRequest(); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + /** @var RedirectResponse $response */ + $response = $c->account('example-userpass'); + $this->assertInstanceOf(RedirectResponse::class, $response); + $this->assertEquals( + 'https://example.org/simplesaml/module.php/core/login/example-userpass', + $response->getTargetUrl() + ); + } + + + /** + * Test that we are presented with a regular page if we are authenticated and try to access the "account" endpoint. + */ + public function testAuthenticated() + { + $asConfig = Configuration::loadFromArray($this->authSources); + Configuration::setPreLoadedConfig($asConfig, 'authsources.php'); + $session = Session::getSessionFromRequest(); + $class = new \ReflectionClass($session); + $authData = $class->getProperty('authData'); + $authData->setAccessible(true); + $authData->setValue($session, [ + 'example-userpass' => [ + 'exampleauth:UserPass', + 'Attributes' => ['uid' => ['test']], + 'Authority' => 'example-userpass', + 'AuthnInstant' => time(), + 'Expire' => time() + 8 * 60* 60 + ] + ]); + $factory = new AuthenticationFactory($this->config, $session); + $c = new Controller($this->config, $session, $factory); + /** @var \SimpleSAML\XHTML\Template $response */ + $response = $c->account('example-userpass'); + $this->assertInstanceOf(Template::class, $response); + $this->assertEquals('auth_status.twig', $response->getTemplateName()); + } +} -- GitLab