diff options
author | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-18 17:31:45 +0000 |
---|---|---|
committer | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-18 17:31:45 +0000 |
commit | 31a7fb0a3f7bec9db975db7b2526dac9624c0dc5 (patch) | |
tree | f76e629398c4d67cd735a6e168cc674b5e2ec028 | |
parent | 2a6c3e512baa6c237861d756d97cecf39e24ad4b (diff) | |
download | chromium_src-31a7fb0a3f7bec9db975db7b2526dac9624c0dc5.zip chromium_src-31a7fb0a3f7bec9db975db7b2526dac9624c0dc5.tar.gz chromium_src-31a7fb0a3f7bec9db975db7b2526dac9624c0dc5.tar.bz2 |
Additional OAuth2 tests for ChromeOS
- authentication attempt for invalid OAuth2 refresh token
- authentication of an existing user
BUG=none
TEST=OAuth2.*
Review URL: https://codereview.chromium.org/108663008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241581 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/login/oauth2_browsertest.cc | 260 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/saml_browsertest.cc | 18 | ||||
-rw-r--r-- | google_apis/gaia/fake_gaia.cc | 161 | ||||
-rw-r--r-- | google_apis/gaia/fake_gaia.h | 49 |
4 files changed, 407 insertions, 81 deletions
diff --git a/chrome/browser/chromeos/login/oauth2_browsertest.cc b/chrome/browser/chromeos/login/oauth2_browsertest.cc index bbbed3e..953d21c 100644 --- a/chrome/browser/chromeos/login/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/oauth2_browsertest.cc @@ -3,16 +3,26 @@ // found in the LICENSE file. #include "base/message_loop/message_loop.h" +#include "base/prefs/pref_service.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/oauth2_login_manager.h" #include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h" #include "chrome/browser/chromeos/login/oobe_base_test.h" +#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/signin/profile_oauth2_token_service.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "content/public/browser/notification_service.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" +#include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_monster.h" +#include "net/cookies/cookie_store.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" namespace chromeos { @@ -20,13 +30,18 @@ namespace { // Email of owner account for test. const char kTestAccountId[] = "username@gmail.com"; - +const char kTestRawAccountId[] = "User.Name"; +const char kTestAccountPassword[] = "fake-password"; const char kTestAuthCode[] = "fake-auth-code"; const char kTestGaiaUberToken[] = "fake-uber-token"; const char kTestAuthLoginAccessToken[] = "fake-access-token"; const char kTestRefreshToken[] = "fake-refresh-token"; +const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie"; +const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie"; const char kTestSessionSIDCookie[] = "fake-session-SID-cookie"; const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie"; +const char kTestSession2SIDCookie[] = "fake-session2-SID-cookie"; +const char kTestSession2LSIDCookie[] = "fake-session2-LSID-cookie"; const char kTestUserinfoToken[] = "fake-userinfo-token"; const char kTestLoginToken[] = "fake-login-token"; const char kTestSyncToken[] = "fake-sync-token"; @@ -40,16 +55,85 @@ class OAuth2Test : public OobeBaseTest { virtual void SetUpOnMainThread() OVERRIDE { OobeBaseTest::SetUpOnMainThread(); + } + + void SetupGaiaServerForNewAccount() { + FakeGaia::MergeSessionParams params; + params.auth_sid_cookie = kTestAuthSIDCookie; + params.auth_lsid_cookie = kTestAuthLSIDCookie; + params.auth_code = kTestAuthCode; + params.refresh_token = kTestRefreshToken; + params.access_token = kTestAuthLoginAccessToken; + params.gaia_uber_token = kTestGaiaUberToken; + params.session_sid_cookie = kTestSessionSIDCookie; + params.session_lsid_cookie = kTestSessionLSIDCookie; + fake_gaia_.SetMergeSessionParams(params); + SetupGaiaServerWithAccessTokens(); + } + + void SetupGaiaServerForExistingAccount() { + FakeGaia::MergeSessionParams params; + params.gaia_uber_token = kTestGaiaUberToken; + params.session_sid_cookie = kTestSession2SIDCookie; + params.session_lsid_cookie = kTestSession2LSIDCookie; + fake_gaia_.SetMergeSessionParams(params); + SetupGaiaServerWithAccessTokens(); + } + bool TryToLogin(const std::string& username, + const std::string& password) { + if (!AddUserTosession(username, password)) + return false; + + if (const User* active_user = UserManager::Get()->GetActiveUser()) + return active_user->email() == username; + + return false; + } + + User::OAuthTokenStatus GetOAuthStatusFromLocalState( + const std::string& user_id) const { + PrefService* local_state = g_browser_process->local_state(); + const DictionaryValue* prefs_oauth_status = + local_state->GetDictionary("OAuthTokenStatus"); + int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN; + if (prefs_oauth_status && + prefs_oauth_status->GetIntegerWithoutPathExpansion( + user_id, &oauth_token_status)) { + User::OAuthTokenStatus result = + static_cast<User::OAuthTokenStatus>(oauth_token_status); + return result; + } + return User::OAUTH_TOKEN_STATUS_UNKNOWN; + } + + private: + bool AddUserTosession(const std::string& username, + const std::string& password) { + ExistingUserController* controller = + ExistingUserController::current_controller(); + if (!controller) { + ADD_FAILURE(); + return false; + } + + controller->Login(UserContext(username, password, std::string())); + content::WindowedNotificationObserver( + chrome::NOTIFICATION_SESSION_STARTED, + content::NotificationService::AllSources()).Wait(); + const UserList& logged_users = UserManager::Get()->GetLoggedInUsers(); + for (UserList::const_iterator it = logged_users.begin(); + it != logged_users.end(); ++it) { + if ((*it)->email() == username) + return true; + } + return false; + } + + void SetupGaiaServerWithAccessTokens() { // Configure OAuth authentication. GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); - fake_gaia_.SetAuthTokens(kTestAuthCode, - kTestRefreshToken, - kTestAuthLoginAccessToken, - kTestGaiaUberToken, - kTestSessionSIDCookie, - kTestSessionLSIDCookie); // This token satisfies the userinfo.email request from // DeviceOAuth2TokenService used in token validation. FakeGaia::AccessTokenInfo userinfo_token_info; @@ -89,10 +173,68 @@ class OAuth2Test : public OobeBaseTest { fake_gaia_.IssueOAuthToken(kTestRefreshToken, auth_login_token_info); } - private: DISALLOW_COPY_AND_ASSIGN(OAuth2Test); }; +class CookieReader : public base::RefCountedThreadSafe<CookieReader> { + public: + CookieReader() { + } + + void ReadCookies(Profile* profile) { + context_ = profile->GetRequestContext(); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&CookieReader::ReadCookiesOnIOThread, + this)); + runner_ = new content::MessageLoopRunner; + runner_->Run(); + } + + std::string GetCookieValue(const std::string& name) { + for (std::vector<net::CanonicalCookie>::const_iterator iter = + cookie_list_.begin(); + iter != cookie_list_.end(); + ++iter) { + if (iter->Name() == name) { + return iter->Value(); + } + } + return std::string(); + } + + private: + friend class base::RefCountedThreadSafe<CookieReader>; + + virtual ~CookieReader() { + } + + void ReadCookiesOnIOThread() { + context_->GetURLRequestContext()->cookie_store()->GetCookieMonster()-> + GetAllCookiesAsync(base::Bind( + &CookieReader::OnGetAllCookiesOnUIThread, + this)); + } + + void OnGetAllCookiesOnUIThread(const net::CookieList& cookies) { + cookie_list_ = cookies; + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&CookieReader::OnCookiesReadyOnUIThread, + this)); + } + + void OnCookiesReadyOnUIThread() { + runner_->Quit(); + } + + scoped_refptr<net::URLRequestContextGetter> context_; + net::CookieList cookie_list_; + scoped_refptr<content::MessageLoopRunner> runner_; + + DISALLOW_COPY_AND_ASSIGN(CookieReader); +}; + class OAuth2LoginManagerStateWaiter : public OAuth2LoginManager::Observer { public: explicit OAuth2LoginManagerStateWaiter(Profile* profile) @@ -146,7 +288,9 @@ class OAuth2LoginManagerStateWaiter : public OAuth2LoginManager::Observer { DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter); }; -IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { +// PRE_MergeSession is testing merge session for a new profile. +IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_PRE_MergeSession) { + SetupGaiaServerForNewAccount(); SimulateNetworkOnline(); chromeos::WizardController::SkipPostLoginScreensForTesting(); chromeos::WizardController* wizard_controller = @@ -157,14 +301,20 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()).Wait(); + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH_TOKEN_STATUS_UNKNOWN); + // Use capitalized and dotted user name on purpose to make sure // our email normalization kicks in. - GetLoginDisplay()->ShowSigninScreenForCreds("User.Name", "password"); + GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawAccountId, + kTestAccountPassword); content::WindowedNotificationObserver( chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources()).Wait(); + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + // Wait for the session merge to finish. std::set<OAuth2LoginManager::SessionRestoreState> states; states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); @@ -174,6 +324,96 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { merge_session_waiter.WaitForStates(states); EXPECT_EQ(merge_session_waiter.final_state(), OAuth2LoginManager::SESSION_RESTORE_DONE); + + // Check for existance of refresh token. + ProfileOAuth2TokenService* token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile( + profile); + EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kTestAccountId)); + + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH2_TOKEN_STATUS_VALID); + + scoped_refptr<CookieReader> cookie_reader(new CookieReader()); + cookie_reader->ReadCookies(profile); + EXPECT_EQ(cookie_reader->GetCookieValue("SID"), kTestSessionSIDCookie); + EXPECT_EQ(cookie_reader->GetCookieValue("LSID"), kTestSessionLSIDCookie); +} + +// MergeSession test is running merge session process for an existing profile +// that was generated in PRE_PRE_MergeSession test. +IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_MergeSession) { + SetupGaiaServerForExistingAccount(); + SimulateNetworkOnline(); + + content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()).Wait(); + + JsExpect("!!document.querySelector('#account-picker')"); + JsExpect("!!document.querySelector('#pod-row')"); + + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH2_TOKEN_STATUS_VALID); + + EXPECT_TRUE(TryToLogin(kTestAccountId, kTestAccountPassword)); + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + + // Wait for the session merge to finish. + std::set<OAuth2LoginManager::SessionRestoreState> states; + states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); + states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); + states.insert(OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED); + OAuth2LoginManagerStateWaiter merge_session_waiter(profile); + merge_session_waiter.WaitForStates(states); + EXPECT_EQ(merge_session_waiter.final_state(), + OAuth2LoginManager::SESSION_RESTORE_DONE); + + // Check for existance of refresh token. + ProfileOAuth2TokenService* token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile(profile); + EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kTestAccountId)); + + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH2_TOKEN_STATUS_VALID); + + scoped_refptr<CookieReader> cookie_reader(new CookieReader()); + cookie_reader->ReadCookies(profile); + EXPECT_EQ(cookie_reader->GetCookieValue("SID"), kTestSession2SIDCookie); + EXPECT_EQ(cookie_reader->GetCookieValue("LSID"), kTestSession2LSIDCookie); +} + +// MergeSession test is attempting to merge session for an existing profile +// that was generated in PRE_PRE_MergeSession test. This attempt should fail +// since FakeGaia instance isn't configured to return relevant tokens/cookies. +IN_PROC_BROWSER_TEST_F(OAuth2Test, MergeSession) { + SimulateNetworkOnline(); + + content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()).Wait(); + + JsExpect("!!document.querySelector('#account-picker')"); + JsExpect("!!document.querySelector('#pod-row')"); + + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH2_TOKEN_STATUS_VALID); + + EXPECT_TRUE(TryToLogin(kTestAccountId, kTestAccountPassword)); + + // Wait for the session merge to finish. + std::set<OAuth2LoginManager::SessionRestoreState> states; + states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); + states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); + states.insert(OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED); + OAuth2LoginManagerStateWaiter merge_session_waiter( + ProfileManager::GetPrimaryUserProfile()); + merge_session_waiter.WaitForStates(states); + EXPECT_EQ(merge_session_waiter.final_state(), + OAuth2LoginManager::SESSION_RESTORE_FAILED); + + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), + User::OAUTH2_TOKEN_STATUS_INVALID); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/saml_browsertest.cc b/chrome/browser/chromeos/login/saml_browsertest.cc index 6b55bce4..91224c6 100644 --- a/chrome/browser/chromeos/login/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml_browsertest.cc @@ -36,6 +36,8 @@ namespace chromeos { namespace { +const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie"; +const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie"; const char kTestAuthCode[] = "fake-auth-code"; const char kTestGaiaUberToken[] = "fake-uber-token"; const char kTestAuthLoginAccessToken[] = "fake-access-token"; @@ -175,12 +177,16 @@ class SamlTest : public InProcessBrowserTest { } virtual void SetUpOnMainThread() OVERRIDE { - fake_gaia_.SetAuthTokens(kTestAuthCode, - kTestRefreshToken, - kTestAuthLoginAccessToken, - kTestGaiaUberToken, - kTestSessionSIDCookie, - kTestSessionLSIDCookie); + FakeGaia::MergeSessionParams params; + params.auth_sid_cookie = kTestAuthSIDCookie; + params.auth_lsid_cookie = kTestAuthLSIDCookie; + params.auth_code = kTestAuthCode; + params.refresh_token = kTestRefreshToken; + params.access_token = kTestAuthLoginAccessToken; + params.gaia_uber_token = kTestGaiaUberToken; + params.session_sid_cookie = kTestSessionSIDCookie; + params.session_lsid_cookie = kTestSessionLSIDCookie; + fake_gaia_.SetMergeSessionParams(params); embedded_test_server()->RegisterRequestHandler( base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_))); diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc index 9eddd85..3c1928a 100644 --- a/google_apis/gaia/fake_gaia.cc +++ b/google_apis/gaia/fake_gaia.cc @@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/json/json_writer.h" #include "base/logging.h" +#include "base/memory/linked_ptr.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -21,6 +22,7 @@ #include "base/values.h" #include "google_apis/gaia/gaia_urls.h" #include "net/base/url_util.h" +#include "net/cookies/parsed_cookie.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" @@ -45,6 +47,52 @@ const base::FilePath::CharType kServiceLogin[] = const char kAuthHeaderBearer[] = "Bearer "; const char kAuthHeaderOAuth[] = "OAuth "; +typedef std::map<std::string, std::string> CookieMap; + +// Parses cookie name-value map our of |request|. +CookieMap GetRequestCookies(const HttpRequest& request) { + CookieMap result; + std::map<std::string, std::string>::const_iterator iter = + request.headers.find("Cookie"); + if (iter != request.headers.end()) { + std::vector<std::string> cookie_nv_pairs; + base::SplitString(iter->second, ' ', &cookie_nv_pairs); + for(std::vector<std::string>::const_iterator cookie_line = + cookie_nv_pairs.begin(); + cookie_line != cookie_nv_pairs.end(); + ++cookie_line) { + std::vector<std::string> name_value; + base::SplitString(*cookie_line, '=', &name_value); + if (name_value.size() != 2) + continue; + + std::string value = name_value[1]; + if (value.size() && value[value.size() - 1] == ';') + value = value.substr(0, value.size() -1); + + result.insert(std::make_pair(name_value[0], value)); + } + } + return result; +} + +// Extracts the |access_token| from authorization header of |request|. +bool GetAccessToken(const HttpRequest& request, + const char* auth_token_prefix, + std::string* access_token) { + std::map<std::string, std::string>::const_iterator auth_header_entry = + request.headers.find("Authorization"); + if (auth_header_entry != request.headers.end()) { + if (StartsWithASCII(auth_header_entry->second, auth_token_prefix, true)) { + *access_token = auth_header_entry->second.substr( + strlen(auth_token_prefix)); + return true; + } + } + + return false; +} + } FakeGaia::AccessTokenInfo::AccessTokenInfo() @@ -52,6 +100,12 @@ FakeGaia::AccessTokenInfo::AccessTokenInfo() FakeGaia::AccessTokenInfo::~AccessTokenInfo() {} +FakeGaia::MergeSessionParams::MergeSessionParams() { +} + +FakeGaia::MergeSessionParams::~MergeSessionParams() { +} + FakeGaia::FakeGaia() { base::FilePath source_root_dir; PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir); @@ -62,18 +116,9 @@ FakeGaia::FakeGaia() { FakeGaia::~FakeGaia() {} -void FakeGaia::SetAuthTokens(const std::string& auth_code, - const std::string& refresh_token, - const std::string& access_token, - const std::string& gaia_uber_token, - const std::string& session_sid_cookie, - const std::string& session_lsid_cookie) { - fake_auth_code_ = auth_code; - fake_refresh_token_ = refresh_token; - fake_access_token_ = access_token; - fake_gaia_uber_token_ = gaia_uber_token; - fake_session_sid_cookie_ = session_sid_cookie; - fake_session_lsid_cookie_ = session_lsid_cookie; +void FakeGaia::SetMergeSessionParams( + const MergeSessionParams& params) { + merge_session_params_ = params; } void FakeGaia::Initialize() { @@ -117,18 +162,36 @@ void FakeGaia::Initialize() { void FakeGaia::HandleProgramaticAuth( const HttpRequest& request, BasicHttpResponse* http_response) { + http_response->set_code(net::HTTP_UNAUTHORIZED); + if (merge_session_params_.auth_code.empty()) { + http_response->set_code(net::HTTP_BAD_REQUEST); + return; + } + GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); std::string scope; if (!GetQueryParameter(request.content, "scope", &scope) || gaia_urls->oauth1_login_scope() != scope) { - http_response->set_code(net::HTTP_BAD_REQUEST); + return; + } + + CookieMap cookies = GetRequestCookies(request); + CookieMap::const_iterator sid_iter = cookies.find("SID"); + if (sid_iter == cookies.end() || + sid_iter->second != merge_session_params_.auth_sid_cookie) { + LOG(ERROR) << "/o/oauth2/programmatic_auth missing SID cookie"; + return; + } + CookieMap::const_iterator lsid_iter = cookies.find("LSID"); + if (lsid_iter == cookies.end() || + lsid_iter->second != merge_session_params_.auth_lsid_cookie) { + LOG(ERROR) << "/o/oauth2/programmatic_auth missing LSID cookie"; return; } std::string client_id; if (!GetQueryParameter(request.content, "client_id", &client_id) || gaia_urls->oauth2_chrome_client_id() != client_id) { - http_response->set_code(net::HTTP_BAD_REQUEST); return; } @@ -136,7 +199,7 @@ void FakeGaia::HandleProgramaticAuth( "Set-Cookie", base::StringPrintf( "oauth_code=%s; Path=/o/GetOAuth2Token; Secure; HttpOnly;", - fake_auth_code_.c_str())); + merge_session_params_.auth_code.c_str())); http_response->set_code(net::HTTP_OK); http_response->set_content_type("text/html"); } @@ -150,7 +213,12 @@ void FakeGaia::HandleServiceLogin(const HttpRequest& request, void FakeGaia::HandleOAuthLogin(const HttpRequest& request, BasicHttpResponse* http_response) { - http_response->set_code(net::HTTP_BAD_REQUEST); + http_response->set_code(net::HTTP_UNAUTHORIZED); + if (merge_session_params_.gaia_uber_token.empty()) { + http_response->set_code(net::HTTP_FORBIDDEN); + return; + } + std::string access_token; if (!GetAccessToken(request, kAuthHeaderOAuth, &access_token)) { LOG(ERROR) << "/OAuthLogin missing access token in the header"; @@ -169,7 +237,7 @@ void FakeGaia::HandleOAuthLogin(const HttpRequest& request, std::string issue_uberauth; if (GetQueryParameter(request_query, "issueuberauth", &issue_uberauth) && issue_uberauth == "1") { - http_response->set_content(fake_gaia_uber_token_); + http_response->set_content(merge_session_params_.gaia_uber_token); http_response->set_code(net::HTTP_OK); // Issue GAIA uber token. } else { @@ -179,11 +247,16 @@ void FakeGaia::HandleOAuthLogin(const HttpRequest& request, void FakeGaia::HandleMergeSession(const HttpRequest& request, BasicHttpResponse* http_response) { - http_response->set_code(net::HTTP_BAD_REQUEST); + http_response->set_code(net::HTTP_UNAUTHORIZED); + if (merge_session_params_.session_sid_cookie.empty() || + merge_session_params_.session_lsid_cookie.empty()) { + http_response->set_code(net::HTTP_BAD_REQUEST); + return; + } std::string uber_token; if (!GetQueryParameter(request.content, "uberauth", &uber_token) || - uber_token != fake_gaia_uber_token_) { + uber_token != merge_session_params_.gaia_uber_token) { LOG(ERROR) << "Missing or invalid 'uberauth' param in /MergeSession call"; return; } @@ -203,9 +276,13 @@ void FakeGaia::HandleMergeSession(const HttpRequest& request, http_response->AddCustomHeader( "Set-Cookie", base::StringPrintf( - "SID=%s; LSID=%s; Path=/; Secure; HttpOnly;", - fake_session_sid_cookie_.c_str(), - fake_session_lsid_cookie_.c_str())); + "SID=%s; Path=/; HttpOnly;", + merge_session_params_.session_sid_cookie.c_str())); + http_response->AddCustomHeader( + "Set-Cookie", + base::StringPrintf( + "LSID=%s; Path=/; HttpOnly;", + merge_session_params_.session_lsid_cookie.c_str())); // TODO(zelidrag): Not used now. http_response->set_content("OK"); http_response->set_code(net::HTTP_OK); @@ -229,6 +306,20 @@ void FakeGaia::HandleServiceLoginAuth(const HttpRequest& request, redirect_url = url.spec(); } + if (!merge_session_params_.auth_sid_cookie.empty() && + !merge_session_params_.auth_lsid_cookie.empty()) { + http_response->AddCustomHeader( + "Set-Cookie", + base::StringPrintf( + "SID=%s; Path=/; HttpOnly;", + merge_session_params_.auth_sid_cookie.c_str())); + http_response->AddCustomHeader( + "Set-Cookie", + base::StringPrintf( + "LSID=%s; Path=/; HttpOnly;", + merge_session_params_.auth_lsid_cookie.c_str())); + } + http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); http_response->AddCustomHeader("Location", redirect_url); } @@ -260,7 +351,7 @@ void FakeGaia::HandleAuthToken(const HttpRequest& request, if (grant_type == "authorization_code") { if (!GetQueryParameter(request.content, "code", &auth_code) || - auth_code != fake_auth_code_) { + auth_code != merge_session_params_.auth_code) { http_response->set_code(net::HTTP_BAD_REQUEST); LOG(ERROR) << "No 'code' param in /o/oauth2/token"; return; @@ -273,8 +364,10 @@ void FakeGaia::HandleAuthToken(const HttpRequest& request, } base::DictionaryValue response_dict; - response_dict.SetString("refresh_token", fake_refresh_token_); - response_dict.SetString("access_token", fake_access_token_); + response_dict.SetString("refresh_token", + merge_session_params_.refresh_token); + response_dict.SetString("access_token", + merge_session_params_.access_token); response_dict.SetInteger("expires_in", 3600); FormatJSONResponse(response_dict, http_response); } else if (GetQueryParameter(request.content, @@ -352,7 +445,6 @@ void FakeGaia::HandleIssueToken(const HttpRequest& request, } } - scoped_ptr<HttpResponse> FakeGaia::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|. @@ -422,20 +514,3 @@ bool FakeGaia::GetQueryParameter(const std::string& query, GURL query_url("http://localhost?" + query); return net::GetValueForKeyInQuery(query_url, key, value); } - -// static -bool FakeGaia::GetAccessToken(const HttpRequest& request, - const char* auth_token_prefix, - std::string* access_token) { - std::map<std::string, std::string>::const_iterator auth_header_entry = - request.headers.find("Authorization"); - if (auth_header_entry != request.headers.end()) { - if (StartsWithASCII(auth_header_entry->second, auth_token_prefix, true)) { - *access_token = auth_header_entry->second.substr( - strlen(auth_token_prefix)); - return true; - } - } - - return false; -} diff --git a/google_apis/gaia/fake_gaia.h b/google_apis/gaia/fake_gaia.h index 6052c2b..ae8c544 100644 --- a/google_apis/gaia/fake_gaia.h +++ b/google_apis/gaia/fake_gaia.h @@ -47,16 +47,36 @@ class FakeGaia { std::string email; }; + // Cookies and tokens for /MergeSession call seqeunce. + struct MergeSessionParams { + MergeSessionParams(); + ~MergeSessionParams(); + + // Values of SID and LSID cookie that are set by + std::string auth_sid_cookie; + std::string auth_lsid_cookie; + + // auth_code cookie value response for /o/oauth2/programmatic_auth call. + std::string auth_code; + + // OAuth2 refresh and access token generated by /o/oauth2/token call + // with "...&grant_type=authorization_code". + std::string refresh_token; + std::string access_token; + + // Uber token response from /OAuthLogin call. + std::string gaia_uber_token; + + // Values of SID and LSID cookie generated from /MergeSession call. + std::string session_sid_cookie; + std::string session_lsid_cookie; + }; + FakeGaia(); ~FakeGaia(); // Sets the initial value of tokens and cookies. - void SetAuthTokens(const std::string& auth_code, - const std::string& refresh_token, - const std::string& access_token, - const std::string& gaia_uber_token, - const std::string& session_sid_cookie, - const std::string& session_lsid_cookie); + void SetMergeSessionParams(const MergeSessionParams& params); // Initializes HTTP request handlers. Should be called after switches // for tweaking GaiaUrls are in place. @@ -131,22 +151,7 @@ class FakeGaia { const std::string& scope_string) const; - // Extracts the |access_token| from authorization header of |request|. - static bool GetAccessToken(const net::test_server::HttpRequest& request, - const char* auth_token_prefix, - std::string* access_token); - - // auth_code cookie value response for /o/oauth2/programmatic_auth call. - std::string fake_auth_code_; - - // refresh_token field value response for the initial /o/oauth2/token call - // with ...&grant_type=authorization_code. - std::string fake_refresh_token_; - std::string fake_access_token_; - std::string fake_gaia_uber_token_; - std::string fake_session_sid_cookie_; - std::string fake_session_lsid_cookie_; - + MergeSessionParams merge_session_params_; AccessTokenInfoMap access_token_info_map_; RequestHandlerMap request_handlers_; std::string service_login_response_; |