gaia_auth_fetcher.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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 <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.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) { 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<std::string>::const_iterator it = parts.begin(); 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != parts.end(); ++it) { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (LowerCaseEqualsASCII(*it, part)) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ExtractOAuth2TokenPairResponse(base::DictionaryValue* dict, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* refresh_token, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* access_token, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* expires_in_secs) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(refresh_token); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(access_token); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(expires_in_secs); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token) || 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !dict->GetStringWithoutPathExpansion("access_token", access_token) || 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(chron): Add sourceless version of this formatter. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginFormat[] = 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Email=%s&" 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Passwd=%s&" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "PersistentCookie=%s&" 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "accountType=%s&" 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s&" 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s"; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginCaptchaFormat[] = 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Email=%s&" 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Passwd=%s&" 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "PersistentCookie=%s&" 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "accountType=%s&" 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s&" 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s&" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "logintoken=%s&" 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "logincaptcha=%s"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kIssueAuthTokenFormat[] = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SID=%s&" 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LSID=%s&" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s&" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Session=%s"; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2BodyFormat[] = 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&client_id=%s"; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2WithDeviceTypeBodyFormat[] = 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "scope=%s&client_id=%s&device_type=chrome"; 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] = 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&" 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "grant_type=authorization_code&" 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "client_id=%s&" 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "client_secret=%s&" 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "code=%s"; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char GaiaAuthFetcher::kOAuth2RevokeTokenBodyFormat[] = 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "token=%s"; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kGetUserInfoFormat[] = 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LSID=%s"; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kMergeSessionFormat[] = 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uberauth=%s&" 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "continue=%s&" 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s"; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kUberAuthTokenURLFormat[] = 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "?source=%s&" 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "issueuberauth=1"; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuthLoginFormat[] = "service=%s&source=%s"; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDeletedError[] = "AccountDeleted"; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountDisabledError[] = "AccountDisabled"; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kBadAuthenticationError[] = "BadAuthentication"; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaError[] = "CaptchaRequired"; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kServiceUnavailableError[] = 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ServiceUnavailable"; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kErrorParam[] = "Error"; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kErrorUrlParam[] = "Url"; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaUrlParam[] = "CaptchaUrl"; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCaptchaTokenParam[] = "CaptchaToken"; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kCookiePersistence[] = "true"; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(johnnyg): When hosted accounts are supported by sync, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can always use "HOSTED_OR_GOOGLE" 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeHostedOrGoogle[] = 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "HOSTED_OR_GOOGLE"; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeGoogle[] = 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "GOOGLE"; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kSecondFactor[] = "Info=InvalidSecondFactor"; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kAuthHeaderFormat[] = 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Authorization: GoogleLogin auth=%s"; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuthHeaderFormat[] = "Authorization: OAuth %s"; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char GaiaAuthFetcher::kOAuth2BearerHeaderFormat[] = 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Authorization: Bearer %s"; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char GaiaAuthFetcher::kDeviceIdHeaderFormat[] = "X-Device-ID: %s"; 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartSecure[] = "secure"; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartHttpOnly[] = 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "httponly"; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix[] = 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "oauth_code="; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefixLength = 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix) - 1; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : consumer_(consumer), 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getter_(getter), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_(source), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) oauth2_revoke_gurl_(GaiaUrls::GetInstance()->oauth2_revoke_url()), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uberauth_token_gurl_(GaiaUrls::GetInstance()->oauth1_login_url().Resolve( 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StringPrintf(kUberAuthTokenURLFormat, source.c_str()))), 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()), 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) list_accounts_gurl_(GaiaUrls::GetInstance()->list_accounts_url()), 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) get_check_connection_info_url_( 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GaiaUrls::GetInstance()->get_check_connection_info_url()), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_( 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url()), 19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) fetch_pending_(false) {} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaAuthFetcher::~GaiaAuthFetcher() {} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::HasPendingFetch() { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fetch_pending_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::CancelRequest() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = false; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLFetcher* GaiaAuthFetcher::CreateGaiaFetcher( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& body, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& headers, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& gaia_gurl, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int load_flags, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcherDelegate* delegate) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* to_return = net::URLFetcher::Create( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, gaia_gurl, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body == "" ? net::URLFetcher::GET : net::URLFetcher::POST, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetRequestContext(getter); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetUploadData("application/x-www-form-urlencoded", body); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher URL: " << gaia_gurl.spec(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher headers: " << headers; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher body: " << body; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Gaia token exchange requests do not require any cookie-based 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // identification as part of requests. We suppress sending any cookies to 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // maintain a separation between the user's browsing and Chrome's internal 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // services. Where such mixing is desired (MergeSession or OAuthLogin), it 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // will be done explicitly. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetLoadFlags(load_flags); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fetchers are sometimes cancelled because a network change was detected, 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // especially at startup and after sign-in on ChromeOS. Retrying once should 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be enough in those cases; let the fetcher retry up to 3 times just in case. 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // http://crbug.com/163710 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_return->SetAutomaticallyRetryOnNetworkChanges(3); 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!headers.empty()) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetExtraRequestHeaders(headers); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return to_return; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeClientLoginBody( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* service, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_username = net::EscapeUrlEncodedData(username, true); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_password = net::EscapeUrlEncodedData(password, true); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_login_token = net::EscapeUrlEncodedData(login_token, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_login_captcha = net::EscapeUrlEncodedData(login_captcha, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* account_type = allow_hosted_accounts == HostedAccountsAllowed ? 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAccountTypeHostedOrGoogle : 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAccountTypeGoogle; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (login_token.empty() || login_captcha.empty()) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kClientLoginFormat, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_username.c_str(), 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_password.c_str(), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCookiePersistence, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) account_type, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.c_str(), 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kClientLoginCaptchaFormat, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_username.c_str(), 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_password.c_str(), 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCookiePersistence, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) account_type, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.c_str(), 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_login_token.c_str(), 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_login_captcha.c_str()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeIssueAuthTokenBody( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& sid, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_sid = net::EscapeUrlEncodedData(sid, true); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All tokens should be session tokens except the gaia auth token. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool session = true; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strcmp(service, GaiaConstants::kGaiaService)) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session = false; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kIssueAuthTokenFormat, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_sid.c_str(), 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_lsid.c_str(), 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session ? "true" : "false"); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeBody(bool include_device_type) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GaiaConstants::kOAuth1LoginScope, true); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_id = net::EscapeUrlEncodedData( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (include_device_type) { 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return base::StringPrintf(kClientLoginToOAuth2WithDeviceTypeBodyFormat, 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encoded_scope.c_str(), 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encoded_client_id.c_str()); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return base::StringPrintf(kClientLoginToOAuth2BodyFormat, 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encoded_scope.c_str(), 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encoded_client_id.c_str()); 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetTokenPairBody( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GaiaConstants::kOAuth1LoginScope, true); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_id = net::EscapeUrlEncodedData( 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_secret = net::EscapeUrlEncodedData( 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), true); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_code = net::EscapeUrlEncodedData(auth_code, true); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(kOAuth2CodeToTokenPairBodyFormat, 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_scope.c_str(), 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_client_id.c_str(), 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_client_secret.c_str(), 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_auth_code.c_str()); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GaiaAuthFetcher::MakeRevokeTokenBody( 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& auth_token) { 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::StringPrintf(kOAuth2RevokeTokenBodyFormat, auth_token.c_str()); 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str()); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeMergeSessionBody( 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& external_cc_result, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& continue_url, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_token = net::EscapeUrlEncodedData(auth_token, true); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_continue_url = net::EscapeUrlEncodedData(continue_url, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string result = base::StringPrintf(kMergeSessionFormat, 3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) encoded_auth_token.c_str(), 3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) encoded_continue_url.c_str(), 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) encoded_source.c_str()); 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!external_cc_result.empty()) { 3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::StringAppendF(&result, "&externalCcResult=%s", 3676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::EscapeUrlEncodedData( 3686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) external_cc_result, true).c_str()); 3696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return result; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeHeader( 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(kAuthHeaderFormat, auth_token.c_str()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper method that extracts tokens from a successful reply. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginResponse(const std::string& data, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* sid, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* lsid, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* token) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sid->clear(); 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsid->clear(); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token->clear(); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != tokens.end(); ++i) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first == "SID") { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sid->assign(i->second); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "LSID") { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lsid->assign(i->second); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "Auth") { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token->assign(i->second); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this was a request for uberauth token, then that's all we've got in 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data. 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sid->empty() && lsid->empty() && token->empty()) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token->assign(data); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_service = net::EscapeUrlEncodedData(service, true); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(kOAuthLoginFormat, 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_service.c_str(), 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoded_source.c_str()); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error_url, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_url, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_token) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != tokens.end(); ++i) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first == kErrorParam) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error->assign(i->second); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kErrorUrlParam) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_url->assign(i->second); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaUrlParam) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_url->assign(i->second); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaTokenParam) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token->assign(i->second); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Response( 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(auth_code); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::ResponseCookies::const_iterator iter; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = cookies.begin(); iter != cookies.end(); ++iter) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ParseClientLoginToOAuth2Cookie(*iter, auth_code)) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Cookie(const std::string& cookie, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> parts; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(cookie, ';', &parts); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Per documentation, the cookie should have Secure and HttpOnly. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CookiePartsContains(parts, kClientLoginToOAuth2CookiePartSecure) || 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CookiePartsContains(parts, kClientLoginToOAuth2CookiePartHttpOnly)) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>::const_iterator iter; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = parts.begin(); iter != parts.end(); ++iter) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& part = *iter; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII( 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) part, kClientLoginToOAuth2CookiePartCodePrefix, false)) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_code->assign(part.substr( 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kClientLoginToOAuth2CookiePartCodePrefixLength)); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartClientLogin( 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This class is thread agnostic, so be sure to call this only on the 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same thread each time. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting new ClientLogin fetch for:" << username; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must outlive fetcher_. 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeClientLoginBody(username, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_token, 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_captcha, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allow_hosted_accounts); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_gurl_, 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartIssueAuthToken(const std::string& sid, 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service) { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting IssueAuthToken for: " << service; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requested_service_ = service; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeIssueAuthTokenBody(sid, lsid, service); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issue_auth_token_gurl_, 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartLsoForOAuthLoginTokenExchange( 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token exchange with auth_token"; 538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(false); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = 540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url(); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeGetAuthCodeHeader(auth_token), 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GaiaAuthFetcher::StartRevokeOAuth2Token(const std::string& auth_token) { 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Starting OAuth2 token revocation"; 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request_body_ = MakeRevokeTokenBody(auth_token); 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request_body_, 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) oauth2_revoke_gurl_, 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLoadFlagsIgnoreCookies, 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this)); 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fetch_pending_ = true; 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fetcher_->Start(); 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange( 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& session_index) { 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) StartCookieForOAuthLoginTokenExchangeWithDeviceId(session_index, 570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string()); 571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchangeWithDeviceId( 574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& session_index, 575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& device_id) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token fetch with cookie jar"; 579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(!device_id.empty()); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) client_login_to_oauth2_gurl_ = 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url(); 583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!session_index.empty()) { 584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) client_login_to_oauth2_gurl_ = 585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) client_login_to_oauth2_gurl_.Resolve("?authuser=" + session_index); 586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string device_id_header; 589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!device_id.empty()) { 590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device_id_header = 591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::StringPrintf(kDeviceIdHeaderFormat, device_id.c_str()); 592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device_id_header, 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GaiaAuthFetcher::StartAuthCodeForOAuth2TokenExchange( 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& auth_code) { 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Starting OAuth token pair fetch"; 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_ = MakeGetTokenPairBody(auth_code); 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_, 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) oauth2_token_gurl_, 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kLoadFlagsIgnoreCookies, 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this)); 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetch_pending_ = true; 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher_->Start(); 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartGetUserInfo(const std::string& lsid) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting GetUserInfo for lsid=" << lsid; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetUserInfoBody(lsid); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_user_info_gurl_, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void GaiaAuthFetcher::StartMergeSession(const std::string& uber_token, 6366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& external_cc_result) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting MergeSession with uber_token=" << uber_token; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The continue URL is a required parameter of the MergeSession API, but in 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this case we don't actually need or want to navigate to it. Setting it to 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an arbitrary Google URL. 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In order for the new session to be merged correctly, the server needs to 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // know what sessions already exist in the browser. The fetcher needs to be 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created such that it sends the cookies with the request, which is 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // different from all other requests the fetcher can make. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string continue_url("http://www.google.com"); 6506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) request_body_ = MakeMergeSessionBody(uber_token, external_cc_result, 6516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) continue_url, source_); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_, 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartTokenFetchForUberAuthExchange( 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting StartTokenFetchForUberAuthExchange with access_token=" 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << access_token; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string authentication_header = 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf(kOAuthHeaderFormat, access_token.c_str()); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authentication_header, 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uberauth_token_gurl_, 674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::LOAD_NORMAL, 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartOAuthLogin(const std::string& access_token, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeOAuthLoginBody(service, source_); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string authentication_header = 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf(kOAuth2BearerHeaderFormat, access_token.c_str()); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authentication_header, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_, 691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::LOAD_NORMAL, 692f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) this)); 693f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) fetch_pending_ = true; 694f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) fetcher_->Start(); 695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void GaiaAuthFetcher::StartListAccounts() { 698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) " ", // To force an HTTP POST. 702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "Origin: https://www.google.com", 703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) list_accounts_gurl_, 704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::LOAD_NORMAL, 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void GaiaAuthFetcher::StartGetCheckConnectionInfo() { 7116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 7126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 7136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 7146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string(), 7156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string(), 7166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) get_check_connection_info_url_, 7176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kLoadFlagsIgnoreCookies, 7186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this)); 7196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fetch_pending_ = true; 7206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fetcher_->Start(); 7216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 7226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status) { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.is_success()) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() == net::URLRequestStatus::CANCELED) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 73123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 73223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) << status.error(); 73323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GoogleServiceAuthError::FromConnectionError(status.error()); 73423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (IsSecondFactorSuccess(data)) 73723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 73823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 73923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string error; 74023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string url; 74123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string captcha_url; 74223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string captcha_token; 74323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); 74423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DLOG(WARNING) << "ClientLogin failed with " << error; 74523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 74623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (error == kCaptchaError) { 74723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 74823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) captcha_token, 74923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GURL(GaiaUrls::GetInstance()->captcha_base_url().Resolve(captcha_url)), 75023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GURL(url)); 75123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 75223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (error == kAccountDeletedError) 75323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); 75423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (error == kAccountDisabledError) 75523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); 75623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (error == kBadAuthenticationError) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 75823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 76023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (error == kServiceUnavailableError) { 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 76523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DLOG(WARNING) << "Incomprehensible response from Google Accounts servers."; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientLoginFetched(const std::string& data, 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ClientLogin successful!"; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sid; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string lsid; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginResponse(data, &sid, &lsid, &token); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginSuccess( 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnIssueAuthTokenFetched( 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only the bare token is returned in the body of this Gaia call 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without any padding. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnIssueAuthTokenSuccess(requested_service_, data); 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnIssueAuthTokenFailure(requested_service_, 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateAuthError(data, status)); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientLoginToOAuth2Fetched( 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_code; 8066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (ParseClientLoginToOAuth2Response(cookies, &auth_code)) { 8076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) StartAuthCodeForOAuth2TokenExchange(auth_code); 8086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 8096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GoogleServiceAuthError auth_error( 8106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GoogleServiceAuthError::FromUnexpectedServiceResponse( 8116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "ClientLogin response cookies didn't contain an auth code")); 8126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) consumer_->OnClientOAuthFailure(auth_error); 8136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GoogleServiceAuthError auth_error(GenerateAuthError(data, status)); 81646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) consumer_->OnClientOAuthFailure(auth_error); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnOAuth2TokenPairFetched( 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string refresh_token; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token; 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expires_in_secs = 0; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) { 832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::DictionaryValue* dict = 833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<base::DictionaryValue*>(value.get()); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = ExtractOAuth2TokenPairResponse(dict, &refresh_token, 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &access_token, &expires_in_secs); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthSuccess( 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token, 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expires_in_secs)); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientOAuthFailure(GenerateAuthError(data, status)); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GaiaAuthFetcher::OnOAuth2RevokeTokenFetched( 849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& data, 850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const net::URLRequestStatus& status, 851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int response_code) { 852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) consumer_->OnOAuth2RevokeTokenCompleted(); 853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 855f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void GaiaAuthFetcher::OnListAccountsFetched(const std::string& data, 856f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const net::URLRequestStatus& status, 857f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int response_code) { 858f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 859f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) consumer_->OnListAccountsSuccess(data); 860f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 861f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) consumer_->OnListAccountsFailure(GenerateAuthError(data, status)); 862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 863f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 864f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnGetUserInfoFetched( 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::pair<std::string, std::string> > tokens; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserInfoMap matches; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::pair<std::string, std::string> >::iterator i; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = tokens.begin(); i != tokens.end(); ++i) { 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches[i->first] = i->second; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnGetUserInfoSuccess(matches); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnGetUserInfoFailure(GenerateAuthError(data, status)); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnMergeSessionFetched(const std::string& data, 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnMergeSessionSuccess(data); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnMergeSessionFailure(GenerateAuthError(data, status)); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnUberAuthTokenFetch(const std::string& data, 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnUberAuthTokenSuccess(data); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnUberAuthTokenFailure(GenerateAuthError(data, status)); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnOAuthLoginFetched(const std::string& data, 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code) { 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ClientLogin successful!"; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sid; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string lsid; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginResponse(data, &sid, &lsid, &token); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginSuccess( 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void GaiaAuthFetcher::OnGetCheckConnectionInfoFetched( 9206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& data, 9216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const net::URLRequestStatus& status, 9226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int response_code) { 9236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 9246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) consumer_->OnGetCheckConnectionInfoSuccess(data); 9256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 9266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) consumer_->OnGetCheckConnectionInfoError(GenerateAuthError(data, status)); 9276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 9296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = false; 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some of the GAIA requests perform redirects, which results in the final 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL of the fetcher not being the original URL requested. Therefore use 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original URL when determining which OnXXX function to call. 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url = source->GetOriginalURL(); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status = source->GetStatus(); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code = source->GetResponseCode(); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetResponseAsString(&data); 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NDEBUG 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string headers; 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (source->GetResponseHeaders()) 9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source->GetResponseHeaders()->GetNormalizedHeaders(&headers); 9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "Response " << url.spec() << ", code = " << response_code << "\n" 9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << headers << "\n"; 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "data: " << data << "\n"; 9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Retrieve the response headers from the request. Must only be called after 9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the OnURLFetchComplete callback has run. 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url == client_login_gurl_) { 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnClientLoginFetched(data, status, response_code); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == issue_auth_token_gurl_) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnIssueAuthTokenFetched(data, status, response_code); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == client_login_to_oauth2_gurl_) { 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnClientLoginToOAuth2Fetched( 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, source->GetCookies(), status, response_code); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == oauth2_token_gurl_) { 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnOAuth2TokenPairFetched(data, status, response_code); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == get_user_info_gurl_) { 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnGetUserInfoFetched(data, status, response_code); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == merge_session_gurl_) { 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnMergeSessionFetched(data, status, response_code); 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == uberauth_token_gurl_) { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUberAuthTokenFetch(data, status, response_code); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (url == oauth_login_gurl_) { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnOAuthLoginFetched(data, status, response_code); 967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (url == oauth2_revoke_gurl_) { 968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnOAuth2RevokeTokenFetched(data, status, response_code); 969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (url == list_accounts_gurl_) { 970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OnListAccountsFetched(data, status, response_code); 9716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (url == get_check_connection_info_url_) { 9726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnGetCheckConnectionInfoFetched(data, status, response_code); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::IsSecondFactorSuccess( 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& alleged_error) { 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alleged_error.find(kSecondFactor) != 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string::npos; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 984