X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/611cb290731e6fac507a7d24b5e234911a28bee6..refs/pull/2393/head:/tests/Auth/Saml2Test.php diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php index 45b6efa07..58c02b471 100644 --- a/tests/Auth/Saml2Test.php +++ b/tests/Auth/Saml2Test.php @@ -1,7 +1,8 @@ -set([ + 'auth.method' => 'saml2', + 'auth.defaults.guard' => 'saml2', 'saml2.name' => 'SingleSignOn-Testing', - 'saml2.enabled' => true, - 'saml2.auto_register' => true, 'saml2.email_attribute' => 'email', 'saml2.display_name_attributes' => ['first_name', 'last_name'], 'saml2.external_id_attribute' => 'uid', @@ -53,27 +54,12 @@ class Saml2Test extends TestCase { $req = $this->get('/login'); $req->assertSeeText('SingleSignOn-Testing'); - $req->assertElementExists('a[href$="/saml2/login"]'); - } - - public function test_login_option_shows_on_register_page_only_when_auto_register_enabled() - { - $this->setSettings(['app-public' => 'true', 'registration-enabled' => 'true']); - - $req = $this->get('/register'); - $req->assertSeeText('SingleSignOn-Testing'); - $req->assertElementExists('a[href$="/saml2/login"]'); - - config()->set(['saml2.auto_register' => false]); - - $req = $this->get('/register'); - $req->assertDontSeeText('SingleSignOn-Testing'); - $req->assertElementNotExists('a[href$="/saml2/login"]'); + $req->assertElementExists('form[action$="/saml2/login"][method=POST] button'); } public function test_login() { - $req = $this->get('/saml2/login'); + $req = $this->post('/saml2/login'); $redirect = $req->headers->get('location'); $this->assertStringStartsWith('http://saml.local/saml2/idp/SSOService.php', $redirect, 'Login redirects to SSO location'); @@ -88,7 +74,7 @@ class Saml2Test extends TestCase $this->assertDatabaseHas('users', [ 'email' => 'user@example.com', 'external_auth_id' => 'user', - 'email_confirmed' => true, + 'email_confirmed' => false, 'name' => 'Barry Scott' ]); @@ -138,20 +124,15 @@ class Saml2Test extends TestCase }); } - public function test_logout_redirects_to_saml_logout_when_active_saml_session() + public function test_logout_link_directs_to_saml_path() { config()->set([ 'saml2.onelogin.strict' => false, ]); - $this->withPost(['SAMLResponse' => $this->acsPostData], function () { - $acsPost = $this->post('/saml2/acs'); - $lastLoginType = session()->get('last_login_type'); - $this->assertEquals('saml2', $lastLoginType); - - $req = $this->get('/logout'); - $req->assertRedirect('/saml2/logout'); - }); + $resp = $this->actingAs($this->getEditor())->get('/'); + $resp->assertElementExists('a[href$="/saml2/logout"]'); + $resp->assertElementContains('a[href$="/saml2/logout"]', 'Logout'); } public function test_logout_sls_flow() @@ -215,44 +196,136 @@ class Saml2Test extends TestCase }); } - public function test_user_registration_with_existing_email() + public function test_saml_routes_are_only_active_if_saml_enabled() + { + config()->set(['auth.method' => 'standard']); + $getRoutes = ['/logout', '/metadata', '/sls']; + foreach ($getRoutes as $route) { + $req = $this->get('/saml2' . $route); + $this->assertPermissionError($req); + } + + $postRoutes = ['/login', '/acs']; + foreach ($postRoutes as $route) { + $req = $this->post('/saml2' . $route); + $this->assertPermissionError($req); + } + } + + public function test_forgot_password_routes_inaccessible() + { + $resp = $this->get('/password/email'); + $this->assertPermissionError($resp); + + $resp = $this->post('/password/email'); + $this->assertPermissionError($resp); + + $resp = $this->get('/password/reset/abc123'); + $this->assertPermissionError($resp); + + $resp = $this->post('/password/reset'); + $this->assertPermissionError($resp); + } + + public function test_standard_login_routes_inaccessible() + { + $resp = $this->post('/login'); + $this->assertPermissionError($resp); + + $resp = $this->get('/logout'); + $this->assertPermissionError($resp); + } + + public function test_user_invite_routes_inaccessible() { + $resp = $this->get('/register/invite/abc123'); + $this->assertPermissionError($resp); + + $resp = $this->post('/register/invite/abc123'); + $this->assertPermissionError($resp); + } + + public function test_user_register_routes_inaccessible() + { + $resp = $this->get('/register'); + $this->assertPermissionError($resp); + + $resp = $this->post('/register'); + $this->assertPermissionError($resp); + } + + public function test_email_domain_restriction_active_on_new_saml_login() + { + $this->setSettings([ + 'registration-restrict' => 'testing.com' + ]); config()->set([ 'saml2.onelogin.strict' => false, ]); - $viewer = $this->getViewer(); - $viewer->email = 'user@example.com'; - $viewer->save(); - $this->withPost(['SAMLResponse' => $this->acsPostData], function () { $acsPost = $this->post('/saml2/acs'); - $acsPost->assertRedirect('/'); + $acsPost->assertRedirect('/login'); $errorMessage = session()->get('error'); - $this->assertEquals('Registration unsuccessful since a user already exists with email address "user@example.com"', $errorMessage); + $this->assertStringContainsString('That email domain does not have access to this application', $errorMessage); + $this->assertDatabaseMissing('users', ['email' => 'user@example.com']); }); } - public function test_saml_routes_are_only_active_if_saml_enabled() + public function test_group_sync_functions_when_email_confirmation_required() { - config()->set(['saml2.enabled' => false]); - $getRoutes = ['/login', '/logout', '/metadata', '/sls']; - foreach ($getRoutes as $route) { - $req = $this->get('/saml2' . $route); - $req->assertRedirect('/'); - $error = session()->get('error'); - $this->assertStringStartsWith('You do not have permission to access', $error); - session()->flush(); - } + setting()->put('registration-confirmation', 'true'); + config()->set([ + 'saml2.onelogin.strict' => false, + 'saml2.user_to_groups' => true, + 'saml2.remove_from_groups' => false, + ]); - $postRoutes = ['/acs']; - foreach ($postRoutes as $route) { - $req = $this->post('/saml2' . $route); - $req->assertRedirect('/'); - $error = session()->get('error'); - $this->assertStringStartsWith('You do not have permission to access', $error); - session()->flush(); - } + $memberRole = factory(Role::class)->create(['external_auth_id' => 'member']); + $adminRole = Role::getSystemRole('admin'); + + $this->withPost(['SAMLResponse' => $this->acsPostData], function () use ($memberRole, $adminRole) { + $acsPost = $this->followingRedirects()->post('/saml2/acs'); + + $this->assertEquals('http://localhost/register/confirm', url()->current()); + $acsPost->assertSee('Please check your email and click the confirmation button to access BookStack.'); + $user = User::query()->where('external_auth_id', '=', 'user')->first(); + + $userRoleIds = $user->roles()->pluck('id'); + $this->assertContains($memberRole->id, $userRoleIds, 'User was assigned to member role'); + $this->assertContains($adminRole->id, $userRoleIds, 'User was assigned to admin role'); + $this->assertTrue($user->email_confirmed == false, 'User email remains unconfirmed'); + }); + + $homeGet = $this->get('/'); + $homeGet->assertRedirect('/register/confirm/awaiting'); + } + + public function test_login_where_existing_non_saml_user_shows_warning() + { + $this->post('/saml2/login'); + config()->set(['saml2.onelogin.strict' => false]); + + // Make the user pre-existing in DB with different auth_id + User::query()->forceCreate([ + 'email' => 'user@example.com', + 'external_auth_id' => 'old_system_user_id', + 'email_confirmed' => false, + 'name' => 'Barry Scott' + ]); + + $this->withPost(['SAMLResponse' => $this->acsPostData], function () { + $acsPost = $this->post('/saml2/acs'); + $acsPost->assertRedirect('/login'); + $this->assertFalse($this->isAuthenticated()); + $this->assertDatabaseHas('users', [ + 'email' => 'user@example.com', + 'external_auth_id' => 'old_system_user_id', + ]); + + $loginGet = $this->get('/login'); + $loginGet->assertSee("A user with the email user@example.com already exists but with different credentials"); + }); } protected function withGet(array $options, callable $callback)