Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Unified Diff: google_apis/gaia/gaia_auth_fetcher.cc

Issue 973953002: Implement the calls to GAIA for the IDP IFrame protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Roger and Guibin's nits and comments Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « google_apis/gaia/gaia_auth_fetcher.h ('k') | google_apis/gaia/gaia_auth_fetcher_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: google_apis/gaia/gaia_auth_fetcher.cc
diff --git a/google_apis/gaia/gaia_auth_fetcher.cc b/google_apis/gaia/gaia_auth_fetcher.cc
index 3b3c1902540489725987f862119e7e63f3a98f6a..224cb6c340bb202de347cc3ffdad24a8d0918600 100644
--- a/google_apis/gaia/gaia_auth_fetcher.cc
+++ b/google_apis/gaia/gaia_auth_fetcher.cc
@@ -41,23 +41,39 @@ static bool CookiePartsContains(const std::vector<std::string>& parts,
return false;
}
-bool ExtractOAuth2TokenPairResponse(base::DictionaryValue* dict,
+// From the JSON string |data|, extract the |access_token| and |expires_in_secs|
+// both of which must exist. If the |refresh_token| is non-NULL, then it also
+// must exist and is extraced; if it's NULL, then no extraction is attempted.
+bool ExtractOAuth2TokenPairResponse(const std::string& data,
std::string* refresh_token,
std::string* access_token,
int* expires_in_secs) {
- DCHECK(refresh_token);
DCHECK(access_token);
DCHECK(expires_in_secs);
- if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token) ||
- !dict->GetStringWithoutPathExpansion("access_token", access_token) ||
+ scoped_ptr<base::Value> value(base::JSONReader::Read(data));
+ if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY)
+ return false;
+
+ base::DictionaryValue* dict =
+ static_cast<base::DictionaryValue*>(value.get());
+
+ if (!dict->GetStringWithoutPathExpansion("access_token", access_token) ||
!dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) {
return false;
}
+ // Refresh token may not be required.
+ if (refresh_token) {
+ if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token))
+ return false;
+ }
return true;
}
+const char kListIdpServiceRequested[] = "list_idp";
+const char kGetTokenResponseRequested[] = "get_token";
+
} // namespace
// TODO(chron): Add sourceless version of this formatter.
@@ -192,6 +208,7 @@ GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer,
GaiaUrls::GetInstance()->ListAccountsURLWithSource(source)),
get_check_connection_info_url_(
GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(source)),
+ oauth2_iframe_url_(GaiaUrls::GetInstance()->oauth2_iframe_url()),
client_login_to_oauth2_gurl_(
GaiaUrls::GetInstance()->client_login_to_oauth2_url()),
fetch_pending_(false) {}
@@ -422,6 +439,45 @@ std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service,
}
// static
+std::string GaiaAuthFetcher::MakeListIDPSessionsBody(
+ const std::string& scopes,
+ const std::string& domain) {
+ static const char getTokenResponseBodyFormat[] =
+ "action=listSessions&"
+ "client_id=%s&"
+ "e=3100087&" // temporarily enable the experiment.
+ "origin=%s&"
+ "scope=%s";
+ std::string encoded_client_id = net::EscapeUrlEncodedData(
+ GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true);
+ return base::StringPrintf(getTokenResponseBodyFormat,
+ encoded_client_id.c_str(),
+ domain.c_str(),
+ scopes.c_str());
+}
+
+std::string GaiaAuthFetcher::MakeGetTokenResponseBody(
+ const std::string& scopes,
+ const std::string& domain,
+ const std::string& login_hint) {
+ static const char getTokenResponseBodyFormat[] =
+ "action=issueToken&"
+ "client_id=%s&"
+ "login_hint=%s&"
+ "origin=%s&"
+ "e=3100087&" // temporarily enable the experiment.
+ "response_type=token&"
+ "scope=%s";
+ std::string encoded_client_id = net::EscapeUrlEncodedData(
+ GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true);
+ return base::StringPrintf(getTokenResponseBodyFormat,
+ encoded_client_id.c_str(),
+ login_hint.c_str(),
+ domain.c_str(),
+ scopes.c_str());
+}
+
+// static
void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data,
std::string* error,
std::string* error_url,
@@ -484,6 +540,39 @@ bool GaiaAuthFetcher::ParseClientLoginToOAuth2Cookie(const std::string& cookie,
return false;
}
+// static
+bool GaiaAuthFetcher::ParseListIdpSessionsResponse(const std::string& data,
+ std::string* login_hint) {
+ DCHECK(login_hint);
+
+ scoped_ptr<base::Value> value(base::JSONReader::Read(data));
+ if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY)
+ return false;
+
+ base::DictionaryValue* dict =
+ static_cast<base::DictionaryValue*>(value.get());
+
+ base::ListValue* sessionsList;
+ if (!dict->GetList("sessions", &sessionsList))
+ return false;
+
+ // Find the first login_hint present in any session.
+ for (base::ListValue::iterator iter = sessionsList->begin();
+ iter != sessionsList->end();
+ iter++) {
+ base::DictionaryValue* sessionDictionary;
+ if (!(*iter)->GetAsDictionary(&sessionDictionary))
+ continue;
+
+ if (sessionDictionary->GetString("login_hint", login_hint))
+ break;
+ }
+
+ if (login_hint->empty())
+ return false;
+ return true;
+}
+
void GaiaAuthFetcher::StartClientLogin(
const std::string& username,
const std::string& password,
@@ -724,6 +813,40 @@ void GaiaAuthFetcher::StartGetCheckConnectionInfo() {
fetcher_->Start();
}
+void GaiaAuthFetcher::StartListIDPSessions(const std::string& scopes,
+ const std::string& domain) {
+ DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
+
+ request_body_ = MakeListIDPSessionsBody(scopes, domain);
+ fetcher_.reset(CreateGaiaFetcher(getter_,
+ request_body_,
+ std::string(),
+ oauth2_iframe_url_,
+ net::LOAD_NORMAL,
+ this));
+ requested_service_ = kListIdpServiceRequested;
+ fetch_pending_ = true;
+ fetcher_->Start();
+}
+
+void GaiaAuthFetcher::StartGetTokenResponse(const std::string& scopes,
+ const std::string& domain,
+ const std::string& login_hint) {
+ DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
+
+ request_body_ = MakeGetTokenResponseBody(scopes, domain, login_hint);
+ fetcher_.reset(CreateGaiaFetcher(getter_,
+ request_body_,
+ std::string(),
+ oauth2_iframe_url_,
+ net::LOAD_NORMAL,
+ this));
+
+ requested_service_ = kGetTokenResponseRequested;
+ fetch_pending_ = true;
+ fetcher_->Start();
+}
+
// static
GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError(
const std::string& data,
@@ -834,13 +957,8 @@ void GaiaAuthFetcher::OnOAuth2TokenPairFetched(
bool success = false;
if (status.is_success() && response_code == net::HTTP_OK) {
- scoped_ptr<base::Value> value(base::JSONReader::Read(data));
- if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) {
- base::DictionaryValue* dict =
- static_cast<base::DictionaryValue*>(value.get());
- success = ExtractOAuth2TokenPairResponse(dict, &refresh_token,
+ success = ExtractOAuth2TokenPairResponse(data, &refresh_token,
&access_token, &expires_in_secs);
- }
}
if (success) {
@@ -934,6 +1052,48 @@ void GaiaAuthFetcher::OnGetCheckConnectionInfoFetched(
}
}
+void GaiaAuthFetcher::OnListIdpSessionsFetched(
+ const std::string& data,
+ const net::URLRequestStatus& status,
+ int response_code) {
+ if (status.is_success() && response_code == net::HTTP_OK) {
+ DVLOG(1) << "ListIdpSessions successful!";
+ std::string login_hint;
+ if (ParseListIdpSessionsResponse(data, &login_hint)) {
+ consumer_->OnListIdpSessionsSuccess(login_hint);
+ } else {
+ GoogleServiceAuthError auth_error(
+ GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "List Sessions response didn't contain a login_hint."));
+ consumer_->OnListIdpSessionsError(auth_error);
+ }
+ } else {
+ consumer_->OnListIdpSessionsError(GenerateAuthError(data, status));
+ }
+}
+
+void GaiaAuthFetcher::OnGetTokenResponseFetched(
+ const std::string& data,
+ const net::URLRequestStatus& status,
+ int response_code) {
+ std::string access_token;
+ int expires_in_secs = 0;
+ bool success = false;
+ if (status.is_success() && response_code == net::HTTP_OK) {
+ DVLOG(1) << "GetTokenResponse successful!";
+ success = ExtractOAuth2TokenPairResponse(data, NULL,
+ &access_token, &expires_in_secs);
+ }
+
+ if (success) {
+ consumer_->OnGetTokenResponseSuccess(
+ GaiaAuthConsumer::ClientOAuthResult(std::string(), access_token,
+ expires_in_secs));
+ } else {
+ consumer_->OnGetTokenResponseError(GenerateAuthError(data, status));
+ }
+}
+
void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
fetch_pending_ = false;
// Some of the GAIA requests perform redirects, which results in the final
@@ -977,6 +1137,13 @@ void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
OnListAccountsFetched(data, status, response_code);
} else if (url == get_check_connection_info_url_) {
OnGetCheckConnectionInfoFetched(data, status, response_code);
+ } else if (url == oauth2_iframe_url_) {
+ if (requested_service_ == kListIdpServiceRequested)
+ OnListIdpSessionsFetched(data, status, response_code);
+ else if (requested_service_ == kGetTokenResponseRequested)
+ OnGetTokenResponseFetched(data, status, response_code);
+ else
+ NOTREACHED();
} else {
NOTREACHED();
}
« no previous file with comments | « google_apis/gaia/gaia_auth_fetcher.h ('k') | google_apis/gaia/gaia_auth_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698