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.
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/json/json_file_value_serializer.h"
16 #include "base/location.h"
17 #include "base/macros.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/path_service.h"
21 #include "base/run_loop.h"
22 #include "base/strings/string16.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/values.h"
27 #include "chrome/browser/chrome_notification_types.h"
28 #include "chrome/browser/chromeos/login/existing_user_controller.h"
29 #include "chrome/browser/chromeos/login/startup_utils.h"
30 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
31 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
32 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
33 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
34 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
35 #include "chrome/browser/chromeos/login/wizard_controller.h"
36 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
37 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
38 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
39 #include "chrome/browser/chromeos/profiles/profile_helper.h"
40 #include "chrome/browser/chromeos/settings/cros_settings.h"
41 #include "chrome/browser/policy/test/local_policy_test_server.h"
42 #include "chrome/browser/profiles/profile.h"
43 #include "chrome/browser/ui/webui/signin/inline_login_ui.h"
44 #include "chrome/common/chrome_constants.h"
45 #include "chrome/common/chrome_paths.h"
46 #include "chrome/common/chrome_switches.h"
47 #include "chrome/common/extensions/features/feature_channel.h"
48 #include "chrome/common/pref_names.h"
49 #include "chrome/grit/generated_resources.h"
50 #include "chrome/test/base/in_process_browser_test.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "chromeos/cryptohome/system_salt_getter.h"
53 #include "chromeos/dbus/cryptohome/key.pb.h"
54 #include "chromeos/dbus/cryptohome/rpc.pb.h"
55 #include "chromeos/dbus/cryptohome_client.h"
56 #include "chromeos/dbus/dbus_thread_manager.h"
57 #include "chromeos/dbus/fake_cryptohome_client.h"
58 #include "chromeos/dbus/fake_session_manager_client.h"
59 #include "chromeos/dbus/session_manager_client.h"
60 #include "chromeos/dbus/shill_manager_client.h"
61 #include "chromeos/login/auth/key.h"
62 #include "chromeos/settings/cros_settings_names.h"
63 #include "components/policy/core/browser/browser_policy_connector.h"
64 #include "components/policy/core/common/mock_configuration_policy_provider.h"
65 #include "components/policy/core/common/policy_map.h"
66 #include "components/policy/core/common/policy_switches.h"
67 #include "components/policy/core/common/policy_types.h"
68 #include "components/user_manager/user.h"
69 #include "components/user_manager/user_manager.h"
70 #include "content/public/browser/browser_thread.h"
71 #include "content/public/browser/render_frame_host.h"
72 #include "content/public/browser/web_contents.h"
73 #include "content/public/browser/web_contents_observer.h"
74 #include "content/public/test/browser_test_utils.h"
75 #include "content/public/test/test_utils.h"
76 #include "google_apis/gaia/fake_gaia.h"
77 #include "google_apis/gaia/gaia_constants.h"
78 #include "google_apis/gaia/gaia_switches.h"
79 #include "google_apis/gaia/gaia_urls.h"
80 #include "net/base/url_util.h"
81 #include "net/cookies/canonical_cookie.h"
82 #include "net/cookies/cookie_monster.h"
83 #include "net/cookies/cookie_store.h"
84 #include "net/dns/mock_host_resolver.h"
85 #include "net/test/embedded_test_server/embedded_test_server.h"
86 #include "net/test/embedded_test_server/http_request.h"
87 #include "net/test/embedded_test_server/http_response.h"
88 #include "net/url_request/url_request_context.h"
89 #include "net/url_request/url_request_context_getter.h"
90 #include "policy/policy_constants.h"
91 #include "policy/proto/device_management_backend.pb.h"
92 #include "testing/gmock/include/gmock/gmock.h"
93 #include "testing/gtest/include/gtest/gtest.h"
94 #include "ui/base/l10n/l10n_util.h"
97 namespace em
= enterprise_management
;
99 using net::test_server::BasicHttpResponse
;
100 using net::test_server::HttpRequest
;
101 using net::test_server::HttpResponse
;
102 using testing::Return
;
109 const char kGAIASIDCookieName
[] = "SID";
110 const char kGAIALSIDCookieName
[] = "LSID";
112 const char kTestAuthSIDCookie1
[] = "fake-auth-SID-cookie-1";
113 const char kTestAuthSIDCookie2
[] = "fake-auth-SID-cookie-2";
114 const char kTestAuthLSIDCookie1
[] = "fake-auth-LSID-cookie-1";
115 const char kTestAuthLSIDCookie2
[] = "fake-auth-LSID-cookie-2";
117 const char kFirstSAMLUserEmail
[] = "bob@example.com";
118 const char kSecondSAMLUserEmail
[] = "alice@example.com";
119 const char kHTTPSAMLUserEmail
[] = "carol@example.com";
120 const char kNonSAMLUserEmail
[] = "dan@example.com";
121 const char kDifferentDomainSAMLUserEmail
[] = "eve@example.test";
123 const char kIdPHost
[] = "login.example.com";
124 const char kAdditionalIdPHost
[] = "login2.example.com";
126 const char kSAMLIdPCookieName
[] = "saml";
127 const char kSAMLIdPCookieValue1
[] = "value-1";
128 const char kSAMLIdPCookieValue2
[] = "value-2";
130 const char kRelayState
[] = "RelayState";
132 const char kTestUserinfoToken
[] = "fake-userinfo-token";
133 const char kTestRefreshToken
[] = "fake-refresh-token";
134 const char kPolicy
[] = "{\"managed_users\": [\"*\"]}";
136 // FakeSamlIdp serves IdP auth form and the form submission. The form is
137 // served with the template's RelayState placeholder expanded to the real
138 // RelayState parameter from request. The form submission redirects back to
139 // FakeGaia with the same RelayState.
145 void SetUp(const std::string
& base_path
, const GURL
& gaia_url
);
147 void SetLoginHTMLTemplate(const std::string
& template_file
);
148 void SetLoginAuthHTMLTemplate(const std::string
& template_file
);
149 void SetRefreshURL(const GURL
& refresh_url
);
150 void SetCookieValue(const std::string
& cookie_value
);
152 scoped_ptr
<HttpResponse
> HandleRequest(const HttpRequest
& request
);
155 scoped_ptr
<HttpResponse
> BuildHTMLResponse(const std::string
& html_template
,
156 const std::string
& relay_state
,
157 const std::string
& next_path
);
159 base::FilePath html_template_dir_
;
161 std::string login_path_
;
162 std::string login_auth_path_
;
164 std::string login_html_template_
;
165 std::string login_auth_html_template_
;
166 GURL gaia_assertion_url_
;
168 std::string cookie_value_
;
170 DISALLOW_COPY_AND_ASSIGN(FakeSamlIdp
);
173 FakeSamlIdp::FakeSamlIdp() {
176 FakeSamlIdp::~FakeSamlIdp() {
179 void FakeSamlIdp::SetUp(const std::string
& base_path
, const GURL
& gaia_url
) {
180 base::FilePath test_data_dir
;
181 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
182 html_template_dir_
= test_data_dir
.Append("login");
184 login_path_
= base_path
;
185 login_auth_path_
= base_path
+ "Auth";
186 gaia_assertion_url_
= gaia_url
.Resolve("/SSO");
189 void FakeSamlIdp::SetLoginHTMLTemplate(const std::string
& template_file
) {
190 EXPECT_TRUE(base::ReadFileToString(
191 html_template_dir_
.Append(template_file
),
192 &login_html_template_
));
195 void FakeSamlIdp::SetLoginAuthHTMLTemplate(const std::string
& template_file
) {
196 EXPECT_TRUE(base::ReadFileToString(
197 html_template_dir_
.Append(template_file
),
198 &login_auth_html_template_
));
201 void FakeSamlIdp::SetRefreshURL(const GURL
& refresh_url
) {
202 refresh_url_
= refresh_url
;
205 void FakeSamlIdp::SetCookieValue(const std::string
& cookie_value
) {
206 cookie_value_
= cookie_value
;
209 scoped_ptr
<HttpResponse
> FakeSamlIdp::HandleRequest(
210 const HttpRequest
& request
) {
211 // The scheme and host of the URL is actually not important but required to
212 // get a valid GURL in order to parse |request.relative_url|.
213 GURL request_url
= GURL("http://localhost").Resolve(request
.relative_url
);
214 std::string request_path
= request_url
.path();
216 if (request_path
== login_path_
) {
217 std::string relay_state
;
218 net::GetValueForKeyInQuery(request_url
, kRelayState
, &relay_state
);
219 return BuildHTMLResponse(login_html_template_
,
224 if (request_path
!= login_auth_path_
) {
225 // Request not understood.
226 return scoped_ptr
<HttpResponse
>();
229 std::string relay_state
;
230 FakeGaia::GetQueryParameter(request
.content
, kRelayState
, &relay_state
);
231 GURL redirect_url
= gaia_assertion_url_
;
233 if (!login_auth_html_template_
.empty()) {
234 return BuildHTMLResponse(login_auth_html_template_
,
236 redirect_url
.spec());
239 redirect_url
= net::AppendQueryParameter(
240 redirect_url
, "SAMLResponse", "fake_response");
241 redirect_url
= net::AppendQueryParameter(
242 redirect_url
, kRelayState
, relay_state
);
244 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse());
245 http_response
->set_code(net::HTTP_TEMPORARY_REDIRECT
);
246 http_response
->AddCustomHeader("Location", redirect_url
.spec());
247 http_response
->AddCustomHeader(
249 base::StringPrintf("saml=%s", cookie_value_
.c_str()));
250 return http_response
.Pass();
253 scoped_ptr
<HttpResponse
> FakeSamlIdp::BuildHTMLResponse(
254 const std::string
& html_template
,
255 const std::string
& relay_state
,
256 const std::string
& next_path
) {
257 std::string response_html
= html_template
;
258 base::ReplaceSubstringsAfterOffset(
259 &response_html
, 0, "$RelayState", relay_state
);
260 base::ReplaceSubstringsAfterOffset(
261 &response_html
, 0, "$Post", next_path
);
262 base::ReplaceSubstringsAfterOffset(
263 &response_html
, 0, "$Refresh", refresh_url_
.spec());
265 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse());
266 http_response
->set_code(net::HTTP_OK
);
267 http_response
->set_content(response_html
);
268 http_response
->set_content_type("text/html");
270 return http_response
.Pass();
273 // A FakeCryptohomeClient that stores the salted and hashed secret passed to
275 class SecretInterceptingFakeCryptohomeClient
: public FakeCryptohomeClient
{
277 SecretInterceptingFakeCryptohomeClient();
279 void MountEx(const cryptohome::AccountIdentifier
& id
,
280 const cryptohome::AuthorizationRequest
& auth
,
281 const cryptohome::MountRequest
& request
,
282 const ProtobufMethodCallback
& callback
) override
;
284 const std::string
& salted_hashed_secret() { return salted_hashed_secret_
; }
287 std::string salted_hashed_secret_
;
289 DISALLOW_COPY_AND_ASSIGN(SecretInterceptingFakeCryptohomeClient
);
292 SecretInterceptingFakeCryptohomeClient::
293 SecretInterceptingFakeCryptohomeClient() {
296 void SecretInterceptingFakeCryptohomeClient::MountEx(
297 const cryptohome::AccountIdentifier
& id
,
298 const cryptohome::AuthorizationRequest
& auth
,
299 const cryptohome::MountRequest
& request
,
300 const ProtobufMethodCallback
& callback
) {
301 salted_hashed_secret_
= auth
.key().secret();
302 FakeCryptohomeClient::MountEx(id
, auth
, request
, callback
);
307 // Boolean parameter is used to run this test for webview (true) and for
308 // iframe (false) GAIA sign in.
309 class SamlTest
: public OobeBaseTest
, public testing::WithParamInterface
<bool> {
311 SamlTest() : cryptohome_client_(new SecretInterceptingFakeCryptohomeClient
) {
312 set_use_webview(GetParam());
313 set_initialize_fake_merge_session(false);
315 ~SamlTest() override
{}
317 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
318 command_line
->AppendSwitch(switches::kOobeSkipPostLogin
);
320 const GURL gaia_url
= gaia_https_forwarder_
.GetURLForSSLHost("");
321 const GURL saml_idp_url
= saml_https_forwarder_
.GetURLForSSLHost("SAML");
322 fake_saml_idp_
.SetUp(saml_idp_url
.path(), gaia_url
);
323 fake_gaia_
->RegisterSamlUser(kFirstSAMLUserEmail
, saml_idp_url
);
324 fake_gaia_
->RegisterSamlUser(kSecondSAMLUserEmail
, saml_idp_url
);
325 fake_gaia_
->RegisterSamlUser(
327 embedded_test_server()->base_url().Resolve("/SAML"));
328 fake_gaia_
->RegisterSamlUser(kDifferentDomainSAMLUserEmail
, saml_idp_url
);
330 OobeBaseTest::SetUpCommandLine(command_line
);
333 void SetUpInProcessBrowserTestFixture() override
{
334 DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
335 scoped_ptr
<CryptohomeClient
>(cryptohome_client_
));
337 OobeBaseTest::SetUpInProcessBrowserTestFixture();
340 void SetUpOnMainThread() override
{
341 fake_gaia_
->SetFakeMergeSessionParams(
342 kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
344 embedded_test_server()->RegisterRequestHandler(base::Bind(
345 &FakeSamlIdp::HandleRequest
, base::Unretained(&fake_saml_idp_
)));
347 OobeBaseTest::SetUpOnMainThread();
350 void SetupAuthFlowChangeListener() {
351 ASSERT_TRUE(content::ExecuteScript(
352 GetLoginUI()->GetWebContents(),
353 "$('gaia-signin').gaiaAuthHost_.addEventListener('authFlowChange',"
355 "$('gaia-signin').gaiaAuthHost_.removeEventListener("
356 "'authFlowChange', f);"
357 "window.domAutomationController.setAutomationId(0);"
358 "window.domAutomationController.send("
359 "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');"
363 virtual void StartSamlAndWaitForIdpPageLoad(const std::string
& gaia_email
) {
364 WaitForSigninScreen();
366 SetupAuthFlowChangeListener();
368 content::DOMMessageQueue message_queue
; // Start observe before SAML.
369 GetLoginDisplay()->ShowSigninScreenForCreds(gaia_email
, "");
372 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
373 EXPECT_EQ("\"SamlLoaded\"", message
);
376 void SendConfirmPassword(const std::string
& password_to_confirm
) {
378 "$('confirm-password-input').value='$Password';"
379 "$('confirm-password').onConfirmPassword_();";
380 base::ReplaceSubstringsAfterOffset(
381 &js
, 0, "$Password", password_to_confirm
);
382 ASSERT_TRUE(content::ExecuteScript(GetLoginUI()->GetWebContents(), js
));
385 std::string
WaitForAndGetFatalErrorMessage() {
386 OobeScreenWaiter(OobeDisplay::SCREEN_FATAL_ERROR
).Wait();
387 std::string message_element
=
388 use_webview() ? "$('fatal-error-card')" : "$('fatal-error-message')";
389 std::string error_message
;
390 if (!content::ExecuteScriptAndExtractString(
391 GetLoginUI()->GetWebContents(),
392 "window.domAutomationController.send(" + message_element
+
397 return error_message
;
400 FakeSamlIdp
* fake_saml_idp() { return &fake_saml_idp_
; }
403 void InitHttpsForwarders() override
{
404 ASSERT_TRUE(saml_https_forwarder_
.Initialize(
405 kIdPHost
, embedded_test_server()->base_url()));
406 OobeBaseTest::InitHttpsForwarders();
409 HTTPSForwarder saml_https_forwarder_
;
411 SecretInterceptingFakeCryptohomeClient
* cryptohome_client_
;
414 FakeSamlIdp fake_saml_idp_
;
416 DISALLOW_COPY_AND_ASSIGN(SamlTest
);
419 // Tests that signin frame should have 'saml' class and 'cancel' button is
420 // visible when SAML IdP page is loaded. And 'cancel' button goes back to
423 // Times out on CrOS MSAN. https://crbug.com/504141
424 #if defined(MEMORY_SANITIZER)
425 #define MAYBE_SamlUI DISABLED_SamlUI
427 #define MAYBE_SamlUI SamlUI
429 IN_PROC_BROWSER_TEST_P(SamlTest
, MAYBE_SamlUI
) {
430 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
431 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
433 // Saml flow UI expectations.
434 JsExpect("$('gaia-signin').classList.contains('full-width')");
435 JsExpect("!$('saml-notice-container').hidden");
436 std::string js
= "$('saml-notice-message').textContent.indexOf('$Host') > -1";
437 base::ReplaceSubstringsAfterOffset(&js
, 0, "$Host", kIdPHost
);
439 if (!use_webview()) {
440 JsExpect("!$('cancel-add-user-button').hidden");
443 SetupAuthFlowChangeListener();
445 // Click on 'cancel'.
446 content::DOMMessageQueue message_queue
; // Observe before 'cancel'.
448 ASSERT_TRUE(content::ExecuteScript(
449 GetLoginUI()->GetWebContents(),
450 "$('close-button-item').click();"));
452 ASSERT_TRUE(content::ExecuteScript(
453 GetLoginUI()->GetWebContents(),
454 "$('cancel-add-user-button').click();"));
457 // Auth flow should change back to Gaia.
460 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
461 } while (message
!= "\"GaiaLoaded\"");
463 // Saml flow is gone.
464 JsExpect("!$('gaia-signin').classList.contains('full-width')");
467 // Tests the sign-in flow when the credentials passing API is used.
468 IN_PROC_BROWSER_TEST_P(SamlTest
, CredentialPassingAPI
) {
469 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
470 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
471 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
473 content::WindowedNotificationObserver
session_start_waiter(
474 chrome::NOTIFICATION_SESSION_STARTED
,
475 content::NotificationService::AllSources());
477 // Fill-in the SAML IdP form and submit.
478 SetSignFormField("Email", "fake_user");
479 SetSignFormField("Dummy", "not_the_password");
480 SetSignFormField("Password", "actual_password");
481 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
483 // Login should finish login and a session should start.
484 session_start_waiter
.Wait();
486 // Regression test for http://crbug.com/490737: Verify that the user's actual
487 // password was used, not the contents of the first type=password input field
488 // found on the page.
489 Key
key("actual_password");
490 key
.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF
,
491 SystemSaltGetter::ConvertRawSaltToHexString(
492 FakeCryptohomeClient::GetStubSystemSalt()));
493 EXPECT_EQ(key
.GetSecret(), cryptohome_client_
->salted_hashed_secret());
496 // Tests the single password scraped flow.
497 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedSingle
) {
498 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
499 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
501 // Fill-in the SAML IdP form and submit.
502 SetSignFormField("Email", "fake_user");
503 SetSignFormField("Password", "fake_password");
504 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
506 // Lands on confirm password screen.
507 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
509 // Entering an unknown password should go back to the confirm password screen.
510 SendConfirmPassword("wrong_password");
511 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
513 // Entering a known password should finish login and start session.
514 content::WindowedNotificationObserver
session_start_waiter(
515 chrome::NOTIFICATION_SESSION_STARTED
,
516 content::NotificationService::AllSources());
517 SendConfirmPassword("fake_password");
518 session_start_waiter
.Wait();
521 // Tests password scraping from a dynamically created password field.
522 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedDynamic
) {
523 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
524 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
526 ExecuteJsInSigninFrame(
528 "var newPassInput = document.createElement('input');"
529 "newPassInput.id = 'DynamicallyCreatedPassword';"
530 "newPassInput.type = 'password';"
531 "newPassInput.name = 'Password';"
532 "document.forms[0].appendChild(newPassInput);"
535 // Fill-in the SAML IdP form and submit.
536 SetSignFormField("Email", "fake_user");
537 SetSignFormField("DynamicallyCreatedPassword", "fake_password");
538 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
540 // Lands on confirm password screen.
541 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
543 // Entering an unknown password should go back to the confirm password screen.
544 SendConfirmPassword("wrong_password");
545 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
547 // Entering a known password should finish login and start session.
548 content::WindowedNotificationObserver
session_start_waiter(
549 chrome::NOTIFICATION_SESSION_STARTED
,
550 content::NotificationService::AllSources());
551 SendConfirmPassword("fake_password");
552 session_start_waiter
.Wait();
555 // Tests the multiple password scraped flow.
556 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedMultiple
) {
557 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html");
559 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
561 SetSignFormField("Email", "fake_user");
562 SetSignFormField("Password", "fake_password");
563 SetSignFormField("Password1", "password1");
564 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
566 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
568 // Either scraped password should be able to sign-in.
569 content::WindowedNotificationObserver
session_start_waiter(
570 chrome::NOTIFICATION_SESSION_STARTED
,
571 content::NotificationService::AllSources());
572 SendConfirmPassword("password1");
573 session_start_waiter
.Wait();
576 // Tests the no password scraped flow.
577 IN_PROC_BROWSER_TEST_P(SamlTest
, ScrapedNone
) {
578 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_no_passwords.html");
580 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
582 SetSignFormField("Email", "fake_user");
583 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
585 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_PASSWORD
),
586 WaitForAndGetFatalErrorMessage());
589 // Types |bob@example.com| into the GAIA login form but then authenticates as
590 // |alice@example.com| via SAML. Verifies that the logged-in user is correctly
591 // identified as Alice.
592 IN_PROC_BROWSER_TEST_P(SamlTest
, UseAutenticatedUserEmailAddress
) {
593 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
594 // Type |bob@example.com| into the GAIA login form.
595 StartSamlAndWaitForIdpPageLoad(kSecondSAMLUserEmail
);
597 // Authenticate as alice@example.com via SAML (the |Email| provided here is
598 // irrelevant - the authenticated user's e-mail address that FakeGAIA
599 // reports was set via |SetFakeMergeSessionParams|.
600 SetSignFormField("Email", "fake_user");
601 SetSignFormField("Password", "fake_password");
602 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
604 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
606 content::WindowedNotificationObserver
session_start_waiter(
607 chrome::NOTIFICATION_SESSION_STARTED
,
608 content::NotificationService::AllSources());
609 SendConfirmPassword("fake_password");
610 session_start_waiter
.Wait();
611 const user_manager::User
* user
=
612 user_manager::UserManager::Get()->GetActiveUser();
614 EXPECT_EQ(kFirstSAMLUserEmail
, user
->email());
617 // Verifies that if the authenticated user's e-mail address cannot be retrieved,
618 // an error message is shown.
619 IN_PROC_BROWSER_TEST_P(SamlTest
, FailToRetrieveAutenticatedUserEmailAddress
) {
620 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
621 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
623 fake_gaia_
->SetFakeMergeSessionParams("", kTestAuthSIDCookie1
,
624 kTestAuthLSIDCookie1
);
625 SetSignFormField("Email", "fake_user");
626 SetSignFormField("Password", "fake_password");
627 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
629 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_ACCOUNT_DETAILS
),
630 WaitForAndGetFatalErrorMessage());
633 // Tests the password confirm flow: show error on the first failure and
634 // fatal error on the second failure.
635 IN_PROC_BROWSER_TEST_P(SamlTest
, PasswordConfirmFlow
) {
636 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
637 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
639 // Fill-in the SAML IdP form and submit.
640 SetSignFormField("Email", "fake_user");
641 SetSignFormField("Password", "fake_password");
642 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
644 // Lands on confirm password screen with no error message.
645 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
646 JsExpect("!$('confirm-password').classList.contains('error')");
648 // Enter an unknown password for the first time should go back to confirm
649 // password screen with error message.
650 SendConfirmPassword("wrong_password");
651 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
652 JsExpect("$('confirm-password').classList.contains('error')");
654 // Enter an unknown password 2nd time should go back fatal error message.
655 SendConfirmPassword("wrong_password");
657 l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_PASSWORD_VERIFICATION
),
658 WaitForAndGetFatalErrorMessage());
661 // Verifies that when the login flow redirects from one host to another, the
662 // notice shown to the user is updated. This guards against regressions of
663 // http://crbug.com/447818.
664 IN_PROC_BROWSER_TEST_P(SamlTest
, NoticeUpdatedOnRedirect
) {
665 // Start another https server at |kAdditionalIdPHost|.
666 HTTPSForwarder saml_https_forwarder_2
;
667 ASSERT_TRUE(saml_https_forwarder_2
.Initialize(
668 kAdditionalIdPHost
, embedded_test_server()->base_url()));
670 // Make the login flow redirect to |kAdditionalIdPHost|.
671 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html");
672 fake_saml_idp()->SetRefreshURL(
673 saml_https_forwarder_2
.GetURLForSSLHost("simple.html"));
674 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
676 // Wait until the notice shown to the user is updated to contain
677 // |kAdditionalIdPHost|.
679 "var sendIfHostFound = function() {"
681 " $('saml-notice-message').textContent.indexOf('$Host') > -1;"
683 " window.domAutomationController.send(true);"
686 "var processEventsAndSendIfHostFound = function() {"
687 " window.setTimeout(function() {"
688 " if (sendIfHostFound()) {"
689 " $('gaia-signin').gaiaAuthHost_.removeEventListener("
690 " 'authDomainChange',"
691 " processEventsAndSendIfHostFound);"
695 "if (!sendIfHostFound()) {"
696 " $('gaia-signin').gaiaAuthHost_.addEventListener("
697 " 'authDomainChange',"
698 " processEventsAndSendIfHostFound);"
700 base::ReplaceSubstringsAfterOffset(&js
, 0, "$Host", kAdditionalIdPHost
);
702 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
703 GetLoginUI()->GetWebContents(), js
, &dummy
));
705 // Verify that the notice is visible.
706 JsExpect("!$('saml-notice-container').hidden");
709 // Verifies that when GAIA attempts to redirect to a SAML IdP served over http,
710 // not https, the redirect is blocked and an error message is shown.
711 IN_PROC_BROWSER_TEST_P(SamlTest
, HTTPRedirectDisallowed
) {
712 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
714 WaitForSigninScreen();
715 GetLoginDisplay()->ShowSigninScreenForCreds(kHTTPSAMLUserEmail
, "");
717 const GURL url
= embedded_test_server()->base_url().Resolve("/SAML");
718 EXPECT_EQ(l10n_util::GetStringFUTF8(
719 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL
,
720 base::UTF8ToUTF16(url
.spec())),
721 WaitForAndGetFatalErrorMessage());
724 // Verifies that when GAIA attempts to redirect to a page served over http, not
725 // https, via an HTML meta refresh, the redirect is blocked and an error message
726 // is shown. This guards against regressions of http://crbug.com/359515.
727 IN_PROC_BROWSER_TEST_P(SamlTest
, MetaRefreshToHTTPDisallowed
) {
728 const GURL url
= embedded_test_server()->base_url().Resolve("/SSO");
729 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html");
730 fake_saml_idp()->SetRefreshURL(url
);
732 WaitForSigninScreen();
733 GetLoginDisplay()->ShowSigninScreenForCreds(kFirstSAMLUserEmail
, "");
735 EXPECT_EQ(l10n_util::GetStringFUTF8(
736 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL
,
737 base::UTF8ToUTF16(url
.spec())),
738 WaitForAndGetFatalErrorMessage());
741 INSTANTIATE_TEST_CASE_P(SamlSuite
,
745 class SAMLEnrollmentTest
: public SamlTest
,
746 public content::WebContentsObserver
{
748 SAMLEnrollmentTest();
749 ~SAMLEnrollmentTest() override
;
752 void SetUp() override
;
753 void SetUpCommandLine(base::CommandLine
* command_line
) override
;
754 void SetUpOnMainThread() override
;
755 void StartSamlAndWaitForIdpPageLoad(const std::string
& gaia_email
) override
;
757 // content::WebContentsObserver:
758 void RenderFrameCreated(content::RenderFrameHost
* render_frame_host
) override
;
759 void DidFinishLoad(content::RenderFrameHost
* render_frame_host
,
760 const GURL
& validated_url
) override
;
762 void WaitForEnrollmentSuccess();
765 scoped_ptr
<policy::LocalPolicyTestServer
> test_server_
;
766 base::ScopedTempDir temp_dir_
;
768 scoped_ptr
<base::RunLoop
> run_loop_
;
769 content::RenderFrameHost
* auth_frame_
;
771 DISALLOW_COPY_AND_ASSIGN(SAMLEnrollmentTest
);
774 SAMLEnrollmentTest::SAMLEnrollmentTest() : auth_frame_(nullptr) {
775 gaia_frame_parent_
= "oauth-enroll-signin-frame";
778 SAMLEnrollmentTest::~SAMLEnrollmentTest() {
781 void SAMLEnrollmentTest::SetUp() {
782 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
783 const base::FilePath policy_file
=
784 temp_dir_
.path().AppendASCII("policy.json");
785 ASSERT_EQ(static_cast<int>(strlen(kPolicy
)),
786 base::WriteFile(policy_file
, kPolicy
, strlen(kPolicy
)));
788 test_server_
.reset(new policy::LocalPolicyTestServer(policy_file
));
789 ASSERT_TRUE(test_server_
->Start());
794 void SAMLEnrollmentTest::SetUpCommandLine(base::CommandLine
* command_line
) {
795 command_line
->AppendSwitchASCII(policy::switches::kDeviceManagementUrl
,
796 test_server_
->GetServiceURL().spec());
797 command_line
->AppendSwitch(policy::switches::kDisablePolicyKeyVerification
);
799 SamlTest::SetUpCommandLine(command_line
);
802 void SAMLEnrollmentTest::SetUpOnMainThread() {
803 Observe(GetLoginUI()->GetWebContents());
805 FakeGaia::AccessTokenInfo token_info
;
806 token_info
.token
= kTestUserinfoToken
;
807 token_info
.scopes
.insert(GaiaConstants::kDeviceManagementServiceOAuth
);
808 token_info
.scopes
.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope
);
809 token_info
.audience
= GaiaUrls::GetInstance()->oauth2_chrome_client_id();
810 token_info
.email
= kFirstSAMLUserEmail
;
811 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, token_info
);
813 SamlTest::SetUpOnMainThread();
816 void SAMLEnrollmentTest::StartSamlAndWaitForIdpPageLoad(
817 const std::string
& gaia_email
) {
818 WaitForSigninScreen();
819 run_loop_
.reset(new base::RunLoop
);
820 ExistingUserController::current_controller()->OnStartEnterpriseEnrollment();
823 SetSignFormField("Email", gaia_email
);
825 run_loop_
.reset(new base::RunLoop
);
826 ExecuteJsInSigninFrame("document.getElementById('signIn').click();");
830 void SAMLEnrollmentTest::RenderFrameCreated(
831 content::RenderFrameHost
* render_frame_host
) {
832 content::RenderFrameHost
* parent
= render_frame_host
->GetParent();
833 if (!parent
|| parent
->GetFrameName() != gaia_frame_parent_
)
836 // The GAIA extension created the iframe in which the login form will be
837 // shown. Now wait for the login form to finish loading.
838 auth_frame_
= render_frame_host
;
839 Observe(content::WebContents::FromRenderFrameHost(auth_frame_
));
842 void SAMLEnrollmentTest::DidFinishLoad(
843 content::RenderFrameHost
* render_frame_host
,
844 const GURL
& validated_url
) {
845 if (render_frame_host
!= auth_frame_
)
848 const GURL origin
= validated_url
.GetOrigin();
849 if (origin
!= gaia_https_forwarder_
.GetURLForSSLHost(std::string()) &&
850 origin
!= saml_https_forwarder_
.GetURLForSSLHost(std::string())) {
854 // The GAIA or SAML IdP login form finished loading.
859 // Waits until the class |oauth-enroll-state-success| becomes set for the
860 // enrollment screen, indicating enrollment success.
861 void SAMLEnrollmentTest::WaitForEnrollmentSuccess() {
863 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
864 GetLoginUI()->GetWebContents(),
865 "var enrollmentScreen = document.getElementById('oauth-enrollment');"
866 "function SendReplyIfEnrollmentDone() {"
867 " if (!enrollmentScreen.classList.contains("
868 " 'oauth-enroll-state-success')) {"
871 " domAutomationController.send(true);"
872 " observer.disconnect();"
875 "var observer = new MutationObserver(SendReplyIfEnrollmentDone);"
876 "if (!SendReplyIfEnrollmentDone()) {"
877 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
878 " observer.observe(enrollmentScreen, options);"
883 IN_PROC_BROWSER_TEST_P(SAMLEnrollmentTest
, WithoutCredentialsPassingAPI
) {
884 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
885 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
887 // Fill-in the SAML IdP form and submit.
888 SetSignFormField("Email", "fake_user");
889 SetSignFormField("Password", "fake_password");
890 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
892 WaitForEnrollmentSuccess();
895 IN_PROC_BROWSER_TEST_P(SAMLEnrollmentTest
, WithCredentialsPassingAPI
) {
896 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
897 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
898 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail
);
900 // Fill-in the SAML IdP form and submit.
901 SetSignFormField("Email", "fake_user");
902 SetSignFormField("Password", "fake_password");
903 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
905 WaitForEnrollmentSuccess();
908 // TODO(dzhioev): fix the tests for webview case. http://crbug.com/513955
910 INSTANTIATE_TEST_CASE_P(SamlSuite,
912 testing::Values(true));
915 class SAMLPolicyTest
: public SamlTest
{
918 ~SAMLPolicyTest() override
;
921 void SetUpInProcessBrowserTestFixture() override
;
922 void SetUpOnMainThread() override
;
924 void SetSAMLOfflineSigninTimeLimitPolicy(int limit
);
925 void EnableTransferSAMLCookiesPolicy();
927 void ShowGAIALoginForm();
928 void LogInWithSAML(const std::string
& user_id
,
929 const std::string
& auth_sid_cookie
,
930 const std::string
& auth_lsid_cookie
);
932 std::string
GetCookieValue(const std::string
& name
);
937 void GetCookiesOnIOThread(
938 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
939 const base::Closure
& callback
);
940 void StoreCookieList(const base::Closure
& callback
,
941 const net::CookieList
& cookie_list
);
943 policy::DevicePolicyCrosTestHelper test_helper_
;
945 // FakeDBusThreadManager uses FakeSessionManagerClient.
946 FakeSessionManagerClient
* fake_session_manager_client_
;
947 policy::DevicePolicyBuilder
* device_policy_
;
949 policy::MockConfigurationPolicyProvider provider_
;
951 net::CookieList cookie_list_
;
954 DISALLOW_COPY_AND_ASSIGN(SAMLPolicyTest
);
957 SAMLPolicyTest::SAMLPolicyTest()
958 : fake_session_manager_client_(new FakeSessionManagerClient
),
959 device_policy_(test_helper_
.device_policy()) {
962 SAMLPolicyTest::~SAMLPolicyTest() {
965 void SAMLPolicyTest::SetUpInProcessBrowserTestFixture() {
966 DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
967 scoped_ptr
<SessionManagerClient
>(fake_session_manager_client_
));
969 SamlTest::SetUpInProcessBrowserTestFixture();
971 // Initialize device policy.
972 test_helper_
.InstallOwnerKey();
973 test_helper_
.MarkAsEnterpriseOwned();
974 device_policy_
->SetDefaultSigningKey();
975 device_policy_
->Build();
976 fake_session_manager_client_
->set_device_policy(device_policy_
->GetBlob());
977 fake_session_manager_client_
->OnPropertyChangeComplete(true);
979 // Initialize user policy.
980 EXPECT_CALL(provider_
, IsInitializationComplete(_
))
981 .WillRepeatedly(Return(true));
982 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_
);
985 void SAMLPolicyTest::SetUpOnMainThread() {
986 SamlTest::SetUpOnMainThread();
988 // Pretend that the test users' OAuth tokens are valid.
989 user_manager::UserManager::Get()->SaveUserOAuthStatus(
990 kFirstSAMLUserEmail
, user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
991 user_manager::UserManager::Get()->SaveUserOAuthStatus(
992 kNonSAMLUserEmail
, user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
993 user_manager::UserManager::Get()->SaveUserOAuthStatus(
994 kDifferentDomainSAMLUserEmail
,
995 user_manager::User::OAUTH2_TOKEN_STATUS_VALID
);
997 // Set up fake networks.
998 DBusThreadManager::Get()
999 ->GetShillManagerClient()
1000 ->GetTestInterface()
1001 ->SetupDefaultEnvironment();
1004 void SAMLPolicyTest::SetSAMLOfflineSigninTimeLimitPolicy(int limit
) {
1005 policy::PolicyMap user_policy
;
1006 user_policy
.Set(policy::key::kSAMLOfflineSigninTimeLimit
,
1007 policy::POLICY_LEVEL_MANDATORY
,
1008 policy::POLICY_SCOPE_USER
,
1009 new base::FundamentalValue(limit
),
1011 provider_
.UpdateChromePolicy(user_policy
);
1012 base::RunLoop().RunUntilIdle();
1015 void SAMLPolicyTest::EnableTransferSAMLCookiesPolicy() {
1016 em::ChromeDeviceSettingsProto
& proto(device_policy_
->payload());
1017 proto
.mutable_saml_settings()->set_transfer_saml_cookies(true);
1019 base::RunLoop run_loop
;
1020 scoped_ptr
<CrosSettings::ObserverSubscription
> observer
=
1021 CrosSettings::Get()->AddSettingsObserver(
1022 kAccountsPrefTransferSAMLCookies
,
1023 run_loop
.QuitClosure());
1024 device_policy_
->SetDefaultSigningKey();
1025 device_policy_
->Build();
1026 fake_session_manager_client_
->set_device_policy(device_policy_
->GetBlob());
1027 fake_session_manager_client_
->OnPropertyChangeComplete(true);
1031 void SAMLPolicyTest::ShowGAIALoginForm() {
1032 login_screen_load_observer_
->Wait();
1033 ASSERT_TRUE(content::ExecuteScript(
1034 GetLoginUI()->GetWebContents(),
1035 "$('gaia-signin').gaiaAuthHost_.addEventListener('ready', function() {"
1036 " window.domAutomationController.setAutomationId(0);"
1037 " window.domAutomationController.send('ready');"
1039 "$('add-user-button').click();"));
1040 content::DOMMessageQueue message_queue
;
1041 std::string message
;
1042 ASSERT_TRUE(message_queue
.WaitForMessage(&message
));
1043 EXPECT_EQ("\"ready\"", message
);
1046 void SAMLPolicyTest::LogInWithSAML(const std::string
& user_id
,
1047 const std::string
& auth_sid_cookie
,
1048 const std::string
& auth_lsid_cookie
) {
1049 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1050 StartSamlAndWaitForIdpPageLoad(user_id
);
1052 fake_gaia_
->SetFakeMergeSessionParams(user_id
, auth_sid_cookie
,
1054 SetSignFormField("Email", "fake_user");
1055 SetSignFormField("Password", "fake_password");
1056 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
1058 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD
).Wait();
1060 content::WindowedNotificationObserver
session_start_waiter(
1061 chrome::NOTIFICATION_SESSION_STARTED
,
1062 content::NotificationService::AllSources());
1063 SendConfirmPassword("fake_password");
1064 session_start_waiter
.Wait();
1067 std::string
SAMLPolicyTest::GetCookieValue(const std::string
& name
) {
1068 for (net::CookieList::const_iterator it
= cookie_list_
.begin();
1069 it
!= cookie_list_
.end(); ++it
) {
1070 if (it
->Name() == name
)
1073 return std::string();
1076 void SAMLPolicyTest::GetCookies() {
1077 Profile
* profile
= chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(
1078 user_manager::UserManager::Get()->GetActiveUser());
1079 ASSERT_TRUE(profile
);
1080 base::RunLoop run_loop
;
1081 content::BrowserThread::PostTask(
1082 content::BrowserThread::IO
,
1084 base::Bind(&SAMLPolicyTest::GetCookiesOnIOThread
,
1085 base::Unretained(this),
1086 scoped_refptr
<net::URLRequestContextGetter
>(
1087 profile
->GetRequestContext()),
1088 run_loop
.QuitClosure()));
1092 void SAMLPolicyTest::GetCookiesOnIOThread(
1093 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
1094 const base::Closure
& callback
) {
1095 request_context
->GetURLRequestContext()->cookie_store()->
1096 GetCookieMonster()->GetAllCookiesAsync(base::Bind(
1097 &SAMLPolicyTest::StoreCookieList
,
1098 base::Unretained(this),
1102 void SAMLPolicyTest::StoreCookieList(
1103 const base::Closure
& callback
,
1104 const net::CookieList
& cookie_list
) {
1105 cookie_list_
= cookie_list
;
1106 content::BrowserThread::PostTask(content::BrowserThread::UI
,
1111 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_NoSAML
) {
1112 // Set the offline login time limit for SAML users to zero.
1113 SetSAMLOfflineSigninTimeLimitPolicy(0);
1115 WaitForSigninScreen();
1117 // Log in without SAML.
1118 GetLoginDisplay()->ShowSigninScreenForCreds(kNonSAMLUserEmail
, "password");
1120 content::WindowedNotificationObserver(
1121 chrome::NOTIFICATION_SESSION_STARTED
,
1122 content::NotificationService::AllSources()).Wait();
1125 // Verifies that the offline login time limit does not affect a user who
1126 // authenticated without SAML.
1127 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, NoSAML
) {
1128 login_screen_load_observer_
->Wait();
1129 // Verify that offline login is allowed.
1131 "window.getComputedStyle(document.querySelector("
1132 " '#pod-row .reauth-hint-container')).display == 'none'");
1135 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_SAMLNoLimit
) {
1136 // Remove the offline login time limit for SAML users.
1137 SetSAMLOfflineSigninTimeLimitPolicy(-1);
1139 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1142 // Verifies that when no offline login time limit is set, a user who
1143 // authenticated with SAML is allowed to log in offline.
1144 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, SAMLNoLimit
) {
1145 login_screen_load_observer_
->Wait();
1146 // Verify that offline login is allowed.
1148 "window.getComputedStyle(document.querySelector("
1149 " '#pod-row .reauth-hint-container')).display == 'none'");
1152 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_SAMLZeroLimit
) {
1153 // Set the offline login time limit for SAML users to zero.
1154 SetSAMLOfflineSigninTimeLimitPolicy(0);
1156 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1159 // Verifies that when the offline login time limit is exceeded for a user who
1160 // authenticated via SAML, that user is forced to log in online the next time.
1161 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, SAMLZeroLimit
) {
1162 login_screen_load_observer_
->Wait();
1163 // Verify that offline login is not allowed.
1165 "window.getComputedStyle(document.querySelector("
1166 " '#pod-row .reauth-hint-container')).display != 'none'");
1169 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_PRE_TransferCookiesAffiliated
) {
1170 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1
);
1171 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie1
, kTestAuthLSIDCookie1
);
1174 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1175 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1176 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1179 // Verifies that when the DeviceTransferSAMLCookies policy is not enabled, SAML
1180 // IdP cookies are not transferred to a user's profile on subsequent login, even
1181 // if the user belongs to the domain that the device is enrolled into. Also
1182 // verifies that GAIA cookies are not transferred.
1183 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_TransferCookiesAffiliated
) {
1184 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1185 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1186 ShowGAIALoginForm();
1187 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie2
, kTestAuthLSIDCookie2
);
1190 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1191 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1192 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1195 // Verifies that when the DeviceTransferSAMLCookies policy is enabled, SAML IdP
1196 // cookies are transferred to a user's profile on subsequent login when the user
1197 // belongs to the domain that the device is enrolled into. Also verifies that
1198 // GAIA cookies are not transferred.
1199 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, TransferCookiesAffiliated
) {
1200 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1201 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1202 ShowGAIALoginForm();
1204 EnableTransferSAMLCookiesPolicy();
1205 LogInWithSAML(kFirstSAMLUserEmail
, kTestAuthSIDCookie2
, kTestAuthLSIDCookie2
);
1208 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1209 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1210 EXPECT_EQ(kSAMLIdPCookieValue2
, GetCookieValue(kSAMLIdPCookieName
));
1213 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, PRE_TransferCookiesUnaffiliated
) {
1214 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1
);
1215 LogInWithSAML(kDifferentDomainSAMLUserEmail
,
1216 kTestAuthSIDCookie1
,
1217 kTestAuthLSIDCookie1
);
1220 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1221 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1222 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1225 // Verifies that even if the DeviceTransferSAMLCookies policy is enabled, SAML
1226 // IdP are not transferred to a user's profile on subsequent login if the user
1227 // does not belong to the domain that the device is enrolled into. Also verifies
1228 // that GAIA cookies are not transferred.
1229 IN_PROC_BROWSER_TEST_P(SAMLPolicyTest
, TransferCookiesUnaffiliated
) {
1230 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2
);
1231 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1232 ShowGAIALoginForm();
1234 EnableTransferSAMLCookiesPolicy();
1235 LogInWithSAML(kDifferentDomainSAMLUserEmail
,
1236 kTestAuthSIDCookie1
,
1237 kTestAuthLSIDCookie1
);
1240 EXPECT_EQ(kTestAuthSIDCookie1
, GetCookieValue(kGAIASIDCookieName
));
1241 EXPECT_EQ(kTestAuthLSIDCookie1
, GetCookieValue(kGAIALSIDCookieName
));
1242 EXPECT_EQ(kSAMLIdPCookieValue1
, GetCookieValue(kSAMLIdPCookieName
));
1245 INSTANTIATE_TEST_CASE_P(SamlSuite
,
1249 } // namespace chromeos