Index: chrome/browser/chromeos/login/saml_browsertest.cc |
diff --git a/chrome/browser/chromeos/login/saml_browsertest.cc b/chrome/browser/chromeos/login/saml_browsertest.cc |
index 5740ee0be882db79131635e50e1cb5f06a743b9b..b866206751fd68378ec3c1ca3dee52a8776249fd 100644 |
--- a/chrome/browser/chromeos/login/saml_browsertest.cc |
+++ b/chrome/browser/chromeos/login/saml_browsertest.cc |
@@ -3,6 +3,9 @@ |
// found in the LICENSE file. |
#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/files/file_path.h" |
+#include "base/path_service.h" |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "chrome/browser/chrome_notification_types.h" |
@@ -14,6 +17,7 @@ |
#include "chrome/browser/chromeos/login/webui_login_display.h" |
#include "chrome/browser/chromeos/login/wizard_controller.h" |
#include "chrome/browser/lifetime/application_lifetime.h" |
+#include "chrome/common/chrome_paths.h" |
#include "chrome/common/chrome_switches.h" |
#include "chrome/test/base/in_process_browser_test.h" |
#include "chromeos/chromeos_switches.h" |
@@ -52,82 +56,124 @@ const char kUserEmail[] = "bob@example.com"; |
const char kRelayState[] = "RelayState"; |
-const char kDefaultIdpHtml[] = |
- "<form id=IdPForm method=post action=\"$Post\">" |
- "<input type=hidden name=RelayState value=\"$RelayState\">" |
- "User: <input type=text id=Email name=Email>" |
- "Password: <input type=password id=Password name=Password>" |
- "<input id=Submit type=submit>" |
- "</form>"; |
- |
// FakeSamlIdp serves IdP auth form and the form submission. The form is |
// served with the template's RelayState placeholder expanded to the real |
// RelayState parameter from request. The form submission redirects back to |
// FakeGaia with the same RelayState. |
class FakeSamlIdp { |
public: |
- FakeSamlIdp() : html_template_(kDefaultIdpHtml) {} |
- ~FakeSamlIdp() {} |
- |
- void SetUp(const std::string& base_path, const GURL& gaia_url) { |
- base_path_= base_path; |
- post_path_ = base_path + "Auth"; |
- gaia_assertion_url_ = gaia_url.Resolve("/SSO"); |
- } |
+ FakeSamlIdp(); |
+ ~FakeSamlIdp(); |
- scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { |
- // The scheme and host of the URL is actually not important but required to |
- // get a valid GURL in order to parse |request.relative_url|. |
- GURL request_url = GURL("http://localhost").Resolve(request.relative_url); |
- std::string request_path = request_url.path(); |
- |
- scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); |
- if (request_path == base_path_) { |
- std::string relay_state; |
- net::GetValueForKeyInQuery(request_url, kRelayState, &relay_state); |
- |
- std::string response_html = html_template_; |
- ReplaceSubstringsAfterOffset( |
- &response_html, 0, "$RelayState", relay_state); |
- ReplaceSubstringsAfterOffset( |
- &response_html, 0, "$Post", post_path_); |
- |
- http_response->set_code(net::HTTP_OK); |
- http_response->set_content(response_html); |
- http_response->set_content_type("text/html"); |
- } else if (request_path == post_path_) { |
- std::string relay_state; |
- FakeGaia::GetQueryParameter(request.content, kRelayState, &relay_state); |
- |
- GURL redirect_url = gaia_assertion_url_; |
- redirect_url = net::AppendQueryParameter( |
- redirect_url, "SAMLResponse", "fake_response"); |
- redirect_url = net::AppendQueryParameter( |
- redirect_url, kRelayState, relay_state); |
- |
- http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); |
- http_response->AddCustomHeader("Location", redirect_url.spec()); |
- } else { |
- // Request not understood. |
- return scoped_ptr<HttpResponse>(); |
- } |
+ void SetUp(const std::string& base_path, const GURL& gaia_url); |
- return http_response.PassAs<HttpResponse>(); |
- } |
+ void SetLoginHTMLTemplate(const std::string& template_file); |
+ void SetLoginAuthHTMLTemplate(const std::string& template_file); |
- void set_html_template(const std::string& html_template) { |
- html_template_ = html_template; |
- } |
+ scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request); |
private: |
- std::string base_path_; |
- std::string post_path_; |
- std::string html_template_; |
+ scoped_ptr<HttpResponse> BuildHTMLResponse(const std::string& html_template, |
+ const std::string& relay_state, |
+ const std::string& next_path); |
+ base::FilePath html_template_dir_; |
+ |
+ std::string login_path_; |
+ std::string login_auth_path_; |
+ |
+ std::string login_html_template_; |
+ std::string login_auth_html_template_; |
GURL gaia_assertion_url_; |
+ |
DISALLOW_COPY_AND_ASSIGN(FakeSamlIdp); |
}; |
+FakeSamlIdp::FakeSamlIdp() { |
+} |
+ |
+FakeSamlIdp::~FakeSamlIdp() { |
+} |
+ |
+void FakeSamlIdp::SetUp(const std::string& base_path, const GURL& gaia_url) { |
+ base::FilePath test_data_dir; |
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); |
+ html_template_dir_ = test_data_dir.Append("login"); |
+ |
+ login_path_= base_path; |
+ login_auth_path_ = base_path + "Auth"; |
+ gaia_assertion_url_ = gaia_url.Resolve("/SSO"); |
+} |
+ |
+void FakeSamlIdp::SetLoginHTMLTemplate(const std::string& template_file) { |
+ EXPECT_TRUE(base::ReadFileToString( |
+ html_template_dir_.Append(template_file), |
+ &login_html_template_)); |
+} |
+ |
+void FakeSamlIdp::SetLoginAuthHTMLTemplate(const std::string& template_file) { |
+ EXPECT_TRUE(base::ReadFileToString( |
+ html_template_dir_.Append(template_file), |
+ &login_auth_html_template_)); |
+} |
+ |
+scoped_ptr<HttpResponse> FakeSamlIdp::HandleRequest( |
+ const HttpRequest& request) { |
+ // The scheme and host of the URL is actually not important but required to |
+ // get a valid GURL in order to parse |request.relative_url|. |
+ GURL request_url = GURL("http://localhost").Resolve(request.relative_url); |
+ std::string request_path = request_url.path(); |
+ |
+ if (request_path == login_path_) { |
+ std::string relay_state; |
+ net::GetValueForKeyInQuery(request_url, kRelayState, &relay_state); |
+ return BuildHTMLResponse(login_html_template_, |
+ relay_state, |
+ login_auth_path_); |
+ } |
+ |
+ if (request_path != login_auth_path_) { |
+ // Request not understood. |
+ return scoped_ptr<HttpResponse>(); |
+ } |
+ |
+ std::string relay_state; |
+ FakeGaia::GetQueryParameter(request.content, kRelayState, &relay_state); |
+ GURL redirect_url = gaia_assertion_url_; |
+ |
+ if (!login_auth_html_template_.empty()) { |
+ return BuildHTMLResponse(login_auth_html_template_, |
+ relay_state, |
+ redirect_url.spec()); |
+ } |
+ |
+ redirect_url = net::AppendQueryParameter( |
+ redirect_url, "SAMLResponse", "fake_response"); |
+ redirect_url = net::AppendQueryParameter( |
+ redirect_url, kRelayState, relay_state); |
+ |
+ scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); |
+ http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); |
+ http_response->AddCustomHeader("Location", redirect_url.spec()); |
+ return http_response.PassAs<HttpResponse>(); |
+} |
+ |
+scoped_ptr<HttpResponse> FakeSamlIdp::BuildHTMLResponse( |
+ const std::string& html_template, |
+ const std::string& relay_state, |
+ const std::string& next_path) { |
+ std::string response_html = html_template; |
+ ReplaceSubstringsAfterOffset(&response_html, 0, "$RelayState", relay_state); |
+ ReplaceSubstringsAfterOffset(&response_html, 0, "$Post", next_path); |
+ |
+ scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); |
+ http_response->set_code(net::HTTP_OK); |
+ http_response->set_content(response_html); |
+ http_response->set_content_type("text/html"); |
+ |
+ return http_response.PassAs<HttpResponse>(); |
+} |
+ |
} // namespace |
class SamlTest : public InProcessBrowserTest { |
@@ -315,6 +361,7 @@ class SamlTest : public InProcessBrowserTest { |
// visible when SAML IdP page is loaded. And 'cancel' button goes back to |
// gaia on clicking. |
IN_PROC_BROWSER_TEST_F(SamlTest, SamlUI) { |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); |
StartSamlAndWaitForIdpPageLoad(kUserEmail); |
// Saml flow UI expectations. |
@@ -337,14 +384,32 @@ IN_PROC_BROWSER_TEST_F(SamlTest, SamlUI) { |
JsExpect("!$('gaia-signin').classList.contains('saml')"); |
} |
+// Tests the sign-in flow when the credentials passing API is used. |
+IN_PROC_BROWSER_TEST_F(SamlTest, CredentialPassingAPI) { |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html"); |
+ fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html"); |
+ StartSamlAndWaitForIdpPageLoad(kUserEmail); |
+ |
+ // Fill-in the SAML IdP form and submit. |
+ SetSignFormField("Email", "fake_user"); |
+ SetSignFormField("Password", "fake_password"); |
+ ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); |
+ |
+ // Login should finish login and a session should start. |
+ content::WindowedNotificationObserver( |
+ chrome::NOTIFICATION_SESSION_STARTED, |
+ content::NotificationService::AllSources()).Wait(); |
+} |
+ |
// Tests the single password scraped flow. |
IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedSingle) { |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); |
StartSamlAndWaitForIdpPageLoad(kUserEmail); |
// Fill-in the SAML IdP form and submit. |
SetSignFormField("Email", "fake_user"); |
SetSignFormField("Password", "fake_password"); |
- ExecuteJsInSigninFrame("document.getElementById('IdPForm').submit();"); |
+ ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); |
// Lands on confirm password screen. |
OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait(); |
@@ -362,21 +427,14 @@ IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedSingle) { |
// Tests the multiple password scraped flow. |
IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedMultiple) { |
- fake_saml_idp()->set_html_template( |
- "<form id=IdPForm method=post action=\"$Post\">" |
- "<input type=hidden name=RelayState value=\"$RelayState\">" |
- "User: <input type=text id=Email name=Email>" |
- "Password: <input type=password id=Password name=Password>" |
- "Password: <input type=password id=Password1 name=Password1>" |
- "<input id=Submit type=submit>" |
- "</form>"); |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html"); |
StartSamlAndWaitForIdpPageLoad(kUserEmail); |
SetSignFormField("Email", "fake_user"); |
SetSignFormField("Password", "fake_password"); |
SetSignFormField("Password1", "password1"); |
- ExecuteJsInSigninFrame("document.getElementById('IdPForm').submit();"); |
+ ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); |
OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait(); |
@@ -389,17 +447,12 @@ IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedMultiple) { |
// Tests the no password scraped flow. |
IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedNone) { |
- fake_saml_idp()->set_html_template( |
- "<form id=IdPForm method=post action=\"$Post\">" |
- "<input type=hidden name=RelayState value=\"$RelayState\">" |
- "User: <input type=text id=Email name=Email>" |
- "<input id=Submit type=submit>" |
- "</form>"); |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_login_no_passwords.html"); |
StartSamlAndWaitForIdpPageLoad(kUserEmail); |
SetSignFormField("Email", "fake_user"); |
- ExecuteJsInSigninFrame("document.getElementById('IdPForm').submit();"); |
+ ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); |
OobeScreenWaiter(OobeDisplay::SCREEN_MESSAGE_BOX).Wait(); |
JsExpect( |
@@ -411,6 +464,7 @@ IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedNone) { |
// |bob@example.com| via SAML. Verifies that the logged-in user is correctly |
// identified as Bob. |
IN_PROC_BROWSER_TEST_F(SamlTest, UseAutenticatedUserEmailAddress) { |
+ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); |
// Type |alice@example.com| into the GAIA login form. |
StartSamlAndWaitForIdpPageLoad(kAnotherUserEmail); |
@@ -419,7 +473,7 @@ IN_PROC_BROWSER_TEST_F(SamlTest, UseAutenticatedUserEmailAddress) { |
// reports was set via SetMergeSessionParams()). |
SetSignFormField("Email", "fake_user"); |
SetSignFormField("Password", "fake_password"); |
- ExecuteJsInSigninFrame("document.getElementById('IdPForm').submit();"); |
+ ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); |
OobeScreenWaiter(OobeDisplay::SCREEN_CONFIRM_PASSWORD).Wait(); |