1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/json/json_file_value_serializer.h"
15 #include "base/location.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string16.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/values.h"
26 #include "chrome/browser/chrome_notification_types.h"
27 #include "chrome/browser/chromeos/login/existing_user_controller.h"
28 #include "chrome/browser/chromeos/login/startup_utils.h"
29 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
30 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
31 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
32 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
33 #include "chrome/browser/chromeos/login/wizard_controller.h"
34 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
35 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
36 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
37 #include "chrome/browser/chromeos/profiles/profile_helper.h"
38 #include "chrome/browser/chromeos/settings/cros_settings.h"
39 #include "chrome/browser/lifetime/application_lifetime.h"
40 #include "chrome/browser/policy/test/local_policy_test_server.h"
41 #include "chrome/browser/profiles/profile.h"
42 #include "chrome/browser/ui/webui/signin/inline_login_ui.h"
43 #include "chrome/common/chrome_constants.h"
44 #include "chrome/common/chrome_paths.h"
45 #include "chrome/common/chrome_switches.h"
46 #include "chrome/common/extensions/features/feature_channel.h"
47 #include "chrome/common/pref_names.h"
48 #include "chrome/grit/generated_resources.h"
49 #include "chrome/test/base/in_process_browser_test.h"
50 #include "chromeos/chromeos_switches.h"
51 #include "chromeos/dbus/dbus_thread_manager.h"
52 #include "chromeos/dbus/fake_session_manager_client.h"
53 #include "chromeos/dbus/session_manager_client.h"
54 #include "chromeos/settings/cros_settings_names.h"
55 #include "components/policy/core/browser/browser_policy_connector.h"
56 #include "components/policy/core/common/mock_configuration_policy_provider.h"
57 #include "components/policy/core/common/policy_map.h"
58 #include "components/policy/core/common/policy_switches.h"
59 #include "components/policy/core/common/policy_types.h"
60 #include "components/user_manager/user.h"
61 #include "components/user_manager/user_manager.h"
62 #include "content/public/browser/browser_thread.h"
63 #include "content/public/browser/render_frame_host.h"
64 #include "content/public/browser/web_contents.h"
65 #include "content/public/browser/web_contents_observer.h"
66 #include "content/public/test/browser_test_utils.h"
67 #include "content/public/test/test_utils.h"
68 #include "google_apis/gaia/fake_gaia.h"
69 #include "google_apis/gaia/gaia_constants.h"
70 #include "google_apis/gaia/gaia_switches.h"
71 #include "google_apis/gaia/gaia_urls.h"
72 #include "net/base/url_util.h"
73 #include "net/cookies/canonical_cookie.h"
74 #include "net/cookies/cookie_monster.h"
75 #include "net/cookies/cookie_store.h"
76 #include "net/dns/mock_host_resolver.h"
77 #include "net/test/embedded_test_server/embedded_test_server.h"
78 #include "net/test/embedded_test_server/http_request.h"
79 #include "net/test/embedded_test_server/http_response.h"
80 #include "net/url_request/url_request_context.h"
81 #include "net/url_request/url_request_context_getter.h"
82 #include "policy/policy_constants.h"
83 #include "policy/proto/device_management_backend.pb.h"
84 #include "testing/gmock/include/gmock/gmock.h"
85 #include "testing/gtest/include/gtest/gtest.h"
86 #include "ui/base/l10n/l10n_util.h"
89 namespace em
= enterprise_management
;
91 using net::test_server::BasicHttpResponse
;
92 using net::test_server::HttpRequest
;
93 using net::test_server::HttpResponse
;
95 using testing::Return
;
101 const char kGAIASIDCookieName
[] = "SID";
102 const char kGAIALSIDCookieName
[] = "LSID";
104 const char kTestAuthSIDCookie1
[] = "fake-auth-SID-cookie-1";
105 const char kTestAuthSIDCookie2
[] = "fake-auth-SID-cookie-2";
106 const char kTestAuthLSIDCookie1
[] = "fake-auth-LSID-cookie-1";
107 const char kTestAuthLSIDCookie2
[] = "fake-auth-LSID-cookie-2";
109 const char kFirstSAMLUserEmail
[] = "bob@example.com";
110 const char kSecondSAMLUserEmail
[] = "alice@example.com";
111 const char kHTTPSAMLUserEmail
[] = "carol@example.com";
112 const char kNonSAMLUserEmail
[] = "dan@example.com";
113 const char kDifferentDomainSAMLUserEmail
[] = "eve@example.test";
115 const char kSAMLIdPCookieName
[] = "saml";
116 const char kSAMLIdPCookieValue1
[] = "value-1";
117 const char kSAMLIdPCookieValue2
[] = "value-2";
119 const char kRelayState
[] = "RelayState";
121 const char kTestUserinfoToken
[] = "fake-userinfo-token";
122 const char kTestRefreshToken
[] = "fake-refresh-token";
123 const char kPolicy
[] = "{\"managed_users\": [\"*\"]}";
125 // FakeSamlIdp serves IdP auth form and the form submission. The form is
126 // served with the template's RelayState placeholder expanded to the real
127 // RelayState parameter from request. The form submission redirects back to
128 // FakeGaia with the same RelayState.
134 void SetUp(const std::string
& base_path
, const GURL
& gaia_url
);
136 void SetLoginHTMLTemplate(const std::string
& template_file
);
137 void SetLoginAuthHTMLTemplate(const std::string
& template_file
);
138 void SetRefreshURL(const GURL
& refresh_url
);
139 void SetCookieValue(const std::string
& cookie_value
);
141 scoped_ptr
<HttpResponse
> HandleRequest(const HttpRequest
& request
);
144 scoped_ptr
<HttpResponse
> BuildHTMLResponse(const std::string
& html_template
,
145 const std::string
& relay_state
,
146 const std::string
& next_path
);
148 base::FilePath html_template_dir_
;
150 std::string login_path_
;
151 std::string login_auth_path_
;
153 std::string login_html_template_
;
154 std::string login_auth_html_template_
;
155 GURL gaia_assertion_url_
;
157 std::string cookie_value_
;
159 DISALLOW_COPY_AND_ASSIGN(FakeSamlIdp
);
162 FakeSamlIdp::FakeSamlIdp() {
165 FakeSamlIdp::~FakeSamlIdp() {
168 void FakeSamlIdp::SetUp(const std::string
& base_path
, const GURL
& gaia_url
) {
169 base::FilePath test_data_dir
;
170 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
171 html_template_dir_
= test_data_dir
.Append("login");
173 login_path_
= base_path
;
174 login_auth_path_
= base_path
+ "Auth";
175 gaia_assertion_url_
= gaia_url
.Resolve("/SSO");
178 void FakeSamlIdp::SetLoginHTMLTemplate(const std::string
& template_file
) {
179 EXPECT_TRUE(base::ReadFileToString(
180 html_template_dir_
.Append(template_file
),
181 &login_html_template_
));
184 void FakeSamlIdp::SetLoginAuthHTMLTemplate(const std::string
& template_file
) {
185 EXPECT_TRUE(base::ReadFileToString(
186 html_template_dir_
.Append(template_file
),
187 &login_auth_html_template_
));
190 void FakeSamlIdp::SetRefreshURL(const GURL
& refresh_url
) {
191 refresh_url_
= refresh_url
;
194 void FakeSamlIdp::SetCookieValue(const std::string
& cookie_value
) {
195 cookie_value_
= cookie_value
;
198 scoped_ptr
<HttpResponse
> FakeSamlIdp::HandleRequest(
199 const HttpRequest
& request
) {
200 // The scheme and host of the URL is actually not important but required to
201 // get a valid GURL in order to parse |request.relative_url|.
202 GURL request_url
= GURL("http://localhost").Resolve(request
.relative_url
);
203 std::string request_path
= request_url
.path();
205 if (request_path
== login_path_
) {
206 std::string relay_state
;
207 net::GetValueForKeyInQuery(request_url
, kRelayState
, &relay_state
);
208 return BuildHTMLResponse(login_html_template_
,
213 if (request_path
!= login_auth_path_
) {
214 // Request not understood.
215 return scoped_ptr
<HttpResponse
>();
218 std::string relay_state
;
219 FakeGaia::GetQueryParameter(request
.content
, kRelayState
, &relay_state
);
220 GURL redirect_url
= gaia_assertion_url_
;
222 if (!login_auth_html_template_
.empty()) {
223 return BuildHTMLResponse(login_auth_html_template_
,
225 redirect_url
.spec());
228 redirect_url
= net::AppendQueryParameter(
229 redirect_url
, "SAMLResponse", "fake_response");
230 redirect_url
= net::AppendQueryParameter(
231 redirect_url
, kRelayState
, relay_state
);
233 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse());
234 http_response
->set_code(net::HTTP_TEMPORARY_REDIRECT
);
235 http_response
->AddCustomHeader("Location", redirect_url
.spec());
236 http_response
->AddCustomHeader(
238 base::StringPrintf("saml=%s", cookie_value_
.c_str()));
239 return http_response
.Pass();
242 scoped_ptr
<HttpResponse
> FakeSamlIdp::BuildHTMLResponse(
243 const std::string
& html_template
,
244 const std::string
& relay_state
,
245 const std::string
& next_path
) {
246 std::string response_html
= html_template
;
247 ReplaceSubstringsAfterOffset(&response_html
, 0, "$RelayState", relay_state
);
248 ReplaceSubstringsAfterOffset(&response_html
, 0, "$Post", next_path
);
249 ReplaceSubstringsAfterOffset(
250 &response_html
, 0, "$Refresh", refresh_url_
.spec());
252 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse());
253 http_response
->set_code(net::HTTP_OK
);
254 http_response
->set_content(response_html
);
255 http_response
->set_content_type("text/html");
257 return http_response
.Pass();
262 class SamlTest
: public InProcessBrowserTest
,
263 public testing::WithParamInterface
<bool> {
265 SamlTest() : gaia_frame_parent_("signin-frame"), saml_load_injected_(false) {}
266 ~SamlTest() override
{}
268 bool UseWebView() const {
272 void SetUp() override
{
273 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
275 // Start the GAIA https wrapper here so that the GAIA URLs can be pointed at
276 // it in SetUpCommandLine().
277 gaia_https_forwarder_
.reset(
278 new HTTPSForwarder(embedded_test_server()->base_url()));
279 ASSERT_TRUE(gaia_https_forwarder_
->Start());
281 // Start the SAML IdP https wrapper here so that GAIA can be pointed at it
282 // in SetUpCommandLine().
283 saml_https_forwarder_
.reset(
284 new HTTPSForwarder(embedded_test_server()->base_url()));
285 ASSERT_TRUE(saml_https_forwarder_
->Start());
287 // Stop IO thread here because no threads are allowed while
288 // spawning sandbox host process. See crbug.com/322732.
289 embedded_test_server()->StopThread();
291 InProcessBrowserTest::SetUp();
294 bool SetUpUserDataDirectory() override
{
296 // Fake Dev channel to enable webview signin.
297 scoped_channel_
.reset(new extensions::ScopedCurrentChannel(
298 chrome::VersionInfo::CHANNEL_DEV
));
300 base::FilePath user_data_dir
;
301 CHECK(PathService::Get(chrome::DIR_USER_DATA
, &user_data_dir
));
302 base::FilePath local_state_path
=
303 user_data_dir
.Append(chrome::kLocalStateFilename
);
305 // Set webview enabled flag only when local state file does not exist.
306 // Otherwise, we break PRE tests that leave state in it.
307 if (!base::PathExists(local_state_path
)) {
308 base::DictionaryValue local_state_dict
;
309 local_state_dict
.SetBoolean(prefs::kWebviewSigninEnabled
, true);
310 // OobeCompleted to skip controller-pairing-screen which still uses
311 // iframe and ends up in a JS error in oobe page init.
312 // See http://crbug.com/467147
313 local_state_dict
.SetBoolean(prefs::kOobeComplete
, true);
315 CHECK(JSONFileValueSerializer(local_state_path
)
316 .Serialize(local_state_dict
));
320 return InProcessBrowserTest::SetUpUserDataDirectory();
323 void SetUpInProcessBrowserTestFixture() override
{
324 host_resolver()->AddRule("*", "127.0.0.1");
327 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
328 command_line
->AppendSwitch(switches::kLoginManager
);
329 command_line
->AppendSwitch(switches::kForceLoginManagerInTests
);
330 command_line
->AppendSwitch(switches::kOobeSkipPostLogin
);
331 command_line
->AppendSwitch(::switches::kDisableBackgroundNetworking
);
332 command_line
->AppendSwitchASCII(switches::kLoginProfile
, "user");
334 const GURL gaia_url
= gaia_https_forwarder_
->GetURL("");
335 command_line
->AppendSwitchASCII(::switches::kGaiaUrl
, gaia_url
.spec());
336 command_line
->AppendSwitchASCII(::switches::kLsoUrl
, gaia_url
.spec());
337 command_line
->AppendSwitchASCII(::switches::kGoogleApisUrl
,
340 const GURL saml_idp_url
= saml_https_forwarder_
->GetURL("SAML");
341 fake_saml_idp_
.SetUp(saml_idp_url
.path(), gaia_url
);
342 fake_gaia_
.RegisterSamlUser(kFirstSAMLUserEmail
, saml_idp_url
);
343 fake_gaia_
.RegisterSamlUser(kSecondSAMLUserEmail
, saml_idp_url
);
344 fake_gaia_
.RegisterSamlUser(
346 embedded_test_server()->base_url().Resolve("/SAML"));
347 fake_gaia_
.RegisterSamlUser(kDifferentDomainSAMLUserEmail
, saml_idp_url
);
349 fake_gaia_
.Initialize();
350 fake_gaia_
.set_issue_oauth_code_cookie(UseWebView());
353 void SetUpOnMainThread() override
{
354 fake_gaia_
.SetFakeMergeSessionParams(kFirstSAMLUserEmail
,
356 kTestAuthLSIDCookie1
);
358 embedded_test_server()->RegisterRequestHandler(
359 base::Bind(&FakeGaia::HandleRequest
, base::Unretained(&fake_gaia_
)));
360 embedded_test_server()->RegisterRequestHandler(base::Bind(
361 &FakeSamlIdp::HandleRequest
, base::Unretained(&fake_saml_idp_
)));
363 // Restart the thread as the sandbox host process has already been spawned.
364 embedded_test_server()->RestartThreadAndListen();
366 login_screen_load_observer_
.reset(new content::WindowedNotificationObserver(
367 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
368 content::NotificationService::AllSources()));
371 void TearDownOnMainThread() override
{
372 // If the login display is still showing, exit gracefully.
373 if (LoginDisplayHostImpl::default_host()) {
374 base::MessageLoop::current()->PostTask(FROM_HERE
,
375 base::Bind(&chrome::AttemptExit
));
376 content::RunMessageLoop();
380 WebUILoginDisplay
* GetLoginDisplay() {
381 ExistingUserController
* controller
=
382 ExistingUserController::current_controller();
384 return static_cast<WebUILoginDisplay
*>(controller
->login_display());
387 void WaitForSigninScreen() {
388 WizardController
* wizard_controller
=
389 WizardController::default_controller();
390 if (wizard_controller
) {
391 wizard_controller
->SkipToLoginForTesting(LoginScreenContext());
393 WizardController::SkipPostLoginScreensForTesting();
395 login_screen_load_observer_
->Wait();
398 virtual void StartSamlAndWaitForIdpPageLoad(const std::string
& gaia_email
) {
399 WaitForSigninScreen();
401 if (!saml_load_injected_
) {
402 saml_load_injected_
= true;
404 ASSERT_TRUE(content::ExecuteScript(
405 GetLoginUI()->GetWebContents(),
406 "$('gaia-signin').gaiaAuthHost_.addEventListener('authFlowChange',"
408 "window.domAutomationController.setAutomationId(0);"
409 "window.domAutomationController.send("
410 "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');"
414 content::DOMMessageQueue message_queue
; // Start observe before SAML.
415 GetLoginDisplay()->ShowSigninScreenForCreds(gaia_email
, "");
418 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
419 EXPECT_EQ("\"SamlLoaded\"", message
);
422 void SetSignFormField(const std::string
& field_id
,
423 const std::string
& field_value
) {
426 "document.getElementById('$FieldId').value = '$FieldValue';"
427 "var e = new Event('input');"
428 "document.getElementById('$FieldId').dispatchEvent(e);"
430 ReplaceSubstringsAfterOffset(&js
, 0, "$FieldId", field_id
);
431 ReplaceSubstringsAfterOffset(&js
, 0, "$FieldValue", field_value
);
432 ExecuteJsInSigninFrame(js
);
435 void SendConfirmPassword(const std::string
& password_to_confirm
) {
437 "$('confirm-password-input').value='$Password';"
438 "$('confirm-password').onConfirmPassword_();";
439 ReplaceSubstringsAfterOffset(&js
, 0, "$Password", password_to_confirm
);
440 ASSERT_TRUE(content::ExecuteScript(GetLoginUI()->GetWebContents(), js
));
443 void JsExpect(const std::string
& js
) {
445 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
446 GetLoginUI()->GetWebContents(),
447 "window.domAutomationController.send(!!(" + js
+ "));",
449 EXPECT_TRUE(result
) << js
;
452 std::string
WaitForAndGetFatalErrorMessage() {
453 OobeScreenWaiter(OobeDisplay::SCREEN_FATAL_ERROR
).Wait();
454 std::string error_message
;
455 if (!content::ExecuteScriptAndExtractString(
456 GetLoginUI()->GetWebContents(),
457 "window.domAutomationController.send("
458 "$('fatal-error-message').textContent);",
462 return error_message
;
465 content::WebUI
* GetLoginUI() {
466 return static_cast<LoginDisplayHostImpl
*>(
467 LoginDisplayHostImpl::default_host())->GetOobeUI()->web_ui();
470 // Executes JavaScript code in the auth iframe hosted by gaia_auth extension.
471 void ExecuteJsInSigninFrame(const std::string
& js
) {
472 content::RenderFrameHost
* frame
= InlineLoginUI::GetAuthIframe(
473 GetLoginUI()->GetWebContents(), GURL(), gaia_frame_parent_
);
474 ASSERT_TRUE(content::ExecuteScript(frame
, js
));
477 FakeSamlIdp
* fake_saml_idp() { return &fake_saml_idp_
; }
480 scoped_ptr
<content::WindowedNotificationObserver
> login_screen_load_observer_
;
483 std::string gaia_frame_parent_
;
485 scoped_ptr
<HTTPSForwarder
> gaia_https_forwarder_
;
486 scoped_ptr
<HTTPSForwarder
> saml_https_forwarder_
;
489 FakeSamlIdp fake_saml_idp_
;
490 scoped_ptr
<extensions::ScopedCurrentChannel
> scoped_channel_
;
492 bool saml_load_injected_
;
494 DISALLOW_COPY_AND_ASSIGN(SamlTest
);
497 // Tests that signin frame should have 'saml' class and 'cancel' button is
498 // visible when SAML IdP page is loaded. And 'cancel' button goes back to
500 IN_PROC_BROWSER_TEST_P(SamlTest
, SamlUI
) {
501 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
502 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
504 // Saml flow UI expectations.
505 JsExpect("$('gaia-signin').classList.contains('full-width')");
507 JsExpect("!$('cancel-add-user-button').hidden");
510 // Click on 'cancel'.
511 content::DOMMessageQueue message_queue
; // Observe before 'cancel'.
513 ASSERT_TRUE(content::ExecuteScript(
514 GetLoginUI()->GetWebContents(),
515 "$('close-button-item').click();"));
517 ASSERT_TRUE(content::ExecuteScript(
518 GetLoginUI()->GetWebContents(),
519 "$('cancel-add-user-button').click();"));
522 // Auth flow should change back to Gaia.
525 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
526 } while (message
!= "\"GaiaLoaded\"");
528 // Saml flow is gone.
529 JsExpect("!$('gaia-signin').classList.contains('full-width')");
532 // Tests the sign-in flow when the credentials passing API is used.
533 IN_PROC_BROWSER_TEST_P(SamlTest
, CredentialPassingAPI
) {
534 // Disabled for webview because the script is injected using
535 // webview.executeScript and there is no way to control the injection time.
536 // As a result, this test is flaky and fails about 20% of the time.
537 // TODO(xiyuan): Re-enable when webview.addContentScript API is ready.
541 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
542 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
543 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
545 content::WindowedNotificationObserver
session_start_waiter(
546 chrome::NOTIFICATION_SESSION_STARTED
,
547 content::NotificationService::AllSources());
549 // Fill-in the SAML IdP form and submit.
550 SetSignFormField("Email", "fake_user");
551 SetSignFormField("Password", "fake_password");
552 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
554 // Login should finish login and a session should start.
555 session_start_waiter
.Wait();
558 // Tests the single password scraped flow.
559 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedSingle
) {
560 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
561 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
563 // Fill-in the SAML IdP form and submit.
564 SetSignFormField("Email", "fake_user");
565 SetSignFormField("Password", "fake_password");
566 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
568 // Lands on confirm password screen.
569 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
571 // Entering an unknown password should go back to the confirm password screen.
572 SendConfirmPassword("wrong_password");
573 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
575 // Entering a known password should finish login and start session.
576 content::WindowedNotificationObserver
session_start_waiter(
577 chrome::NOTIFICATION_SESSION_STARTED
,
578 content::NotificationService::AllSources());
579 SendConfirmPassword("fake_password");
580 session_start_waiter
.Wait();
583 // Tests password scraping from a dynamically created password field.
584 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedDynamic
) {
585 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
586 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
588 ExecuteJsInSigninFrame(
590 "var newPassInput = document.createElement('input');"
591 "newPassInput.id = 'DynamicallyCreatedPassword';"
592 "newPassInput.type = 'password';"
593 "newPassInput.name = 'Password';"
594 "document.forms[0].appendChild(newPassInput);"
597 // Fill-in the SAML IdP form and submit.
598 SetSignFormField("Email", "fake_user");
599 SetSignFormField("DynamicallyCreatedPassword", "fake_password");
600 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
602 // Lands on confirm password screen.
603 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
605 // Entering an unknown password should go back to the confirm password screen.
606 SendConfirmPassword("wrong_password");
607 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
609 // Entering a known password should finish login and start session.
610 content::WindowedNotificationObserver
session_start_waiter(
611 chrome::NOTIFICATION_SESSION_STARTED
,
612 content::NotificationService::AllSources());
613 SendConfirmPassword("fake_password");
614 session_start_waiter
.Wait();
617 // Tests the multiple password scraped flow.
618 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedMultiple
) {
619 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html");
621 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
623 SetSignFormField("Email", "fake_user");
624 SetSignFormField("Password", "fake_password");
625 SetSignFormField("Password1", "password1");
626 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
628 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
630 // Either scraped password should be able to sign-in.
631 content::WindowedNotificationObserver
session_start_waiter(
632 chrome::NOTIFICATION_SESSION_STARTED
,
633 content::NotificationService::AllSources());
634 SendConfirmPassword("password1");
635 session_start_waiter
.Wait();
638 // Tests the no password scraped flow.
639 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedNone
) {
640 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_no_passwords.html");
642 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
644 SetSignFormField("Email", "fake_user");
645 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
647 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_PASSWORD
),
648 WaitForAndGetFatalErrorMessage());
651 // Types |bob@example.com| into the GAIA login form but then authenticates as
652 // |alice@example.com| via SAML. Verifies that the logged-in user is correctly
653 // identified as Alice.
654 IN_PROC_BROWSER_TEST_P(SamlTest
, UseAutenticatedUserEmailAddress
) {
655 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
656 // Type |bob@example.com| into the GAIA login form.
657 StartSamlAndWaitForIdpPageLoad(kSecondSAMLUserEmail
);
659 // Authenticate as alice@example.com via SAML (the |Email| provided here is
660 // irrelevant - the authenticated user's e-mail address that FakeGAIA
661 // reports was set via |SetFakeMergeSessionParams|.
662 SetSignFormField("Email", "fake_user");
663 SetSignFormField("Password", "fake_password");
664 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
666 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
668 content::WindowedNotificationObserver
session_start_waiter(
669 chrome::NOTIFICATION_SESSION_STARTED
,
670 content::NotificationService::AllSources());
671 SendConfirmPassword("fake_password");
672 session_start_waiter
.Wait();
673 const user_manager::User
* user
=
674 user_manager::UserManager::Get()->GetActiveUser();
676 EXPECT_EQ(kFirstSAMLUserEmail
, user
->email());
679 // Verifies that if the authenticated user's e-mail address cannot be retrieved,
680 // an error message is shown.
681 IN_PROC_BROWSER_TEST_P(SamlTest
, FailToRetrieveAutenticatedUserEmailAddress
) {
682 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
683 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
685 fake_gaia_
.SetFakeMergeSessionParams(
686 "", kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
687 SetSignFormField("Email", "fake_user");
688 SetSignFormField("Password", "fake_password");
689 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
691 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_ACCOUNT_DETAILS
),
692 WaitForAndGetFatalErrorMessage());
695 // Tests the password confirm flow: show error on the first failure and
696 // fatal error on the second failure.
697 IN_PROC_BROWSER_TEST_P(SamlTest
, PasswordConfirmFlow
) {
698 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
699 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
701 // Fill-in the SAML IdP form and submit.
702 SetSignFormField("Email", "fake_user");
703 SetSignFormField("Password", "fake_password");
704 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
706 // Lands on confirm password screen with no error message.
707 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
708 JsExpect("!$('confirm-password').classList.contains('error')");
710 // Enter an unknown password for the first time should go back to confirm
711 // password screen with error message.
712 SendConfirmPassword("wrong_password");
713 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
714 JsExpect("$('confirm-password').classList.contains('error')");
716 // Enter an unknown password 2nd time should go back fatal error message.
717 SendConfirmPassword("wrong_password");
719 l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_PASSWORD_VERIFICATION
),
720 WaitForAndGetFatalErrorMessage());
723 // Verifies that when GAIA attempts to redirect to a SAML IdP served over http,
724 // not https, the redirect is blocked and an error message is shown.
725 IN_PROC_BROWSER_TEST_P(SamlTest
, HTTPRedirectDisallowed
) {
726 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
728 WaitForSigninScreen();
729 GetLoginDisplay()->ShowSigninScreenForCreds(kHTTPSAMLUserEmail
, "");
731 const GURL url
= embedded_test_server()->base_url().Resolve("/SAML");
732 EXPECT_EQ(l10n_util::GetStringFUTF8(
733 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL
,
734 base::UTF8ToUTF16(url
.spec())),
735 WaitForAndGetFatalErrorMessage());
738 // Verifies that when GAIA attempts to redirect to a page served over http, not
739 // https, via an HTML meta refresh, the redirect is blocked and an error message
740 // is shown. This guards against regressions of http://crbug.com/359515.
741 IN_PROC_BROWSER_TEST_P(SamlTest
, MetaRefreshToHTTPDisallowed
) {
742 const GURL url
= embedded_test_server()->base_url().Resolve("/SSO");
743 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html");
744 fake_saml_idp()->SetRefreshURL(url
);
746 WaitForSigninScreen();
747 GetLoginDisplay()->ShowSigninScreenForCreds(kFirstSAMLUserEmail
, "");
749 EXPECT_EQ(l10n_util::GetStringFUTF8(
750 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL
,
751 base::UTF8ToUTF16(url
.spec())),
752 WaitForAndGetFatalErrorMessage());
755 INSTANTIATE_TEST_CASE_P(SamlSuite
,
759 class SAMLEnrollmentTest
: public SamlTest
,
760 public content::WebContentsObserver
{
762 SAMLEnrollmentTest();
763 ~SAMLEnrollmentTest() override
;
766 void SetUp() override
;
767 void SetUpCommandLine(base::CommandLine
* command_line
) override
;
768 void SetUpOnMainThread() override
;
769 void StartSamlAndWaitForIdpPageLoad(const std::string
& gaia_email
) override
;
771 // content::WebContentsObserver:
772 void RenderFrameCreated(content::RenderFrameHost
* render_frame_host
) override
;
773 void DidFinishLoad(content::RenderFrameHost
* render_frame_host
,
774 const GURL
& validated_url
) override
;
776 void WaitForEnrollmentSuccess();
779 scoped_ptr
<policy::LocalPolicyTestServer
> test_server_
;
780 base::ScopedTempDir temp_dir_
;
782 scoped_ptr
<base::RunLoop
> run_loop_
;
783 content::RenderFrameHost
* auth_frame_
;
785 DISALLOW_COPY_AND_ASSIGN(SAMLEnrollmentTest
);
788 SAMLEnrollmentTest::SAMLEnrollmentTest() : auth_frame_(nullptr) {
789 gaia_frame_parent_
= "oauth-enroll-signin-frame";
792 SAMLEnrollmentTest::~SAMLEnrollmentTest() {
795 void SAMLEnrollmentTest::SetUp() {
796 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
797 const base::FilePath policy_file
=
798 temp_dir_
.path().AppendASCII("policy.json");
799 ASSERT_EQ(static_cast<int>(strlen(kPolicy
)),
800 base::WriteFile(policy_file
, kPolicy
, strlen(kPolicy
)));
802 test_server_
.reset(new policy::LocalPolicyTestServer(policy_file
));
803 ASSERT_TRUE(test_server_
->Start());
808 void SAMLEnrollmentTest::SetUpCommandLine(base::CommandLine
* command_line
) {
809 command_line
->AppendSwitchASCII(policy::switches::kDeviceManagementUrl
,
810 test_server_
->GetServiceURL().spec());
811 command_line
->AppendSwitch(policy::switches::kDisablePolicyKeyVerification
);
812 command_line
->AppendSwitch(switches::kEnterpriseEnrollmentSkipRobotAuth
);
814 SamlTest::SetUpCommandLine(command_line
);
817 void SAMLEnrollmentTest::SetUpOnMainThread() {
818 Observe(GetLoginUI()->GetWebContents());
820 FakeGaia::AccessTokenInfo token_info
;
821 token_info
.token
= kTestUserinfoToken
;
822 token_info
.scopes
.insert(GaiaConstants::kDeviceManagementServiceOAuth
);
823 token_info
.scopes
.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope
);
824 token_info
.audience
= GaiaUrls::GetInstance()->oauth2_chrome_client_id();
825 token_info
.email
= kFirstSAMLUserEmail
;
826 fake_gaia_
.IssueOAuthToken(kTestRefreshToken
, token_info
);
828 SamlTest::SetUpOnMainThread();
831 void SAMLEnrollmentTest::StartSamlAndWaitForIdpPageLoad(
832 const std::string
& gaia_email
) {
833 WaitForSigninScreen();
834 run_loop_
.reset(new base::RunLoop
);
835 ExistingUserController::current_controller()->OnStartEnterpriseEnrollment();
838 SetSignFormField("Email", gaia_email
);
840 run_loop_
.reset(new base::RunLoop
);
841 ExecuteJsInSigninFrame("document.getElementById('signIn').click();");
845 void SAMLEnrollmentTest::RenderFrameCreated(
846 content::RenderFrameHost
* render_frame_host
) {
847 content::RenderFrameHost
* parent
= render_frame_host
->GetParent();
848 if (!parent
|| parent
->GetFrameName() != gaia_frame_parent_
)
851 // The GAIA extension created the iframe in which the login form will be
852 // shown. Now wait for the login form to finish loading.
853 auth_frame_
= render_frame_host
;
854 Observe(content::WebContents::FromRenderFrameHost(auth_frame_
));
857 void SAMLEnrollmentTest::DidFinishLoad(
858 content::RenderFrameHost
* render_frame_host
,
859 const GURL
& validated_url
) {
860 if (render_frame_host
!= auth_frame_
)
863 const GURL origin
= validated_url
.GetOrigin();
864 if (origin
!= gaia_https_forwarder_
->GetURL("") &&
865 origin
!= saml_https_forwarder_
->GetURL("")) {
869 // The GAIA or SAML IdP login form finished loading.
874 // Waits until the class |oauth-enroll-state-success| becomes set for the
875 // enrollment screen, indicating enrollment success.
876 void SAMLEnrollmentTest::WaitForEnrollmentSuccess() {
878 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
879 GetLoginUI()->GetWebContents(),
880 "var enrollmentScreen = document.getElementById('oauth-enrollment');"
881 "function SendReplyIfEnrollmentDone() {"
882 " if (!enrollmentScreen.classList.contains("
883 " 'oauth-enroll-state-success')) {"
886 " domAutomationController.send(true);"
887 " observer.disconnect();"
890 "var observer = new MutationObserver(SendReplyIfEnrollmentDone);"
891 "if (!SendReplyIfEnrollmentDone()) {"
892 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
893 " observer.observe(enrollmentScreen, options);"
898 IN_PROC_BROWSER_TEST_P(SAMLEnrollmentTest
, WithoutCredentialsPassingAPI
) {
899 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
900 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
902 // Fill-in the SAML IdP form and submit.
903 SetSignFormField("Email", "fake_user");
904 SetSignFormField("Password", "fake_password");
905 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
907 WaitForEnrollmentSuccess();
910 IN_PROC_BROWSER_TEST_P(SAMLEnrollmentTest
, WithCredentialsPassingAPI
) {
911 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
912 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
913 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
915 // Fill-in the SAML IdP form and submit.
916 SetSignFormField("Email", "fake_user");
917 SetSignFormField("Password", "fake_password");
918 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
920 WaitForEnrollmentSuccess();
923 // TODO(xiyuan): Update once webview flow is implemented.
924 INSTANTIATE_TEST_CASE_P(SamlSuite
,
926 testing::Values(false));
928 class SAMLPolicyTest
: public SamlTest
{
931 ~SAMLPolicyTest() override
;
934 void SetUpInProcessBrowserTestFixture() override
;
935 void SetUpOnMainThread() override
;
937 void SetSAMLOfflineSigninTimeLimitPolicy(int limit
);
938 void EnableTransferSAMLCookiesPolicy();
940 void ShowGAIALoginForm();
941 void LogInWithSAML(const std::string
& user_id
,
942 const std::string
& auth_sid_cookie
,
943 const std::string
& auth_lsid_cookie
);
945 std::string
GetCookieValue(const std::string
& name
);
950 void GetCookiesOnIOThread(
951 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
952 const base::Closure
& callback
);
953 void StoreCookieList(const base::Closure
& callback
,
954 const net::CookieList
& cookie_list
);
956 policy::DevicePolicyCrosTestHelper test_helper_
;
958 // FakeDBusThreadManager uses FakeSessionManagerClient.
959 FakeSessionManagerClient
* fake_session_manager_client_
;
960 policy::DevicePolicyBuilder
* device_policy_
;
962 policy::MockConfigurationPolicyProvider provider_
;
964 net::CookieList cookie_list_
;
967 DISALLOW_COPY_AND_ASSIGN(SAMLPolicyTest
);
970 SAMLPolicyTest::SAMLPolicyTest()
971 : fake_session_manager_client_(new FakeSessionManagerClient
),
972 device_policy_(test_helper_
.device_policy()) {
975 SAMLPolicyTest::~SAMLPolicyTest() {
978 void SAMLPolicyTest::SetUpInProcessBrowserTestFixture() {
979 DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
980 scoped_ptr
<SessionManagerClient
>(fake_session_manager_client_
));
982 SamlTest::SetUpInProcessBrowserTestFixture();
984 // Initialize device policy.
985 test_helper_
.InstallOwnerKey();
986 test_helper_
.MarkAsEnterpriseOwned();
987 device_policy_
->SetDefaultSigningKey();
988 device_policy_
->Build();
989 fake_session_manager_client_
->set_device_policy(device_policy_
->GetBlob());
990 fake_session_manager_client_
->OnPropertyChangeComplete(true);
992 // Initialize user policy.
993 EXPECT_CALL(provider_
, IsInitializationComplete(_
))
994 .WillRepeatedly(Return(true));
995 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_
);
998 void SAMLPolicyTest::SetUpOnMainThread() {
999 SamlTest::SetUpOnMainThread();
1001 // Pretend that the test users' OAuth tokens are valid.
1002 user_manager::UserManager::Get()->SaveUserOAuthStatus(
1003 kFirstSAMLUserEmail
, user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
1004 user_manager::UserManager::Get()->SaveUserOAuthStatus(
1005 kNonSAMLUserEmail
, user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
1006 user_manager::UserManager::Get()->SaveUserOAuthStatus(
1007 kDifferentDomainSAMLUserEmail
,
1008 user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
1011 void SAMLPolicyTest::SetSAMLOfflineSigninTimeLimitPolicy(int limit
) {
1012 policy::PolicyMap user_policy
;
1013 user_policy
.Set(policy::key::kSAMLOfflineSigninTimeLimit
,
1014 policy::POLICY_LEVEL_MANDATORY
,
1015 policy::POLICY_SCOPE_USER
,
1016 new base::FundamentalValue(limit
),
1018 provider_
.UpdateChromePolicy(user_policy
);
1019 base::RunLoop().RunUntilIdle();
1022 void SAMLPolicyTest::EnableTransferSAMLCookiesPolicy() {
1023 em::ChromeDeviceSettingsProto
& proto(device_policy_
->payload());
1024 proto
.mutable_saml_settings()->set_transfer_saml_cookies(true);
1026 base::RunLoop run_loop
;
1027 scoped_ptr
<CrosSettings::ObserverSubscription
> observer
=
1028 CrosSettings::Get()->AddSettingsObserver(
1029 kAccountsPrefTransferSAMLCookies
,
1030 run_loop
.QuitClosure());
1031 device_policy_
->SetDefaultSigningKey();
1032 device_policy_
->Build();
1033 fake_session_manager_client_
->set_device_policy(device_policy_
->GetBlob());
1034 fake_session_manager_client_
->OnPropertyChangeComplete(true);
1038 void SAMLPolicyTest::ShowGAIALoginForm() {
1039 login_screen_load_observer_
->Wait();
1040 ASSERT_TRUE(content::ExecuteScript(
1041 GetLoginUI()->GetWebContents(),
1042 "$('gaia-signin').gaiaAuthHost_.addEventListener('ready', function() {"
1043 " window.domAutomationController.setAutomationId(0);"
1044 " window.domAutomationController.send('ready');"
1046 "$('add-user-button').click();"));
1047 content::DOMMessageQueue message_queue
;
1048 std::string message
;
1049 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
1050 EXPECT_EQ("\"ready\"", message
);
1053 void SAMLPolicyTest::LogInWithSAML(const std::string
& user_id
,
1054 const std::string
& auth_sid_cookie
,
1055 const std::string
& auth_lsid_cookie
) {
1056 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1057 StartSamlAndWaitForIdpPageLoad(user_id
);
1059 fake_gaia_
.SetFakeMergeSessionParams(
1060 user_id
, auth_sid_cookie
, auth_lsid_cookie
);
1061 SetSignFormField("Email", "fake_user");
1062 SetSignFormField("Password", "fake_password");
1063 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
1065 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
1067 content::WindowedNotificationObserver
session_start_waiter(
1068 chrome::NOTIFICATION_SESSION_STARTED
,
1069 content::NotificationService::AllSources());
1070 SendConfirmPassword("fake_password");
1071 session_start_waiter
.Wait();
1074 std::string
SAMLPolicyTest::GetCookieValue(const std::string
& name
) {
1075 for (net::CookieList::const_iterator it
= cookie_list_
.begin();
1076 it
!= cookie_list_
.end(); ++it
) {
1077 if (it
->Name() == name
)
1080 return std::string();
1083 void SAMLPolicyTest::GetCookies() {
1084 Profile
* profile
= chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(
1085 user_manager::UserManager::Get()->GetActiveUser());
1086 ASSERT_TRUE(profile
);
1087 base::RunLoop run_loop
;
1088 content::BrowserThread::PostTask(
1089 content::BrowserThread::IO
,
1091 base::Bind(&SAMLPolicyTest::GetCookiesOnIOThread
,
1092 base::Unretained(this),
1093 scoped_refptr
<net::URLRequestContextGetter
>(
1094 profile
->GetRequestContext()),
1095 run_loop
.QuitClosure()));
1099 void SAMLPolicyTest::GetCookiesOnIOThread(
1100 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
1101 const base::Closure
& callback
) {
1102 request_context
->GetURLRequestContext()->cookie_store()->
1103 GetCookieMonster()->GetAllCookiesAsync(base::Bind(
1104 &SAMLPolicyTest::StoreCookieList
,
1105 base::Unretained(this),
1109 void SAMLPolicyTest::StoreCookieList(
1110 const base::Closure
& callback
,
1111 const net::CookieList
& cookie_list
) {
1112 cookie_list_
= cookie_list
;
1113 content::BrowserThread::PostTask(content::BrowserThread::UI
,
1118 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_NoSAML
) {
1119 // Set the offline login time limit for SAML users to zero.
1120 SetSAMLOfflineSigninTimeLimitPolicy(0);
1122 WaitForSigninScreen();
1124 // Log in without SAML.
1125 GetLoginDisplay()->ShowSigninScreenForCreds(kNonSAMLUserEmail
, "password");
1127 content::WindowedNotificationObserver(
1128 chrome::NOTIFICATION_SESSION_STARTED
,
1129 content::NotificationService::AllSources()).Wait();
1132 // Verifies that the offline login time limit does not affect a user who
1133 // authenticated without SAML.
1134 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, NoSAML
) {
1135 login_screen_load_observer_
->Wait();
1136 // Verify that offline login is allowed.
1137 JsExpect("window.getComputedStyle(document.querySelector("
1138 " '#pod-row .signin-button-container')).display == 'none'");
1141 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_SAMLNoLimit
) {
1142 // Remove the offline login time limit for SAML users.
1143 SetSAMLOfflineSigninTimeLimitPolicy(-1);
1145 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1148 // Verifies that when no offline login time limit is set, a user who
1149 // authenticated with SAML is allowed to log in offline.
1150 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, SAMLNoLimit
) {
1151 login_screen_load_observer_
->Wait();
1152 // Verify that offline login is allowed.
1153 JsExpect("window.getComputedStyle(document.querySelector("
1154 " '#pod-row .signin-button-container')).display == 'none'");
1157 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_SAMLZeroLimit
) {
1158 // Set the offline login time limit for SAML users to zero.
1159 SetSAMLOfflineSigninTimeLimitPolicy(0);
1161 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1164 // Verifies that when the offline login time limit is exceeded for a user who
1165 // authenticated via SAML, that user is forced to log in online the next time.
1166 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, SAMLZeroLimit
) {
1167 login_screen_load_observer_
->Wait();
1168 // Verify that offline login is not allowed.
1169 JsExpect("window.getComputedStyle(document.querySelector("
1170 " '#pod-row .signin-button-container')).display != 'none'");
1173 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_PRE_TransferCookiesAffiliated
) {
1174 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1
);
1175 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1178 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1179 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1180 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1183 // Verifies that when the DeviceTransferSAMLCookies policy is not enabled, SAML
1184 // IdP cookies are not transferred to a user's profile on subsequent login, even
1185 // if the user belongs to the domain that the device is enrolled into. Also
1186 // verifies that GAIA cookies are not transferred.
1187 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_TransferCookiesAffiliated
) {
1188 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1189 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1190 ShowGAIALoginForm();
1191 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie2
, kTestAuthLSIDCookie2
);
1194 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1195 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1196 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1199 // Verifies that when the DeviceTransferSAMLCookies policy is enabled, SAML IdP
1200 // cookies are transferred to a user's profile on subsequent login when the user
1201 // belongs to the domain that the device is enrolled into. Also verifies that
1202 // GAIA cookies are not transferred.
1203 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, TransferCookiesAffiliated
) {
1204 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1205 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1206 ShowGAIALoginForm();
1208 EnableTransferSAMLCookiesPolicy();
1209 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie2
, kTestAuthLSIDCookie2
);
1212 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1213 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1214 EXPECT_EQ(kSAMLIdPCookieValue2
, GetCookieValue(kSAMLIdPCookieName
));
1217 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_TransferCookiesUnaffiliated
) {
1218 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1
);
1219 LogInWithSAML(kDifferentDomainSAMLUserEmail
,
1220 kTestAuthSIDCookie1
,
1221 kTestAuthLSIDCookie1
);
1224 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1225 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1226 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1229 // Verifies that even if the DeviceTransferSAMLCookies policy is enabled, SAML
1230 // IdP are not transferred to a user's profile on subsequent login if the user
1231 // does not belong to the domain that the device is enrolled into. Also verifies
1232 // that GAIA cookies are not transferred.
1233 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, TransferCookiesUnaffiliated
) {
1234 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1235 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1236 ShowGAIALoginForm();
1238 EnableTransferSAMLCookiesPolicy();
1239 LogInWithSAML(kDifferentDomainSAMLUserEmail
,
1240 kTestAuthSIDCookie1
,
1241 kTestAuthLSIDCookie1
);
1244 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1245 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1246 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1249 INSTANTIATE_TEST_CASE_P(SamlSuite
,
1253 } // namespace chromeos