summaryrefslogtreecommitdiffstats
path: root/chrome/common/net/gaia/gaia_auth_fetcher.cc
diff options
context:
space:
mode:
authormunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-24 02:49:46 +0000
committermunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-24 02:49:46 +0000
commitdda6d0ddca97a3f4ba53decce35f26ec7305e3ac (patch)
treecf0bcc735273cf27a8d85b8fbac7c8ce19b700ce /chrome/common/net/gaia/gaia_auth_fetcher.cc
parent14a0cbd0e2cab5041b151ecc190c76efa9e11a06 (diff)
downloadchromium_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.cc227
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_) {