diff options
author | munjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-24 02:49:46 +0000 |
---|---|---|
committer | munjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-24 02:49:46 +0000 |
commit | dda6d0ddca97a3f4ba53decce35f26ec7305e3ac (patch) | |
tree | cf0bcc735273cf27a8d85b8fbac7c8ce19b700ce /chrome/common/net/gaia/gaia_auth_fetcher.cc | |
parent | 14a0cbd0e2cab5041b151ecc190c76efa9e11a06 (diff) | |
download | chromium_src-dda6d0ddca97a3f4ba53decce35f26ec7305e3ac.zip chromium_src-dda6d0ddca97a3f4ba53decce35f26ec7305e3ac.tar.gz chromium_src-dda6d0ddca97a3f4ba53decce35f26ec7305e3ac.tar.bz2 |
Revive reverted CL with fix for CrOS build.
The original CL was:
http://src.chromium.org/viewvc/chrome?view=rev&revision=111270
Codereview:
http://codereview.chromium.org/8632005/
Review URL: http://codereview.chromium.org/8662002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111485 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/net/gaia/gaia_auth_fetcher.cc')
-rw-r--r-- | chrome/common/net/gaia/gaia_auth_fetcher.cc | 227 |
1 files changed, 224 insertions, 3 deletions
diff --git a/chrome/common/net/gaia/gaia_auth_fetcher.cc b/chrome/common/net/gaia/gaia_auth_fetcher.cc index 0a861e6..f3f86d3 100644 --- a/chrome/common/net/gaia/gaia_auth_fetcher.cc +++ b/chrome/common/net/gaia/gaia_auth_fetcher.cc @@ -4,13 +4,16 @@ #include "chrome/common/net/gaia/gaia_auth_fetcher.h" +#include <algorithm> #include <string> #include <utility> #include <vector> +#include "base/json/json_reader.h" #include "base/string_split.h" #include "base/string_util.h" #include "base/stringprintf.h" +#include "base/values.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/gaia/gaia_urls.h" @@ -22,6 +25,13 @@ #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_status.h" +namespace { +static bool CookiePartsContains(const std::vector<std::string>& parts, + const char* part) { + return std::find(parts.begin(), parts.end(), part) != parts.end(); +} +} // namespace + // TODO(chron): Add sourceless version of this formatter. // static const char GaiaAuthFetcher::kClientLoginFormat[] = @@ -48,6 +58,16 @@ const char GaiaAuthFetcher::kIssueAuthTokenFormat[] = "service=%s&" "Session=%s"; // static +const char GaiaAuthFetcher::kClientLoginToOAuth2BodyFormat[] = + "scope=%s&client_id=%s"; +// static +const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] = + "scope=%s&" + "grant_type=authorization_code&" + "client_id=%s&" + "client_secret=%s&" + "code=%s"; +// static const char GaiaAuthFetcher::kGetUserInfoFormat[] = "LSID=%s"; // static @@ -100,6 +120,27 @@ const char GaiaAuthFetcher::kAccountTypeGoogle[] = // static const char GaiaAuthFetcher::kSecondFactor[] = "Info=InvalidSecondFactor"; +// static +const char GaiaAuthFetcher::kAuthHeaderFormat[] = + "Authorization: GoogleLogin auth=%s"; +// static +const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartSecure[] = "Secure"; +// static +const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartHttpOnly[] = + "HttpOnly"; +// static +const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix[] = + "oauth_code="; +// static +const int GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefixLength = + arraysize(GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix) - 1; +// static +const char GaiaAuthFetcher::kOAuth2RefreshTokenKey[] = "refresh_token"; +// static +const char GaiaAuthFetcher::kOAuth2AccessTokenKey[] = "access_token"; +// static +const char GaiaAuthFetcher::kOAuth2ExpiresInKey[] = "expires_in"; + GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, const std::string& source, net::URLRequestContextGetter* getter) @@ -108,6 +149,9 @@ GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, source_(source), client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()), issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()), + client_login_to_oauth2_gurl_( + GaiaUrls::GetInstance()->client_login_to_oauth2_url()), + oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), token_auth_gurl_(GaiaUrls::GetInstance()->token_auth_url()), merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), @@ -128,8 +172,9 @@ void GaiaAuthFetcher::CancelRequest() { content::URLFetcher* GaiaAuthFetcher::CreateGaiaFetcher( net::URLRequestContextGetter* getter, const std::string& body, + const std::string& headers, const GURL& gaia_gurl, - bool send_cookies, + bool use_cookies, content::URLFetcherDelegate* delegate) { content::URLFetcher* to_return = content::URLFetcher::Create( 0, gaia_gurl, content::URLFetcher::POST, delegate); @@ -141,8 +186,12 @@ content::URLFetcher* GaiaAuthFetcher::CreateGaiaFetcher( // maintain a separation between the user's browsing and Chrome's internal // services. Where such mixing is desired (MergeSession), it will be done // explicitly. - if (!send_cookies) - to_return->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES); + if (!use_cookies) { + to_return->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES); + } + if (!headers.empty()) + to_return->SetExtraRequestHeaders(headers); return to_return; } @@ -209,6 +258,34 @@ std::string GaiaAuthFetcher::MakeIssueAuthTokenBody( } // static +std::string GaiaAuthFetcher::MakeGetAuthCodeBody() { + std::string encoded_scope = net::EscapeUrlEncodedData( + GaiaUrls::GetInstance()->oauth1_login_scope(), true); + std::string encoded_client_id = net::EscapeUrlEncodedData( + GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); + return StringPrintf(kClientLoginToOAuth2BodyFormat, + encoded_scope.c_str(), + encoded_client_id.c_str()); +} + +// static +std::string GaiaAuthFetcher::MakeGetTokenPairBody( + const std::string& auth_code) { + std::string encoded_scope = net::EscapeUrlEncodedData( + GaiaUrls::GetInstance()->oauth1_login_scope(), true); + std::string encoded_client_id = net::EscapeUrlEncodedData( + GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); + std::string encoded_client_secret = net::EscapeUrlEncodedData( + GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), true); + std::string encoded_auth_code = net::EscapeUrlEncodedData(auth_code, true); + return StringPrintf(kOAuth2CodeToTokenPairBodyFormat, + encoded_scope.c_str(), + encoded_client_id.c_str(), + encoded_client_secret.c_str(), + encoded_auth_code.c_str()); +} + +// static std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) { std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); return base::StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str()); @@ -243,6 +320,12 @@ std::string GaiaAuthFetcher::MakeMergeSessionBody( encoded_source.c_str()); } +// static +std::string GaiaAuthFetcher::MakeGetAuthCodeHeader( + const std::string& auth_token) { + return StringPrintf(kAuthHeaderFormat, auth_token.c_str()); +} + // Helper method that extracts tokens from a successful reply. // static void GaiaAuthFetcher::ParseClientLoginResponse(const std::string& data, @@ -293,6 +376,72 @@ void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, } } +// static +bool GaiaAuthFetcher::ParseClientLoginToOAuth2Response( + const net::ResponseCookies& cookies, + std::string* auth_code) { + DCHECK(auth_code); + net::ResponseCookies::const_iterator iter; + for (iter = cookies.begin(); iter != cookies.end(); ++iter) { + if (ParseClientLoginToOAuth2Cookie(*iter, auth_code)) + return true; + } + return false; +} + +// static +bool GaiaAuthFetcher::ParseOAuth2TokenPairResponse(const std::string& data, + std::string* refresh_token, + std::string* access_token, + int* expires_in_secs) { + DCHECK(refresh_token); + DCHECK(access_token); + base::JSONReader reader; + scoped_ptr<base::Value> value(reader.Read(data, false)); + if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY) + return false; + + DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); + std::string rt; + std::string at; + int exp; + + if (!dict->GetStringWithoutPathExpansion(kOAuth2RefreshTokenKey, &rt) || + !dict->GetStringWithoutPathExpansion(kOAuth2AccessTokenKey, &at) || + !dict->GetIntegerWithoutPathExpansion(kOAuth2ExpiresInKey, &exp)) { + return false; + } + + refresh_token->assign(rt); + access_token->assign(at); + *expires_in_secs = exp; + return true; +} + +// static +bool GaiaAuthFetcher::ParseClientLoginToOAuth2Cookie(const std::string& cookie, + std::string* auth_code) { + std::vector<std::string> parts; + base::SplitString(cookie, ';', &parts); + // Per documentation, the cookie should have Secure and HttpOnly. + if (!CookiePartsContains(parts, kClientLoginToOAuth2CookiePartSecure) || + !CookiePartsContains(parts, kClientLoginToOAuth2CookiePartHttpOnly)) { + return false; + } + + std::vector<std::string>::const_iterator iter; + for (iter = parts.begin(); iter != parts.end(); ++iter) { + const std::string& part = *iter; + if (StartsWithASCII( + part, kClientLoginToOAuth2CookiePartCodePrefix, false)) { + auth_code->assign(part.substr( + kClientLoginToOAuth2CookiePartCodePrefixLength)); + return true; + } + } + return false; +} + void GaiaAuthFetcher::StartClientLogin( const std::string& username, const std::string& password, @@ -317,6 +466,7 @@ void GaiaAuthFetcher::StartClientLogin( allow_hosted_accounts); fetcher_.reset(CreateGaiaFetcher(getter_, request_body_, + "", client_login_gurl_, false, this)); @@ -334,6 +484,7 @@ void GaiaAuthFetcher::StartIssueAuthToken(const std::string& sid, request_body_ = MakeIssueAuthTokenBody(sid, lsid, service); fetcher_.reset(CreateGaiaFetcher(getter_, request_body_, + "", issue_auth_token_gurl_, false, this)); @@ -341,6 +492,22 @@ void GaiaAuthFetcher::StartIssueAuthToken(const std::string& sid, fetcher_->Start(); } +void GaiaAuthFetcher::StartOAuthLoginTokenFetch( + const std::string& auth_token) { + DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; + + DVLOG(1) << "Starting OAuth login token fetch"; + request_body_ = MakeGetAuthCodeBody(); + fetcher_.reset(CreateGaiaFetcher(getter_, + request_body_, + MakeGetAuthCodeHeader(auth_token), + client_login_to_oauth2_gurl_, + false, + this)); + fetch_pending_ = true; + fetcher_->Start(); +} + void GaiaAuthFetcher::StartGetUserInfo(const std::string& lsid, const std::string& info_key) { DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; @@ -349,6 +516,7 @@ void GaiaAuthFetcher::StartGetUserInfo(const std::string& lsid, request_body_ = MakeGetUserInfoBody(lsid); fetcher_.reset(CreateGaiaFetcher(getter_, request_body_, + "", get_user_info_gurl_, false, this)); @@ -369,6 +537,7 @@ void GaiaAuthFetcher::StartTokenAuth(const std::string& auth_token) { request_body_ = MakeTokenAuthBody(auth_token, continue_url, source_); fetcher_.reset(CreateGaiaFetcher(getter_, request_body_, + "", token_auth_gurl_, false, this)); @@ -393,6 +562,7 @@ void GaiaAuthFetcher::StartMergeSession(const std::string& auth_token) { request_body_ = MakeMergeSessionBody(auth_token, continue_url, source_); fetcher_.reset(CreateGaiaFetcher(getter_, request_body_, + "", merge_session_gurl_, true, this)); @@ -536,6 +706,52 @@ void GaiaAuthFetcher::OnIssueAuthTokenFetched( } } +void GaiaAuthFetcher::OnClientLoginToOAuth2Fetched( + const std::string& data, + const net::ResponseCookies& cookies, + const net::URLRequestStatus& status, + int response_code) { + if (status.is_success() && response_code == RC_REQUEST_OK) { + std::string auth_code; + ParseClientLoginToOAuth2Response(cookies, &auth_code); + StartOAuth2TokenPairFetch(auth_code); + } else { + consumer_->OnOAuthLoginTokenFailure(GenerateAuthError(data, status)); + } +} + +void GaiaAuthFetcher::StartOAuth2TokenPairFetch(const std::string& auth_code) { + DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; + + DVLOG(1) << "Starting OAuth token pair fetch"; + request_body_ = MakeGetTokenPairBody(auth_code); + fetcher_.reset(CreateGaiaFetcher(getter_, + request_body_, + "", + oauth2_token_gurl_, + false, + this)); + fetch_pending_ = true; + fetcher_->Start(); +} + +void GaiaAuthFetcher::OnOAuth2TokenPairFetched( + const std::string& data, + const net::URLRequestStatus& status, + int response_code) { + if (status.is_success() && response_code == RC_REQUEST_OK) { + std::string refresh_token; + std::string access_token; + int expires_in_secs; + ParseOAuth2TokenPairResponse( + data, &refresh_token, &access_token, &expires_in_secs); + consumer_->OnOAuthLoginTokenSuccess( + refresh_token, access_token, expires_in_secs); + } else { + consumer_->OnOAuthLoginTokenFailure(GenerateAuthError(data, status)); + } +} + void GaiaAuthFetcher::OnGetUserInfoFetched( const std::string& data, const net::URLRequestStatus& status, @@ -591,6 +807,11 @@ void GaiaAuthFetcher::OnURLFetchComplete(const content::URLFetcher* source) { OnClientLoginFetched(data, status, response_code); } else if (url == issue_auth_token_gurl_) { OnIssueAuthTokenFetched(data, status, response_code); + } else if (url == client_login_to_oauth2_gurl_) { + OnClientLoginToOAuth2Fetched( + data, source->GetCookies(), status, response_code); + } else if (url == oauth2_token_gurl_) { + OnOAuth2TokenPairFetched(data, status, response_code); } else if (url == get_user_info_gurl_) { OnGetUserInfoFetched(data, status, response_code); } else if (url == token_auth_gurl_) { |