gaia_auth_fetcher.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_fetcher.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_split.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLoadFlagsIgnoreCookies = net::LOAD_DO_NOT_SEND_COOKIES | 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CookiePartsContains(const std::vector<std::string>& parts, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* part) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::find(parts.begin(), parts.end(), part) != parts.end(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtractOAuth2TokenPairResponse(DictionaryValue* dict, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* refresh_token, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* access_token, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* expires_in_secs) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(refresh_token); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(access_token); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(expires_in_secs); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token) || 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !dict->GetStringWithoutPathExpansion("access_token", access_token) || 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(chron): Add sourceless version of this formatter. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginFormat[] = 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Email=%s&" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Passwd=%s&" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "PersistentCookie=%s&" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "accountType=%s&" 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s&" 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s"; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginCaptchaFormat[] = 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Email=%s&" 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Passwd=%s&" 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "PersistentCookie=%s&" 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "accountType=%s&" 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s&" 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s&" 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "logintoken=%s&" 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "logincaptcha=%s"; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kIssueAuthTokenFormat[] = 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SID=%s&" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LSID=%s&" 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s&" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Session=%s"; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2BodyFormat[] = 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&client_id=%s"; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] = 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "grant_type=authorization_code&" 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "client_id=%s&" 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "client_secret=%s&" 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "code=%s"; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kGetUserInfoFormat[] = 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LSID=%s"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kMergeSessionFormat[] = 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uberauth=%s&" 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "continue=%s&" 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s"; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kUberAuthTokenURLFormat[] = 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s?source=%s&" 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "issueuberauth=1"; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuthLoginFormat[] = "service=%s&source=%s"; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDeletedError[] = "AccountDeleted"; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDeletedErrorCode[] = "adel"; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDisabledError[] = "AccountDisabled"; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDisabledErrorCode[] = "adis"; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kBadAuthenticationError[] = "BadAuthentication"; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kBadAuthenticationErrorCode[] = "badauth"; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaError[] = "CaptchaRequired"; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaErrorCode[] = "cr"; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kServiceUnavailableError[] = 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ServiceUnavailable"; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kServiceUnavailableErrorCode[] = 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ire"; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kErrorParam[] = "Error"; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kErrorUrlParam[] = "Url"; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaUrlParam[] = "CaptchaUrl"; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaTokenParam[] = "CaptchaToken"; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kNeedsAdditional[] = "NeedsAdditional"; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptcha[] = "Captcha"; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kTwoFactor[] = "TwoStep"; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCookiePersistence[] = "true"; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(johnnyg): When hosted accounts are supported by sync, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can always use "HOSTED_OR_GOOGLE" 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeHostedOrGoogle[] = 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "HOSTED_OR_GOOGLE"; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeGoogle[] = 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "GOOGLE"; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kSecondFactor[] = "Info=InvalidSecondFactor"; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAuthHeaderFormat[] = 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Authorization: GoogleLogin auth=%s"; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuthHeaderFormat[] = "Authorization: OAuth %s"; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartSecure[] = "Secure"; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartHttpOnly[] = 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "HttpOnly"; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix[] = 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "oauth_code="; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefixLength = 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix) - 1; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : consumer_(consumer), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getter_(getter), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_(source), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()), 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uberauth_token_gurl_(base::StringPrintf(kUberAuthTokenURLFormat, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth1_login_url().c_str(), source.c_str())), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_oauth_gurl_(GaiaUrls::GetInstance()->client_oauth_url()), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()), 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_( 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url()), 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_(false) {} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaAuthFetcher::~GaiaAuthFetcher() {} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::HasPendingFetch() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fetch_pending_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::CancelRequest() { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = false; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLFetcher* GaiaAuthFetcher::CreateGaiaFetcher( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& body, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& headers, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& gaia_gurl, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int load_flags, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcherDelegate* delegate) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* to_return = net::URLFetcher::Create( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, gaia_gurl, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body == "" ? net::URLFetcher::GET : net::URLFetcher::POST, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetRequestContext(getter); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetUploadData("application/x-www-form-urlencoded", body); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher URL: " << gaia_gurl.spec(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher headers: " << headers; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher body: " << body; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Gaia token exchange requests do not require any cookie-based 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // identification as part of requests. We suppress sending any cookies to 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // maintain a separation between the user's browsing and Chrome's internal 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // services. Where such mixing is desired (MergeSession), it will be done 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetLoadFlags(load_flags); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!headers.empty()) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetExtraRequestHeaders(headers); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return to_return; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeClientLoginBody( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* service, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_username = net::EscapeUrlEncodedData(username, true); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_password = net::EscapeUrlEncodedData(password, true); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_login_token = net::EscapeUrlEncodedData(login_token, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_login_captcha = net::EscapeUrlEncodedData(login_captcha, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* account_type = allow_hosted_accounts == HostedAccountsAllowed ? 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAccountTypeHostedOrGoogle : 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAccountTypeGoogle; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (login_token.empty() || login_captcha.empty()) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kClientLoginFormat, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_username.c_str(), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_password.c_str(), 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCookiePersistence, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) account_type, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.c_str(), 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kClientLoginCaptchaFormat, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_username.c_str(), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_password.c_str(), 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCookiePersistence, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) account_type, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.c_str(), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_login_token.c_str(), 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_login_captcha.c_str()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeIssueAuthTokenBody( 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& sid, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_sid = net::EscapeUrlEncodedData(sid, true); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All tokens should be session tokens except the gaia auth token. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool session = true; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strcmp(service, GaiaConstants::kGaiaService)) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session = false; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kIssueAuthTokenFormat, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_sid.c_str(), 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_lsid.c_str(), 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session ? "true" : "false"); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeBody() { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth1_login_scope(), true); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_id = net::EscapeUrlEncodedData( 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringPrintf(kClientLoginToOAuth2BodyFormat, 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_scope.c_str(), 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_client_id.c_str()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetTokenPairBody( 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth1_login_scope(), true); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_id = net::EscapeUrlEncodedData( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_secret = net::EscapeUrlEncodedData( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), true); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_code = net::EscapeUrlEncodedData(auth_code, true); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringPrintf(kOAuth2CodeToTokenPairBodyFormat, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_scope.c_str(), 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_client_id.c_str(), 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_client_secret.c_str(), 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_auth_code.c_str()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeMergeSessionBody( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& continue_url, 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_token = net::EscapeUrlEncodedData(auth_token, true); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_continue_url = net::EscapeUrlEncodedData(continue_url, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kMergeSessionFormat, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_auth_token.c_str(), 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_continue_url.c_str(), 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_source.c_str()); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeHeader( 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringPrintf(kAuthHeaderFormat, auth_token.c_str()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper method that extracts tokens from a successful reply. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginResponse(const std::string& data, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* sid, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* lsid, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* token) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != tokens.end(); ++i) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first == "SID") { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sid->assign(i->second); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "LSID") { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lsid->assign(i->second); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "Auth") { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token->assign(i->second); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeClientOAuthBody( 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<std::string>& scopes, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& persistent_id, 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& friendly_name, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& locale) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthEmailKey, username); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthPasswordKey, password); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> scope_list(new base::ListValue); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < scopes.size(); ++i) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scope_list->Append(base::Value::CreateStringValue(scopes[i])); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set(GaiaConstants::kClientOAuthScopesKey, scope_list.release()); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthOAuth2ClientIdKey, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id()); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // crbug.com/129600: use a less generic friendly name. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthFriendlyDeviceNameKey, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friendly_name); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> accepts_challenge_list(new base::ListValue); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accepts_challenge_list->Append(base::Value::CreateStringValue(kCaptcha)); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accepts_challenge_list->Append(base::Value::CreateStringValue(kTwoFactor)); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set(GaiaConstants::kClientOAuthAcceptsChallengesKey, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accepts_challenge_list.release()); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthLocaleKey, locale); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome presently does not not support a web-fallback for ClientOAuth, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but need to hardcode an arbitrary one here since the endpoint expects it. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString(GaiaConstants::kClientOAuthFallbackNameKey, "GetOAuth2Token"); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string json_string; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONWriter::Write(dict.get(), &json_string); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return json_string; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeClientOAuthChallengeResponseBody( 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& token, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& solution) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string field_name = name == kTwoFactor ? "otp" : "solution"; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> challenge_reply(new base::DictionaryValue); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_reply->SetString(GaiaConstants::kClientOAuthNameKey, name); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_reply->SetString(GaiaConstants::kClientOAuthChallengeTokenKey, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_reply->SetString(field_name, solution); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set(GaiaConstants::kClientOAuthchallengeReplyKey, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_reply.release()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string json_string; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONWriter::Write(dict.get(), &json_string); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return json_string; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_service = net::EscapeUrlEncodedData(service, true); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringPrintf(kOAuthLoginFormat, encoded_service.c_str(), 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_source.c_str()); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error, 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error_url, 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_url, 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_token) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != tokens.end(); ++i) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first == kErrorParam) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error->assign(i->second); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kErrorUrlParam) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_url->assign(i->second); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaUrlParam) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_url->assign(i->second); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaTokenParam) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token->assign(i->second); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Response( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(auth_code); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::ResponseCookies::const_iterator iter; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = cookies.begin(); iter != cookies.end(); ++iter) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ParseClientLoginToOAuth2Cookie(*iter, auth_code)) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Cookie(const std::string& cookie, 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> parts; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(cookie, ';', &parts); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Per documentation, the cookie should have Secure and HttpOnly. 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CookiePartsContains(parts, kClientLoginToOAuth2CookiePartSecure) || 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CookiePartsContains(parts, kClientLoginToOAuth2CookiePartHttpOnly)) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>::const_iterator iter; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = parts.begin(); iter != parts.end(); ++iter) { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& part = *iter; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII( 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) part, kClientLoginToOAuth2CookiePartCodePrefix, false)) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_code->assign(part.substr( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kClientLoginToOAuth2CookiePartCodePrefixLength)); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleServiceAuthError 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaAuthFetcher::GenerateClientOAuthError(const std::string& data, 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GenerateAuthError(data, status); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cause; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dict->GetStringWithoutPathExpansion("cause", &cause)) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cause != kNeedsAdditional) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* challenge; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dict->GetDictionaryWithoutPathExpansion("challenge", &challenge)) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!challenge->GetStringWithoutPathExpansion("name", &name)) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == kCaptcha) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string audio_url; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string image_url; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_width; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_height; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!challenge->GetStringWithoutPathExpansion("challenge_token", &token) || 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !challenge->GetStringWithoutPathExpansion("audio_url", &audio_url) || 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !challenge->GetStringWithoutPathExpansion("image_url", &image_url) || 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !challenge->GetIntegerWithoutPathExpansion("image_width", 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &image_width) || 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !challenge->GetIntegerWithoutPathExpansion("image_height", 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &image_height)) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromCaptchaChallenge(token, GURL(audio_url), 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL(image_url), 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_width, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_height); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (name == kTwoFactor) { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string prompt_text; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string alternate_text; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int field_length; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The protocol doc says these are required, but in practice they are not 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. So only a missing challenge token will cause an error here. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge->GetStringWithoutPathExpansion("prompt_text", &prompt_text); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge->GetStringWithoutPathExpansion("alternate_text", &alternate_text); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge->GetIntegerWithoutPathExpansion("field_length", &field_length); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!challenge->GetStringWithoutPathExpansion("challenge_token", &token)) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromSecondFactorChallenge(token, prompt_text, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternate_text, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) field_length); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientOAuthError(data); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartClientLogin( 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service, 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This class is thread agnostic, so be sure to call this only on the 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same thread each time. 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting new ClientLogin fetch for:" << username; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must outlive fetcher_. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeClientLoginBody(username, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password, 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_token, 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_captcha, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allow_hosted_accounts); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_gurl_, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartIssueAuthToken(const std::string& sid, 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting IssueAuthToken for: " << service; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requested_service_ = service; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeIssueAuthTokenBody(sid, lsid, service); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issue_auth_token_gurl_, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartLsoForOAuthLoginTokenExchange( 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token exchange with auth_token"; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL(GaiaUrls::GetInstance()->client_login_to_oauth2_url()); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeGetAuthCodeHeader(auth_token), 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange( 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& session_index) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token fetch with cookie jar"; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = GaiaUrls::GetInstance()->client_login_to_oauth2_url(); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!session_index.empty()) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url += "?authuser=" + session_index; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = GURL(url); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartGetUserInfo(const std::string& lsid) { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting GetUserInfo for lsid=" << lsid; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetUserInfoBody(lsid); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_user_info_gurl_, 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartMergeSession(const std::string& uber_token) { 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting MergeSession with uber_token=" << uber_token; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The continue URL is a required parameter of the MergeSession API, but in 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this case we don't actually need or want to navigate to it. Setting it to 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an arbitrary Google URL. 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In order for the new session to be merged correctly, the server needs to 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // know what sessions already exist in the browser. The fetcher needs to be 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created such that it sends the cookies with the request, which is 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // different from all other requests the fetcher can make. 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string continue_url("http://www.google.com"); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeMergeSessionBody(uber_token, continue_url, source_); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_, 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartTokenFetchForUberAuthExchange( 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token) { 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting StartTokenFetchForUberAuthExchange with access_token=" 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << access_token; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string authentication_header = 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf(kOAuthHeaderFormat, access_token.c_str()); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authentication_header, 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uberauth_token_gurl_, 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartClientOAuth(const std::string& username, 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<std::string>& scopes, 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& persistent_id, 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& locale) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeClientOAuthBody(username, password, scopes, persistent_id, 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_, locale); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_oauth_gurl_, 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartClientOAuthChallengeResponse( 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::State type, 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& token, 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& solution) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GoogleServiceAuthError::CAPTCHA_REQUIRED: 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = kCaptcha; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GoogleServiceAuthError::TWO_FACTOR: 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = kTwoFactor; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeClientOAuthChallengeResponseBody(name, token, solution); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_oauth_gurl_, 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartOAuthLogin(const std::string& access_token, 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeOAuthLoginBody(service, source_); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string authentication_header = 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("Authorization: Bearer %s", access_token.c_str()); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authentication_header, 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_, 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status) { 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.is_success()) { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() == net::URLRequestStatus::CANCELED) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << status.error(); 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromConnectionError(status.error()); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsSecondFactorSuccess(data)) { 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string captcha_url; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string captcha_token; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "ClientLogin failed with " << error; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kCaptchaError) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL image_url( 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->captcha_url_prefix() + captcha_url); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL unlock_url(url); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token, image_url, unlock_url); 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDeletedError) 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDisabledError) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kBadAuthenticationError) { 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kServiceUnavailableError) { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Incomprehensible response from Google Accounts servers."; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleServiceAuthError GaiaAuthFetcher::GenerateOAuthLoginError( 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status) { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.is_success()) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() == net::URLRequestStatus::CANCELED) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << status.error(); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromConnectionError(status.error()); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsSecondFactorSuccess(data)) { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string captcha_url; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string captcha_token; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "OAuthLogin failed with " << error; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kCaptchaErrorCode) { 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL image_url( 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->captcha_url_prefix() + captcha_url); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL unlock_url(url); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token, image_url, unlock_url); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDeletedErrorCode) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDisabledErrorCode) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kBadAuthenticationErrorCode) { 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kServiceUnavailableErrorCode) { 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Incomprehensible response from Google Accounts servers."; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientLoginFetched(const std::string& data, 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ClientLogin successful!"; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sid; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string lsid; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginResponse(data, &sid, &lsid, &token); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginSuccess( 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnIssueAuthTokenFetched( 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only the bare token is returned in the body of this Gaia call 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without any padding. 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnIssueAuthTokenSuccess(requested_service_, data); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnIssueAuthTokenFailure(requested_service_, 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateAuthError(data, status)); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientLoginToOAuth2Fetched( 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_code; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginToOAuth2Response(cookies, &auth_code); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartOAuth2TokenPairFetch(auth_code); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthFailure(GenerateAuthError(data, status)); 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartOAuth2TokenPairFetch(const std::string& auth_code) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth token pair fetch"; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetTokenPairBody(auth_code); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_token_gurl_, 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnOAuth2TokenPairFetched( 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string refresh_token; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token; 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expires_in_secs = 0; 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) { 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = ExtractOAuth2TokenPairResponse(dict, &refresh_token, 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &access_token, &expires_in_secs); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthSuccess( 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token, 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expires_in_secs)); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthFailure(GenerateAuthError(data, status)); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnGetUserInfoFetched( 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::pair<std::string, std::string> > tokens; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserInfoMap matches; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::pair<std::string, std::string> >::iterator i; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = tokens.begin(); i != tokens.end(); ++i) { 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches[i->first] = i->second; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnGetUserInfoSuccess(matches); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnGetUserInfoFailure(GenerateAuthError(data, status)); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnMergeSessionFetched(const std::string& data, 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnMergeSessionSuccess(data); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnMergeSessionFailure(GenerateAuthError(data, status)); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnUberAuthTokenFetch(const std::string& data, 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnUberAuthTokenSuccess(data); 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnUberAuthTokenFailure(GenerateAuthError(data, status)); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientOAuthFetched(const std::string& data, 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string refresh_token; 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expires_in_secs = 0; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) { 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* dict_oauth2; 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dict->GetDictionaryWithoutPathExpansion("oauth2", &dict_oauth2)) { 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = ExtractOAuth2TokenPairResponse(dict_oauth2, &refresh_token, 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &access_token, 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &expires_in_secs); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rogerta): for now this reuses the OnOAuthLoginTokenXXX callbacks 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since the data is exactly the same. This ignores the optional 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // persistent_id data in the response, which we may need to handle. 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we do, we'll need to modify ExtractOAuth2TokenPairResponse() to parse 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the optional data and declare new consumer callbacks to take it. 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthSuccess( 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token, 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expires_in_secs)); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthFailure(GenerateClientOAuthError(data, status)); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnOAuthLoginFetched(const std::string& data, 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ClientLogin successful!"; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sid; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string lsid; 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginResponse(data, &sid, &lsid, &token); 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginSuccess( 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = false; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some of the GAIA requests perform redirects, which results in the final 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL of the fetcher not being the original URL requested. Therefore use 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original URL when determining which OnXXX function to call. 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url = source->GetOriginalURL(); 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status = source->GetStatus(); 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code = source->GetResponseCode(); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetResponseAsString(&data); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher response code: " << response_code; 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher response data: " << data; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url == client_login_gurl_) { 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnClientLoginFetched(data, status, response_code); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == issue_auth_token_gurl_) { 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnIssueAuthTokenFetched(data, status, response_code); 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == client_login_to_oauth2_gurl_) { 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnClientLoginToOAuth2Fetched( 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, source->GetCookies(), status, response_code); 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == oauth2_token_gurl_) { 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnOAuth2TokenPairFetched(data, status, response_code); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == get_user_info_gurl_) { 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnGetUserInfoFetched(data, status, response_code); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == merge_session_gurl_) { 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnMergeSessionFetched(data, status, response_code); 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == uberauth_token_gurl_) { 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUberAuthTokenFetch(data, status, response_code); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == client_oauth_gurl_) { 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnClientOAuthFetched(data, status, response_code); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == oauth_login_gurl_) { 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnOAuthLoginFetched(data, status, response_code); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::IsSecondFactorSuccess( 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& alleged_error) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alleged_error.find(kSecondFactor) != 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string::npos; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1107