Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / saml / saml_browsertest.cc
blob42f4906879165caa7b071ec388bf78e632a744e7
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/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"
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 // 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> {
310 public:
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(
326 kHTTPSAMLUserEmail,
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',"
354 "function f() {"
355 "$('gaia-signin').gaiaAuthHost_.removeEventListener("
356 "'authFlowChange', f);"
357 "window.domAutomationController.setAutomationId(0);"
358 "window.domAutomationController.send("
359 "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');"
360 "});"));
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, "");
371 std::string message;
372 ASSERT_TRUE(message_queue.WaitForMessage(&message));
373 EXPECT_EQ("\"SamlLoaded\"", message);
376 void SendConfirmPassword(const std::string& password_to_confirm) {
377 std::string js =
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 +
393 ".textContent);",
394 &error_message)) {
395 ADD_FAILURE();
397 return error_message;
400 FakeSamlIdp* fake_saml_idp() { return &fake_saml_idp_; }
402 protected:
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_;
413 private:
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
421 // gaia on clicking.
423 // Times out on CrOS MSAN. https://crbug.com/504141
424 #if defined(MEMORY_SANITIZER)
425 #define MAYBE_SamlUI DISABLED_SamlUI
426 #else
427 #define MAYBE_SamlUI SamlUI
428 #endif
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);
438 JsExpect(js);
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'.
447 if (use_webview()) {
448 ASSERT_TRUE(content::ExecuteScript(
449 GetLoginUI()->GetWebContents(),
450 "$('close-button-item').click();"));
451 } else {
452 ASSERT_TRUE(content::ExecuteScript(
453 GetLoginUI()->GetWebContents(),
454 "$('cancel-add-user-button').click();"));
457 // Auth flow should change back to Gaia.
458 std::string message;
459 do {
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(
527 "(function() {"
528 "var newPassInput = document.createElement('input');"
529 "newPassInput.id = 'DynamicallyCreatedPassword';"
530 "newPassInput.type = 'password';"
531 "newPassInput.name = 'Password';"
532 "document.forms[0].appendChild(newPassInput);"
533 "})();");
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();
613 ASSERT_TRUE(user);
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");
656 EXPECT_EQ(
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|.
678 std::string js =
679 "var sendIfHostFound = function() {"
680 " var found ="
681 " $('saml-notice-message').textContent.indexOf('$Host') > -1;"
682 " if (found)"
683 " window.domAutomationController.send(true);"
684 " return found;"
685 "};"
686 "var processEventsAndSendIfHostFound = function() {"
687 " window.setTimeout(function() {"
688 " if (sendIfHostFound()) {"
689 " $('gaia-signin').gaiaAuthHost_.removeEventListener("
690 " 'authDomainChange',"
691 " processEventsAndSendIfHostFound);"
692 " }"
693 " }, 0);"
694 "};"
695 "if (!sendIfHostFound()) {"
696 " $('gaia-signin').gaiaAuthHost_.addEventListener("
697 " 'authDomainChange',"
698 " processEventsAndSendIfHostFound);"
699 "}";
700 base::ReplaceSubstringsAfterOffset(&js, 0, "$Host", kAdditionalIdPHost);
701 bool dummy;
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,
742 SamlTest,
743 testing::Bool());
745 class SAMLEnrollmentTest : public SamlTest,
746 public content::WebContentsObserver {
747 public:
748 SAMLEnrollmentTest();
749 ~SAMLEnrollmentTest() override;
751 // SamlTest:
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();
764 private:
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());
791 SamlTest::SetUp();
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();
821 run_loop_->Run();
823 SetSignFormField("Email", gaia_email);
825 run_loop_.reset(new base::RunLoop);
826 ExecuteJsInSigninFrame("document.getElementById('signIn').click();");
827 run_loop_->Run();
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_)
834 return;
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_)
846 return;
848 const GURL origin = validated_url.GetOrigin();
849 if (origin != gaia_https_forwarder_.GetURLForSSLHost(std::string()) &&
850 origin != saml_https_forwarder_.GetURLForSSLHost(std::string())) {
851 return;
854 // The GAIA or SAML IdP login form finished loading.
855 if (run_loop_)
856 run_loop_->Quit();
859 // Waits until the class |oauth-enroll-state-success| becomes set for the
860 // enrollment screen, indicating enrollment success.
861 void SAMLEnrollmentTest::WaitForEnrollmentSuccess() {
862 bool done = false;
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')) {"
869 " return false;"
870 " }"
871 " domAutomationController.send(true);"
872 " observer.disconnect();"
873 " return true;"
875 "var observer = new MutationObserver(SendReplyIfEnrollmentDone);"
876 "if (!SendReplyIfEnrollmentDone()) {"
877 " var options = { attributes: true, attributeFilter: [ 'class' ] };"
878 " observer.observe(enrollmentScreen, options);"
879 "}",
880 &done));
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,
911 SAMLEnrollmentTest,
912 testing::Values(true));
915 class SAMLPolicyTest : public SamlTest {
916 public:
917 SAMLPolicyTest();
918 ~SAMLPolicyTest() override;
920 // SamlTest:
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);
934 void GetCookies();
936 protected:
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_;
953 private:
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),
1010 NULL);
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);
1028 run_loop.Run();
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');"
1038 "});"
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,
1053 auth_lsid_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)
1071 return it->Value();
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,
1083 FROM_HERE,
1084 base::Bind(&SAMLPolicyTest::GetCookiesOnIOThread,
1085 base::Unretained(this),
1086 scoped_refptr<net::URLRequestContextGetter>(
1087 profile->GetRequestContext()),
1088 run_loop.QuitClosure()));
1089 run_loop.Run();
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),
1099 callback));
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,
1107 FROM_HERE,
1108 callback);
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.
1130 JsExpect(
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.
1147 JsExpect(
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.
1164 JsExpect(
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);
1173 GetCookies();
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);
1189 GetCookies();
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);
1207 GetCookies();
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);
1219 GetCookies();
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);
1239 GetCookies();
1240 EXPECT_EQ(kTestAuthSIDCookie1, GetCookieValue(kGAIASIDCookieName));
1241 EXPECT_EQ(kTestAuthLSIDCookie1, GetCookieValue(kGAIALSIDCookieName));
1242 EXPECT_EQ(kSAMLIdPCookieValue1, GetCookieValue(kSAMLIdPCookieName));
1245 INSTANTIATE_TEST_CASE_P(SamlSuite,
1246 SAMLPolicyTest,
1247 testing::Bool());
1249 } // namespace chromeos