Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / login / saml / saml_browsertest.cc
blob4d63f2db9d815121a4bf0ffc7275fb671cda06ef
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.
5 #include <cstring>
6 #include <string>
8 #include "base/bind.h"
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/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_base_test.h"
31 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
32 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
33 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
34 #include "chrome/browser/chromeos/login/wizard_controller.h"
35 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
36 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
37 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
38 #include "chrome/browser/chromeos/profiles/profile_helper.h"
39 #include "chrome/browser/chromeos/settings/cros_settings.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/grit/generated_resources.h"
48 #include "chrome/test/base/in_process_browser_test.h"
49 #include "chromeos/chromeos_switches.h"
50 #include "chromeos/cryptohome/system_salt_getter.h"
51 #include "chromeos/dbus/cryptohome/key.pb.h"
52 #include "chromeos/dbus/cryptohome/rpc.pb.h"
53 #include "chromeos/dbus/cryptohome_client.h"
54 #include "chromeos/dbus/dbus_thread_manager.h"
55 #include "chromeos/dbus/fake_cryptohome_client.h"
56 #include "chromeos/dbus/fake_session_manager_client.h"
57 #include "chromeos/dbus/session_manager_client.h"
58 #include "chromeos/dbus/shill_manager_client.h"
59 #include "chromeos/login/auth/key.h"
60 #include "chromeos/settings/cros_settings_names.h"
61 #include "components/guest_view/browser/test_guest_view_manager.h"
62 #include "components/policy/core/browser/browser_policy_connector.h"
63 #include "components/policy/core/common/mock_configuration_policy_provider.h"
64 #include "components/policy/core/common/policy_map.h"
65 #include "components/policy/core/common/policy_switches.h"
66 #include "components/policy/core/common/policy_types.h"
67 #include "components/user_manager/user.h"
68 #include "components/user_manager/user_manager.h"
69 #include "content/public/browser/browser_thread.h"
70 #include "content/public/browser/render_frame_host.h"
71 #include "content/public/browser/web_contents.h"
72 #include "content/public/browser/web_contents_observer.h"
73 #include "content/public/test/browser_test_utils.h"
74 #include "content/public/test/test_utils.h"
75 #include "extensions/browser/guest_view/web_view/web_view_guest.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"
95 #include "url/gurl.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;
103 using testing::_;
105 namespace chromeos {
107 namespace {
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.
140 class FakeSamlIdp {
141 public:
142 FakeSamlIdp();
143 ~FakeSamlIdp();
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);
154 private:
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_;
167 GURL refresh_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_,
220 relay_state,
221 login_auth_path_);
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_,
235 relay_state,
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(
248 "Set-cookie",
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
274 // MountEx().
275 class SecretInterceptingFakeCryptohomeClient : public FakeCryptohomeClient {
276 public:
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_; }
286 private:
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);
305 } // namespace
307 class SamlTest : public OobeBaseTest {
308 public:
309 SamlTest() : cryptohome_client_(new SecretInterceptingFakeCryptohomeClient) {
310 set_initialize_fake_merge_session(false);
312 ~SamlTest() override {}
314 void SetUpCommandLine(base::CommandLine* command_line) override {
315 command_line->AppendSwitch(switches::kOobeSkipPostLogin);
317 const GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost("");
318 const GURL saml_idp_url = saml_https_forwarder_.GetURLForSSLHost("SAML");
319 fake_saml_idp_.SetUp(saml_idp_url.path(), gaia_url);
320 fake_gaia_->RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url);
321 fake_gaia_->RegisterSamlUser(kSecondSAMLUserEmail, saml_idp_url);
322 fake_gaia_->RegisterSamlUser(
323 kHTTPSAMLUserEmail,
324 embedded_test_server()->base_url().Resolve("/SAML"));
325 fake_gaia_->RegisterSamlUser(kDifferentDomainSAMLUserEmail, saml_idp_url);
327 OobeBaseTest::SetUpCommandLine(command_line);
330 void SetUpInProcessBrowserTestFixture() override {
331 DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
332 scoped_ptr<CryptohomeClient>(cryptohome_client_));
334 OobeBaseTest::SetUpInProcessBrowserTestFixture();
337 void SetUpOnMainThread() override {
338 fake_gaia_->SetFakeMergeSessionParams(
339 kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
341 embedded_test_server()->RegisterRequestHandler(base::Bind(
342 &FakeSamlIdp::HandleRequest, base::Unretained(&fake_saml_idp_)));
344 OobeBaseTest::SetUpOnMainThread();
347 void SetupAuthFlowChangeListener() {
348 ASSERT_TRUE(content::ExecuteScript(
349 GetLoginUI()->GetWebContents(),
350 "$('gaia-signin').gaiaAuthHost_.addEventListener('authFlowChange',"
351 "function f() {"
352 "$('gaia-signin').gaiaAuthHost_.removeEventListener("
353 "'authFlowChange', f);"
354 "window.domAutomationController.setAutomationId(0);"
355 "window.domAutomationController.send("
356 "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');"
357 "});"));
360 virtual void StartSamlAndWaitForIdpPageLoad(const std::string& gaia_email) {
361 WaitForSigninScreen();
363 SetupAuthFlowChangeListener();
365 content::DOMMessageQueue message_queue; // Start observe before SAML.
366 GetLoginDisplay()->ShowSigninScreenForCreds(gaia_email, "");
368 std::string message;
369 ASSERT_TRUE(message_queue.WaitForMessage(&message));
370 EXPECT_EQ("\"SamlLoaded\"", message);
373 void SendConfirmPassword(const std::string& password_to_confirm) {
374 std::string js =
375 "$('confirm-password-input').value='$Password';"
376 "$('confirm-password').onConfirmPassword_();";
377 base::ReplaceSubstringsAfterOffset(
378 &js, 0, "$Password", password_to_confirm);
379 ASSERT_TRUE(content::ExecuteScript(GetLoginUI()->GetWebContents(), js));
382 std::string WaitForAndGetFatalErrorMessage() {
383 OobeScreenWaiter(OobeDisplay::SCREEN_FATAL_ERROR).Wait();
384 std::string message_element = "$('fatal-error-card')";
385 std::string error_message;
386 if (!content::ExecuteScriptAndExtractString(
387 GetLoginUI()->GetWebContents(),
388 "window.domAutomationController.send(" + message_element +
389 ".textContent);",
390 &error_message)) {
391 ADD_FAILURE();
393 return error_message;
396 FakeSamlIdp* fake_saml_idp() { return &fake_saml_idp_; }
398 protected:
399 void InitHttpsForwarders() override {
400 ASSERT_TRUE(saml_https_forwarder_.Initialize(
401 kIdPHost, embedded_test_server()->base_url()));
402 OobeBaseTest::InitHttpsForwarders();
405 HTTPSForwarder saml_https_forwarder_;
407 SecretInterceptingFakeCryptohomeClient* cryptohome_client_;
409 private:
410 FakeSamlIdp fake_saml_idp_;
412 DISALLOW_COPY_AND_ASSIGN(SamlTest);
415 // Tests that signin frame should have 'saml' class and 'cancel' button is
416 // visible when SAML IdP page is loaded. And 'cancel' button goes back to
417 // gaia on clicking.
419 // Times out on CrOS MSAN. https://crbug.com/504141
420 #if defined(MEMORY_SANITIZER)
421 #define MAYBE_SamlUI DISABLED_SamlUI
422 #else
423 #define MAYBE_SamlUI SamlUI
424 #endif
425 IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_SamlUI) {
426 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
427 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
429 // Saml flow UI expectations.
430 JsExpect("$('gaia-signin').classList.contains('full-width')");
431 JsExpect("!$('saml-notice-container').hidden");
432 std::string js = "$('saml-notice-message').textContent.indexOf('$Host') > -1";
433 base::ReplaceSubstringsAfterOffset(&js, 0, "$Host", kIdPHost);
434 JsExpect(js);
436 SetupAuthFlowChangeListener();
438 // Click on 'cancel'.
439 content::DOMMessageQueue message_queue; // Observe before 'cancel'.
440 ASSERT_TRUE(content::ExecuteScript(GetLoginUI()->GetWebContents(),
441 "$('close-button-item').click();"));
443 // Auth flow should change back to Gaia.
444 std::string message;
445 do {
446 ASSERT_TRUE(message_queue.WaitForMessage(&message));
447 } while (message != "\"GaiaLoaded\"");
449 // Saml flow is gone.
450 JsExpect("!$('gaia-signin').classList.contains('full-width')");
453 // Tests the sign-in flow when the credentials passing API is used.
454 IN_PROC_BROWSER_TEST_F(SamlTest, CredentialPassingAPI) {
455 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
456 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
457 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
459 content::WindowedNotificationObserver session_start_waiter(
460 chrome::NOTIFICATION_SESSION_STARTED,
461 content::NotificationService::AllSources());
463 // Fill-in the SAML IdP form and submit.
464 SetSignFormField("Email", "fake_user");
465 SetSignFormField("Dummy", "not_the_password");
466 SetSignFormField("Password", "actual_password");
467 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
469 // Login should finish login and a session should start.
470 session_start_waiter.Wait();
472 // Regression test for http://crbug.com/490737: Verify that the user's actual
473 // password was used, not the contents of the first type=password input field
474 // found on the page.
475 Key key("actual_password");
476 key.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
477 SystemSaltGetter::ConvertRawSaltToHexString(
478 FakeCryptohomeClient::GetStubSystemSalt()));
479 EXPECT_EQ(key.GetSecret(), cryptohome_client_->salted_hashed_secret());
482 // Tests the single password scraped flow.
483 IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedSingle) {
484 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
485 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
487 // Fill-in the SAML IdP form and submit.
488 SetSignFormField("Email", "fake_user");
489 SetSignFormField("Password", "fake_password");
490 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
492 // Lands on confirm password screen.
493 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
495 // Entering an unknown password should go back to the confirm password screen.
496 SendConfirmPassword("wrong_password");
497 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
499 // Entering a known password should finish login and start session.
500 content::WindowedNotificationObserver session_start_waiter(
501 chrome::NOTIFICATION_SESSION_STARTED,
502 content::NotificationService::AllSources());
503 SendConfirmPassword("fake_password");
504 session_start_waiter.Wait();
507 // Tests password scraping from a dynamically created password field.
508 IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedDynamic) {
509 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
510 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
512 ExecuteJsInSigninFrame(
513 "(function() {"
514 "var newPassInput = document.createElement('input');"
515 "newPassInput.id = 'DynamicallyCreatedPassword';"
516 "newPassInput.type = 'password';"
517 "newPassInput.name = 'Password';"
518 "document.forms[0].appendChild(newPassInput);"
519 "})();");
521 // Fill-in the SAML IdP form and submit.
522 SetSignFormField("Email", "fake_user");
523 SetSignFormField("DynamicallyCreatedPassword", "fake_password");
524 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
526 // Lands on confirm password screen.
527 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
529 // Entering an unknown password should go back to the confirm password screen.
530 SendConfirmPassword("wrong_password");
531 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
533 // Entering a known password should finish login and start session.
534 content::WindowedNotificationObserver session_start_waiter(
535 chrome::NOTIFICATION_SESSION_STARTED,
536 content::NotificationService::AllSources());
537 SendConfirmPassword("fake_password");
538 session_start_waiter.Wait();
541 // Tests the multiple password scraped flow.
542 IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedMultiple) {
543 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html");
545 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
547 SetSignFormField("Email", "fake_user");
548 SetSignFormField("Password", "fake_password");
549 SetSignFormField("Password1", "password1");
550 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
552 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
554 // Either scraped password should be able to sign-in.
555 content::WindowedNotificationObserver session_start_waiter(
556 chrome::NOTIFICATION_SESSION_STARTED,
557 content::NotificationService::AllSources());
558 SendConfirmPassword("password1");
559 session_start_waiter.Wait();
562 // Tests the no password scraped flow.
563 IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedNone) {
564 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_no_passwords.html");
566 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
568 SetSignFormField("Email", "fake_user");
569 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
571 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_PASSWORD),
572 WaitForAndGetFatalErrorMessage());
575 // Types |bob@example.com| into the GAIA login form but then authenticates as
576 // |alice@example.com| via SAML. Verifies that the logged-in user is correctly
577 // identified as Alice.
578 IN_PROC_BROWSER_TEST_F(SamlTest, UseAutenticatedUserEmailAddress) {
579 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
580 // Type |bob@example.com| into the GAIA login form.
581 StartSamlAndWaitForIdpPageLoad(kSecondSAMLUserEmail);
583 // Authenticate as alice@example.com via SAML (the |Email| provided here is
584 // irrelevant - the authenticated user's e-mail address that FakeGAIA
585 // reports was set via |SetFakeMergeSessionParams|.
586 SetSignFormField("Email", "fake_user");
587 SetSignFormField("Password", "fake_password");
588 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
590 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
592 content::WindowedNotificationObserver session_start_waiter(
593 chrome::NOTIFICATION_SESSION_STARTED,
594 content::NotificationService::AllSources());
595 SendConfirmPassword("fake_password");
596 session_start_waiter.Wait();
597 const user_manager::User* user =
598 user_manager::UserManager::Get()->GetActiveUser();
599 ASSERT_TRUE(user);
600 EXPECT_EQ(kFirstSAMLUserEmail, user->email());
603 // Verifies that if the authenticated user's e-mail address cannot be retrieved,
604 // an error message is shown.
605 IN_PROC_BROWSER_TEST_F(SamlTest, FailToRetrieveAutenticatedUserEmailAddress) {
606 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
607 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
609 fake_gaia_->SetFakeMergeSessionParams("", kTestAuthSIDCookie1,
610 kTestAuthLSIDCookie1);
611 SetSignFormField("Email", "fake_user");
612 SetSignFormField("Password", "fake_password");
613 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
615 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_ACCOUNT_DETAILS),
616 WaitForAndGetFatalErrorMessage());
619 // Tests the password confirm flow: show error on the first failure and
620 // fatal error on the second failure.
621 IN_PROC_BROWSER_TEST_F(SamlTest, PasswordConfirmFlow) {
622 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
623 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
625 // Fill-in the SAML IdP form and submit.
626 SetSignFormField("Email", "fake_user");
627 SetSignFormField("Password", "fake_password");
628 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
630 // Lands on confirm password screen with no error message.
631 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
632 JsExpect("!$('confirm-password').classList.contains('error')");
634 // Enter an unknown password for the first time should go back to confirm
635 // password screen with error message.
636 SendConfirmPassword("wrong_password");
637 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
638 JsExpect("$('confirm-password').classList.contains('error')");
640 // Enter an unknown password 2nd time should go back fatal error message.
641 SendConfirmPassword("wrong_password");
642 EXPECT_EQ(
643 l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_PASSWORD_VERIFICATION),
644 WaitForAndGetFatalErrorMessage());
647 // Verifies that when the login flow redirects from one host to another, the
648 // notice shown to the user is updated. This guards against regressions of
649 // http://crbug.com/447818.
650 IN_PROC_BROWSER_TEST_F(SamlTest, NoticeUpdatedOnRedirect) {
651 // Start another https server at |kAdditionalIdPHost|.
652 HTTPSForwarder saml_https_forwarder_2;
653 ASSERT_TRUE(saml_https_forwarder_2.Initialize(
654 kAdditionalIdPHost, embedded_test_server()->base_url()));
656 // Make the login flow redirect to |kAdditionalIdPHost|.
657 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html");
658 fake_saml_idp()->SetRefreshURL(
659 saml_https_forwarder_2.GetURLForSSLHost("simple.html"));
660 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
662 // Wait until the notice shown to the user is updated to contain
663 // |kAdditionalIdPHost|.
664 std::string js =
665 "var sendIfHostFound = function() {"
666 " var found ="
667 " $('saml-notice-message').textContent.indexOf('$Host') > -1;"
668 " if (found)"
669 " window.domAutomationController.send(true);"
670 " return found;"
671 "};"
672 "var processEventsAndSendIfHostFound = function() {"
673 " window.setTimeout(function() {"
674 " if (sendIfHostFound()) {"
675 " $('gaia-signin').gaiaAuthHost_.removeEventListener("
676 " 'authDomainChange',"
677 " processEventsAndSendIfHostFound);"
678 " }"
679 " }, 0);"
680 "};"
681 "if (!sendIfHostFound()) {"
682 " $('gaia-signin').gaiaAuthHost_.addEventListener("
683 " 'authDomainChange',"
684 " processEventsAndSendIfHostFound);"
685 "}";
686 base::ReplaceSubstringsAfterOffset(&js, 0, "$Host", kAdditionalIdPHost);
687 bool dummy;
688 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
689 GetLoginUI()->GetWebContents(), js, &dummy));
691 // Verify that the notice is visible.
692 JsExpect("!$('saml-notice-container').hidden");
695 // Verifies that when GAIA attempts to redirect to a SAML IdP served over http,
696 // not https, the redirect is blocked and an error message is shown.
697 IN_PROC_BROWSER_TEST_F(SamlTest, HTTPRedirectDisallowed) {
698 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
700 WaitForSigninScreen();
701 GetLoginDisplay()->ShowSigninScreenForCreds(kHTTPSAMLUserEmail, "");
703 const GURL url = embedded_test_server()->base_url().Resolve("/SAML");
704 EXPECT_EQ(l10n_util::GetStringFUTF8(
705 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL,
706 base::UTF8ToUTF16(url.spec())),
707 WaitForAndGetFatalErrorMessage());
710 // Verifies that when GAIA attempts to redirect to a page served over http, not
711 // https, via an HTML meta refresh, the redirect is blocked and an error message
712 // is shown. This guards against regressions of http://crbug.com/359515.
713 IN_PROC_BROWSER_TEST_F(SamlTest, MetaRefreshToHTTPDisallowed) {
714 const GURL url = embedded_test_server()->base_url().Resolve("/SSO");
715 fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html");
716 fake_saml_idp()->SetRefreshURL(url);
718 WaitForSigninScreen();
719 GetLoginDisplay()->ShowSigninScreenForCreds(kFirstSAMLUserEmail, "");
721 EXPECT_EQ(l10n_util::GetStringFUTF8(
722 IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL,
723 base::UTF8ToUTF16(url.spec())),
724 WaitForAndGetFatalErrorMessage());
727 class SAMLEnrollmentTest : public SamlTest,
728 public content::WebContentsObserver {
729 public:
730 SAMLEnrollmentTest();
731 ~SAMLEnrollmentTest() override;
733 // SamlTest:
734 void SetUp() override;
735 void SetUpCommandLine(base::CommandLine* command_line) override;
736 void SetUpOnMainThread() override;
737 void StartSamlAndWaitForIdpPageLoad(const std::string& gaia_email) override;
739 // content::WebContentsObserver:
740 void DidFinishLoad(content::RenderFrameHost* render_frame_host,
741 const GURL& validated_url) override;
743 void WaitForEnrollmentSuccess();
744 guest_view::TestGuestViewManager* GetGuestViewManager();
745 content::WebContents* GetEnrollmentContents();
747 private:
748 scoped_ptr<policy::LocalPolicyTestServer> test_server_;
749 base::ScopedTempDir temp_dir_;
751 scoped_ptr<base::RunLoop> run_loop_;
753 guest_view::TestGuestViewManagerFactory guest_view_manager_factory_;
755 DISALLOW_COPY_AND_ASSIGN(SAMLEnrollmentTest);
758 SAMLEnrollmentTest::SAMLEnrollmentTest() {
759 guest_view::GuestViewManager::set_factory_for_testing(
760 &guest_view_manager_factory_);
761 gaia_frame_parent_ = "oauth-enroll-auth-view";
764 SAMLEnrollmentTest::~SAMLEnrollmentTest() {
767 void SAMLEnrollmentTest::SetUp() {
768 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
769 const base::FilePath policy_file =
770 temp_dir_.path().AppendASCII("policy.json");
771 ASSERT_EQ(static_cast<int>(strlen(kPolicy)),
772 base::WriteFile(policy_file, kPolicy, strlen(kPolicy)));
774 test_server_.reset(new policy::LocalPolicyTestServer(policy_file));
775 ASSERT_TRUE(test_server_->Start());
777 SamlTest::SetUp();
780 void SAMLEnrollmentTest::SetUpCommandLine(base::CommandLine* command_line) {
781 command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
782 test_server_->GetServiceURL().spec());
783 command_line->AppendSwitch(policy::switches::kDisablePolicyKeyVerification);
785 SamlTest::SetUpCommandLine(command_line);
788 void SAMLEnrollmentTest::SetUpOnMainThread() {
789 FakeGaia::AccessTokenInfo token_info;
790 token_info.token = kTestUserinfoToken;
791 token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
792 token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
793 token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
794 token_info.email = kFirstSAMLUserEmail;
795 fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info);
797 SamlTest::SetUpOnMainThread();
800 void SAMLEnrollmentTest::StartSamlAndWaitForIdpPageLoad(
801 const std::string& gaia_email) {
802 WaitForSigninScreen();
803 run_loop_.reset(new base::RunLoop);
804 ExistingUserController::current_controller()->OnStartEnterpriseEnrollment();
805 while (!GetEnrollmentContents()) {
806 GetGuestViewManager()->WaitForNextGuestCreated();
808 Observe(GetEnrollmentContents());
809 run_loop_->Run();
811 SetSignFormField("identifier", gaia_email);
813 run_loop_.reset(new base::RunLoop);
814 ExecuteJsInSigninFrame("document.getElementById('nextButton').click();");
815 run_loop_->Run();
818 void SAMLEnrollmentTest::DidFinishLoad(
819 content::RenderFrameHost* render_frame_host,
820 const GURL& validated_url) {
821 const GURL origin = validated_url.GetOrigin();
822 if (origin != gaia_https_forwarder_.GetURLForSSLHost(std::string()) &&
823 origin != saml_https_forwarder_.GetURLForSSLHost(std::string())) {
824 return;
827 // The GAIA or SAML IdP login form finished loading.
828 if (run_loop_)
829 run_loop_->Quit();
832 // Waits until the class |oauth-enroll-state-success| becomes set for the
833 // enrollment screen, indicating enrollment success.
834 void SAMLEnrollmentTest::WaitForEnrollmentSuccess() {
835 bool done = false;
836 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
837 GetLoginUI()->GetWebContents(),
838 "var enrollmentScreen = document.getElementById('oauth-enrollment');"
839 "function SendReplyIfEnrollmentDone() {"
840 " if (!enrollmentScreen.classList.contains("
841 " 'oauth-enroll-state-success')) {"
842 " return false;"
843 " }"
844 " domAutomationController.send(true);"
845 " observer.disconnect();"
846 " return true;"
848 "var observer = new MutationObserver(SendReplyIfEnrollmentDone);"
849 "if (!SendReplyIfEnrollmentDone()) {"
850 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
851 " observer.observe(enrollmentScreen, options);"
852 "}",
853 &done));
856 guest_view::TestGuestViewManager* SAMLEnrollmentTest::GetGuestViewManager() {
857 using namespace guest_view;
858 return static_cast<TestGuestViewManager*>(
859 TestGuestViewManager::FromBrowserContext(
860 ProfileHelper::GetSigninProfile()));
863 content::WebContents* SAMLEnrollmentTest::GetEnrollmentContents() {
864 content::RenderFrameHost* frame_host = InlineLoginUI::GetAuthFrame(
865 GetLoginUI()->GetWebContents(), GURL(), gaia_frame_parent_);
866 if (!frame_host)
867 return nullptr;
868 return content::WebContents::FromRenderFrameHost(frame_host);
871 IN_PROC_BROWSER_TEST_F(SAMLEnrollmentTest, WithoutCredentialsPassingAPI) {
872 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
873 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
875 // Fill-in the SAML IdP form and submit.
876 SetSignFormField("Email", "fake_user");
877 SetSignFormField("Password", "fake_password");
878 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
880 WaitForEnrollmentSuccess();
883 IN_PROC_BROWSER_TEST_F(SAMLEnrollmentTest, WithCredentialsPassingAPI) {
884 fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html");
885 fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html");
886 StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
888 // Fill-in the SAML IdP form and submit.
889 SetSignFormField("Email", "fake_user");
890 SetSignFormField("Password", "fake_password");
891 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
893 WaitForEnrollmentSuccess();
896 class SAMLPolicyTest : public SamlTest {
897 public:
898 SAMLPolicyTest();
899 ~SAMLPolicyTest() override;
901 // SamlTest:
902 void SetUpInProcessBrowserTestFixture() override;
903 void SetUpOnMainThread() override;
905 void SetSAMLOfflineSigninTimeLimitPolicy(int limit);
906 void EnableTransferSAMLCookiesPolicy();
908 void ShowGAIALoginForm();
909 void LogInWithSAML(const std::string& user_id,
910 const std::string& auth_sid_cookie,
911 const std::string& auth_lsid_cookie);
913 std::string GetCookieValue(const std::string& name);
915 void GetCookies();
917 protected:
918 void GetCookiesOnIOThread(
919 const scoped_refptr<net::URLRequestContextGetter>& request_context,
920 const base::Closure& callback);
921 void StoreCookieList(const base::Closure& callback,
922 const net::CookieList& cookie_list);
924 policy::DevicePolicyCrosTestHelper test_helper_;
926 // FakeDBusThreadManager uses FakeSessionManagerClient.
927 FakeSessionManagerClient* fake_session_manager_client_;
928 policy::DevicePolicyBuilder* device_policy_;
930 policy::MockConfigurationPolicyProvider provider_;
932 net::CookieList cookie_list_;
934 private:
935 DISALLOW_COPY_AND_ASSIGN(SAMLPolicyTest);
938 SAMLPolicyTest::SAMLPolicyTest()
939 : fake_session_manager_client_(new FakeSessionManagerClient),
940 device_policy_(test_helper_.device_policy()) {
943 SAMLPolicyTest::~SAMLPolicyTest() {
946 void SAMLPolicyTest::SetUpInProcessBrowserTestFixture() {
947 DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
948 scoped_ptr<SessionManagerClient>(fake_session_manager_client_));
950 SamlTest::SetUpInProcessBrowserTestFixture();
952 // Initialize device policy.
953 test_helper_.InstallOwnerKey();
954 test_helper_.MarkAsEnterpriseOwned();
955 device_policy_->SetDefaultSigningKey();
956 device_policy_->Build();
957 fake_session_manager_client_->set_device_policy(device_policy_->GetBlob());
958 fake_session_manager_client_->OnPropertyChangeComplete(true);
960 // Initialize user policy.
961 EXPECT_CALL(provider_, IsInitializationComplete(_))
962 .WillRepeatedly(Return(true));
963 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
966 void SAMLPolicyTest::SetUpOnMainThread() {
967 SamlTest::SetUpOnMainThread();
969 // Pretend that the test users' OAuth tokens are valid.
970 user_manager::UserManager::Get()->SaveUserOAuthStatus(
971 kFirstSAMLUserEmail, user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
972 user_manager::UserManager::Get()->SaveUserOAuthStatus(
973 kNonSAMLUserEmail, user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
974 user_manager::UserManager::Get()->SaveUserOAuthStatus(
975 kDifferentDomainSAMLUserEmail,
976 user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
978 // Set up fake networks.
979 DBusThreadManager::Get()
980 ->GetShillManagerClient()
981 ->GetTestInterface()
982 ->SetupDefaultEnvironment();
985 void SAMLPolicyTest::SetSAMLOfflineSigninTimeLimitPolicy(int limit) {
986 policy::PolicyMap user_policy;
987 user_policy.Set(policy::key::kSAMLOfflineSigninTimeLimit,
988 policy::POLICY_LEVEL_MANDATORY,
989 policy::POLICY_SCOPE_USER,
990 new base::FundamentalValue(limit),
991 NULL);
992 provider_.UpdateChromePolicy(user_policy);
993 base::RunLoop().RunUntilIdle();
996 void SAMLPolicyTest::EnableTransferSAMLCookiesPolicy() {
997 em::ChromeDeviceSettingsProto& proto(device_policy_->payload());
998 proto.mutable_saml_settings()->set_transfer_saml_cookies(true);
1000 base::RunLoop run_loop;
1001 scoped_ptr<CrosSettings::ObserverSubscription> observer =
1002 CrosSettings::Get()->AddSettingsObserver(
1003 kAccountsPrefTransferSAMLCookies,
1004 run_loop.QuitClosure());
1005 device_policy_->SetDefaultSigningKey();
1006 device_policy_->Build();
1007 fake_session_manager_client_->set_device_policy(device_policy_->GetBlob());
1008 fake_session_manager_client_->OnPropertyChangeComplete(true);
1009 run_loop.Run();
1012 void SAMLPolicyTest::ShowGAIALoginForm() {
1013 login_screen_load_observer_->Wait();
1014 ASSERT_TRUE(content::ExecuteScript(
1015 GetLoginUI()->GetWebContents(),
1016 "$('gaia-signin').gaiaAuthHost_.addEventListener('ready', function() {"
1017 " window.domAutomationController.setAutomationId(0);"
1018 " window.domAutomationController.send('ready');"
1019 "});"
1020 "$('add-user-button').click();"));
1021 content::DOMMessageQueue message_queue;
1022 std::string message;
1023 ASSERT_TRUE(message_queue.WaitForMessage(&message));
1024 EXPECT_EQ("\"ready\"", message);
1027 void SAMLPolicyTest::LogInWithSAML(const std::string& user_id,
1028 const std::string& auth_sid_cookie,
1029 const std::string& auth_lsid_cookie) {
1030 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1031 StartSamlAndWaitForIdpPageLoad(user_id);
1033 fake_gaia_->SetFakeMergeSessionParams(user_id, auth_sid_cookie,
1034 auth_lsid_cookie);
1035 SetSignFormField("Email", "fake_user");
1036 SetSignFormField("Password", "fake_password");
1037 ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
1039 OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait();
1041 content::WindowedNotificationObserver session_start_waiter(
1042 chrome::NOTIFICATION_SESSION_STARTED,
1043 content::NotificationService::AllSources());
1044 SendConfirmPassword("fake_password");
1045 session_start_waiter.Wait();
1048 std::string SAMLPolicyTest::GetCookieValue(const std::string& name) {
1049 for (net::CookieList::const_iterator it = cookie_list_.begin();
1050 it != cookie_list_.end(); ++it) {
1051 if (it->Name() == name)
1052 return it->Value();
1054 return std::string();
1057 void SAMLPolicyTest::GetCookies() {
1058 Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(
1059 user_manager::UserManager::Get()->GetActiveUser());
1060 ASSERT_TRUE(profile);
1061 base::RunLoop run_loop;
1062 content::BrowserThread::PostTask(
1063 content::BrowserThread::IO,
1064 FROM_HERE,
1065 base::Bind(&SAMLPolicyTest::GetCookiesOnIOThread,
1066 base::Unretained(this),
1067 scoped_refptr<net::URLRequestContextGetter>(
1068 profile->GetRequestContext()),
1069 run_loop.QuitClosure()));
1070 run_loop.Run();
1073 void SAMLPolicyTest::GetCookiesOnIOThread(
1074 const scoped_refptr<net::URLRequestContextGetter>& request_context,
1075 const base::Closure& callback) {
1076 request_context->GetURLRequestContext()->cookie_store()->
1077 GetCookieMonster()->GetAllCookiesAsync(base::Bind(
1078 &SAMLPolicyTest::StoreCookieList,
1079 base::Unretained(this),
1080 callback));
1083 void SAMLPolicyTest::StoreCookieList(
1084 const base::Closure& callback,
1085 const net::CookieList& cookie_list) {
1086 cookie_list_ = cookie_list;
1087 content::BrowserThread::PostTask(content::BrowserThread::UI,
1088 FROM_HERE,
1089 callback);
1092 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_NoSAML) {
1093 // Set the offline login time limit for SAML users to zero.
1094 SetSAMLOfflineSigninTimeLimitPolicy(0);
1096 WaitForSigninScreen();
1098 // Log in without SAML.
1099 GetLoginDisplay()->ShowSigninScreenForCreds(kNonSAMLUserEmail, "password");
1101 content::WindowedNotificationObserver(
1102 chrome::NOTIFICATION_SESSION_STARTED,
1103 content::NotificationService::AllSources()).Wait();
1106 // Verifies that the offline login time limit does not affect a user who
1107 // authenticated without SAML.
1108 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, NoSAML) {
1109 login_screen_load_observer_->Wait();
1110 // Verify that offline login is allowed.
1111 JsExpect(
1112 "window.getComputedStyle(document.querySelector("
1113 " '#pod-row .reauth-hint-container')).display == 'none'");
1116 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_SAMLNoLimit) {
1117 // Remove the offline login time limit for SAML users.
1118 SetSAMLOfflineSigninTimeLimitPolicy(-1);
1120 LogInWithSAML(kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
1123 // Verifies that when no offline login time limit is set, a user who
1124 // authenticated with SAML is allowed to log in offline.
1125 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, SAMLNoLimit) {
1126 login_screen_load_observer_->Wait();
1127 // Verify that offline login is allowed.
1128 JsExpect(
1129 "window.getComputedStyle(document.querySelector("
1130 " '#pod-row .reauth-hint-container')).display == 'none'");
1133 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_SAMLZeroLimit) {
1134 // Set the offline login time limit for SAML users to zero.
1135 SetSAMLOfflineSigninTimeLimitPolicy(0);
1137 LogInWithSAML(kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
1140 // Verifies that when the offline login time limit is exceeded for a user who
1141 // authenticated via SAML, that user is forced to log in online the next time.
1142 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, SAMLZeroLimit) {
1143 login_screen_load_observer_->Wait();
1144 // Verify that offline login is not allowed.
1145 JsExpect(
1146 "window.getComputedStyle(document.querySelector("
1147 " '#pod-row .reauth-hint-container')).display != 'none'");
1150 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_PRE_TransferCookiesAffiliated) {
1151 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1);
1152 LogInWithSAML(kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
1154 GetCookies();
1155 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1156 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1157 EXPECT_EQ(kSAMLIdPCookieValue1, GetCookieValue(kSAMLIdPCookieName));
1160 // Verifies that when the DeviceTransferSAMLCookies policy is not enabled, SAML
1161 // IdP cookies are not transferred to a user's profile on subsequent login, even
1162 // if the user belongs to the domain that the device is enrolled into. Also
1163 // verifies that GAIA cookies are not transferred.
1164 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_TransferCookiesAffiliated) {
1165 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2);
1166 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1167 ShowGAIALoginForm();
1168 LogInWithSAML(kFirstSAMLUserEmail, kTestAuthSIDCookie2, kTestAuthLSIDCookie2);
1170 GetCookies();
1171 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1172 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1173 EXPECT_EQ(kSAMLIdPCookieValue1, GetCookieValue(kSAMLIdPCookieName));
1176 // Verifies that when the DeviceTransferSAMLCookies policy is enabled, SAML IdP
1177 // cookies are transferred to a user's profile on subsequent login when the user
1178 // belongs to the domain that the device is enrolled into. Also verifies that
1179 // GAIA cookies are not transferred.
1180 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, TransferCookiesAffiliated) {
1181 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2);
1182 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1183 ShowGAIALoginForm();
1185 EnableTransferSAMLCookiesPolicy();
1186 LogInWithSAML(kFirstSAMLUserEmail, kTestAuthSIDCookie2, kTestAuthLSIDCookie2);
1188 GetCookies();
1189 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1190 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1191 EXPECT_EQ(kSAMLIdPCookieValue2, GetCookieValue(kSAMLIdPCookieName));
1194 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_TransferCookiesUnaffiliated) {
1195 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1);
1196 LogInWithSAML(kDifferentDomainSAMLUserEmail,
1197 kTestAuthSIDCookie1,
1198 kTestAuthLSIDCookie1);
1200 GetCookies();
1201 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1202 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1203 EXPECT_EQ(kSAMLIdPCookieValue1, GetCookieValue(kSAMLIdPCookieName));
1206 // Verifies that even if the DeviceTransferSAMLCookies policy is enabled, SAML
1207 // IdP are not transferred to a user's profile on subsequent login if the user
1208 // does not belong to the domain that the device is enrolled into. Also verifies
1209 // that GAIA cookies are not transferred.
1210 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, TransferCookiesUnaffiliated) {
1211 fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue2);
1212 fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
1213 ShowGAIALoginForm();
1215 EnableTransferSAMLCookiesPolicy();
1216 LogInWithSAML(kDifferentDomainSAMLUserEmail,
1217 kTestAuthSIDCookie1,
1218 kTestAuthLSIDCookie1);
1220 GetCookies();
1221 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1222 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1223 EXPECT_EQ(kSAMLIdPCookieValue1, GetCookieValue(kSAMLIdPCookieName));
1227 } // namespace chromeos