gaia_auth_fetcher.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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> 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_split.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/base/escape.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/load_flags.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/http/http_response_headers.h" 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "net/http/http_status_code.h" 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "net/url_request/url_fetcher.h" 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/url_request/url_request_status.h" 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kLoadFlagsIgnoreCookies = net::LOAD_DO_NOT_SEND_COOKIES | 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CookiePartsContains(const std::vector<std::string>& parts, 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const char* part) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<std::string>::const_iterator it = parts.begin(); 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != parts.end(); ++it) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LowerCaseEqualsASCII(*it, part)) 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ExtractOAuth2TokenPairResponse(base::DictionaryValue* dict, 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string* refresh_token, 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string* access_token, 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int* expires_in_secs) { 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(refresh_token); 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (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) || 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !dict->GetStringWithoutPathExpansion("access_token", access_token) || 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(chron): Add sourceless version of this formatter. 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginFormat[] = 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Email=%s&" 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Passwd=%s&" 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "PersistentCookie=%s&" 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "accountType=%s&" 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "source=%s&" 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s"; 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char GaiaAuthFetcher::kClientLoginCaptchaFormat[] = 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (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&" 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "logincaptcha=%s"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kIssueAuthTokenFormat[] = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SID=%s&" 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "LSID=%s&" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service=%s&" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Session=%s"; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2BodyFormat[] = 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&client_id=%s"; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] = 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scope=%s&" 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "grant_type=authorization_code&" 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "client_id=%s&" 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "client_secret=%s&" 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "code=%s"; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char GaiaAuthFetcher::kOAuth2RevokeTokenBodyFormat[] = 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "token=%s"; 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kGetUserInfoFormat[] = 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "LSID=%s"; 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kMergeSessionFormat[] = 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "uberauth=%s&" 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "continue=%s&" 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "source=%s"; 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kUberAuthTokenURLFormat[] = 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "?source=%s&" 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "issueuberauth=1"; 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kOAuthLoginFormat[] = "service=%s&source=%s"; 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountDeletedError[] = "AccountDeleted"; 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountDeletedErrorCode[] = "adel"; 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountDisabledError[] = "AccountDisabled"; 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountDisabledErrorCode[] = "adis"; 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kBadAuthenticationError[] = "BadAuthentication"; 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kBadAuthenticationErrorCode[] = "badauth"; 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kCaptchaError[] = "CaptchaRequired"; 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kCaptchaErrorCode[] = "cr"; 12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kServiceUnavailableError[] = 12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "ServiceUnavailable"; 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kServiceUnavailableErrorCode[] = 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "ire"; 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kErrorParam[] = "Error"; 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kErrorUrlParam[] = "Url"; 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kCaptchaUrlParam[] = "CaptchaUrl"; 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kCaptchaTokenParam[] = "CaptchaToken"; 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kCookiePersistence[] = "true"; 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(johnnyg): When hosted accounts are supported by sync, 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// we can always use "HOSTED_OR_GOOGLE" 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeHostedOrGoogle[] = 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "HOSTED_OR_GOOGLE"; 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kAccountTypeGoogle[] = 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "GOOGLE"; 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char GaiaAuthFetcher::kSecondFactor[] = "Info=InvalidSecondFactor"; 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char GaiaAuthFetcher::kAuthHeaderFormat[] = 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Authorization: GoogleLogin auth=%s"; 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char GaiaAuthFetcher::kOAuthHeaderFormat[] = "Authorization: OAuth %s"; 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kOAuth2BearerHeaderFormat[] = 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Authorization: Bearer %s"; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartSecure[] = "secure"; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartHttpOnly[] = 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "httponly"; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix[] = 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "oauth_code="; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefixLength = 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(GaiaAuthFetcher::kClientLoginToOAuth2CookiePartCodePrefix) - 1; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& source, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : consumer_(consumer), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getter_(getter), 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) source_(source), 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_revoke_gurl_(GaiaUrls::GetInstance()->oauth2_revoke_url()), 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uberauth_token_gurl_(GaiaUrls::GetInstance()->oauth1_login_url().Resolve( 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf(kUberAuthTokenURLFormat, source.c_str()))), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()), 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) list_accounts_gurl_(GaiaUrls::GetInstance()->list_accounts_url()), 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) client_login_to_oauth2_gurl_( 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url()), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_(false), 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_code_only_(false) {} 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)GaiaAuthFetcher::~GaiaAuthFetcher() {} 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::HasPendingFetch() { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fetch_pending_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void GaiaAuthFetcher::CancelRequest() { 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetcher_.reset(); 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetch_pending_ = false; 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnet::URLFetcher* GaiaAuthFetcher::CreateGaiaFetcher( 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLRequestContextGetter* getter, 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& body, 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& headers, 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& gaia_gurl, 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int load_flags, 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLFetcherDelegate* delegate) { 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLFetcher* to_return = net::URLFetcher::Create( 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 0, gaia_gurl, 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch body == "" ? net::URLFetcher::GET : net::URLFetcher::POST, 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch delegate); 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch to_return->SetRequestContext(getter); 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) to_return->SetUploadData("application/x-www-form-urlencoded", body); 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DVLOG(2) << "Gaia fetcher URL: " << gaia_gurl.spec(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Gaia fetcher headers: " << headers; 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DVLOG(2) << "Gaia fetcher body: " << body; 22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (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 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // maintain a separation between the user's browsing and Chrome's internal 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // services. Where such mixing is desired (MergeSession or OAuthLogin), it 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // will be done explicitly. 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) to_return->SetLoadFlags(load_flags); 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetchers are sometimes cancelled because a network change was detected, 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // especially at startup and after sign-in on ChromeOS. Retrying once should 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // be enough in those cases; let the fetcher retry up to 3 times just in case. 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // http://crbug.com/163710 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetAutomaticallyRetryOnNetworkChanges(3); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!headers.empty()) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_return->SetExtraRequestHeaders(headers); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return to_return; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GaiaAuthFetcher::MakeClientLoginBody( 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& username, 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& password, 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& source, 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* service, 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& login_token, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HostedAccountsSetting allow_hosted_accounts) { 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encoded_username = net::EscapeUrlEncodedData(username, true); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encoded_password = net::EscapeUrlEncodedData(password, true); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encoded_login_token = net::EscapeUrlEncodedData(login_token, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (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 ? 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kAccountTypeHostedOrGoogle : 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAccountTypeGoogle; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (login_token.empty() || login_captcha.empty()) { 26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return base::StringPrintf(kClientLoginFormat, 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (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 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeBody() { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (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); 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return base::StringPrintf(kClientLoginToOAuth2BodyFormat, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_scope.c_str(), 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_client_id.c_str()); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetTokenPairBody( 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_scope = net::EscapeUrlEncodedData( 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaConstants::kOAuth1LoginScope, true); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_id = net::EscapeUrlEncodedData( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_client_secret = net::EscapeUrlEncodedData( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), true); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_code = net::EscapeUrlEncodedData(auth_code, true); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kOAuth2CodeToTokenPairBodyFormat, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_scope.c_str(), 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encoded_client_id.c_str(), 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_client_secret.c_str(), 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_auth_code.c_str()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeRevokeTokenBody( 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kOAuth2RevokeTokenBodyFormat, auth_token.c_str()); 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) { 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str()); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeMergeSessionBody( 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& continue_url, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_token = net::EscapeUrlEncodedData(auth_token, true); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_continue_url = net::EscapeUrlEncodedData(continue_url, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kMergeSessionFormat, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_auth_token.c_str(), 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_continue_url.c_str(), 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_source.c_str()); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeGetAuthCodeHeader( 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf(kAuthHeaderFormat, auth_token.c_str()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper method that extracts tokens from a successful reply. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginResponse(const std::string& data, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* sid, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* lsid, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* token) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sid->clear(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lsid->clear(); 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token->clear(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != tokens.end(); ++i) { 382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (i->first == "SID") { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sid->assign(i->second); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "LSID") { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lsid->assign(i->second); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == "Auth") { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token->assign(i->second); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this was a request for uberauth token, then that's all we've got in 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sid->empty() && lsid->empty() && token->empty()) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token->assign(data); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_service = net::EscapeUrlEncodedData(service, true); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_source = net::EscapeUrlEncodedData(source, true); 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return base::StringPrintf(kOAuthLoginFormat, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_service.c_str(), 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_source.c_str()); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error_url, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_url, 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_token) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::vector; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::pair; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using std::string; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<pair<string, string> > tokens; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (vector<pair<string, string> >::iterator i = tokens.begin(); 419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i != tokens.end(); ++i) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first == kErrorParam) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error->assign(i->second); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kErrorUrlParam) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_url->assign(i->second); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaUrlParam) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_url->assign(i->second); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i->first == kCaptchaTokenParam) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token->assign(i->second); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Response( 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(auth_code); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::ResponseCookies::const_iterator iter; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = cookies.begin(); iter != cookies.end(); ++iter) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ParseClientLoginToOAuth2Cookie(*iter, auth_code)) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool GaiaAuthFetcher::ParseClientLoginToOAuth2Cookie(const std::string& cookie, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> parts; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(cookie, ';', &parts); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Per documentation, the cookie should have Secure and HttpOnly. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CookiePartsContains(parts, kClientLoginToOAuth2CookiePartSecure) || 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CookiePartsContains(parts, kClientLoginToOAuth2CookiePartHttpOnly)) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>::const_iterator iter; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = parts.begin(); iter != parts.end(); ++iter) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& part = *iter; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII( 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) part, kClientLoginToOAuth2CookiePartCodePrefix, false)) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_code->assign(part.substr( 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kClientLoginToOAuth2CookiePartCodePrefixLength)); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartClientLogin( 4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& username, 4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& password, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service, 47358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& login_token, 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& login_captcha, 4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts) { 4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This class is thread agnostic, so be sure to call this only on the 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same thread each time. 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting new ClientLogin fetch for:" << username; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must outlive fetcher_. 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_ = MakeClientLoginBody(username, 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) password, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_token, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_captcha, 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allow_hosted_accounts); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_gurl_, 495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kLoadFlagsIgnoreCookies, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher_->Start(); 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GaiaAuthFetcher::StartIssueAuthToken(const std::string& sid, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Starting IssueAuthToken for: " << service; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requested_service_ = service; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeIssueAuthTokenBody(sid, lsid, service); 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) issue_auth_token_gurl_, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetch_pending_ = true; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartLsoForOAuthLoginTokenExchange( 520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& auth_token) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token exchange with auth_token"; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url(); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) request_body_, 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeGetAuthCodeHeader(auth_token), 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetcher_->Start(); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartRevokeOAuth2Token(const std::string& auth_token) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DVLOG(1) << "Starting OAuth2 token revocation"; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeRevokeTokenBody(auth_token); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) request_body_, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_revoke_gurl_, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetcher_->Start(); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartCookieForOAuthCodeExchange( 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& session_index) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as the first step of StartCookieForOAuthLoginTokenExchange; 556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) StartCookieForOAuthLoginTokenExchange(session_index); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_code_only_ = true; 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange( 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& session_index) { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth login token fetch with cookie jar"; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetAuthCodeBody(); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = 568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GaiaUrls::GetInstance()->client_login_to_oauth2_url(); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!session_index.empty()) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_ = 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_.Resolve("?authuser=" + session_index); 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_login_to_oauth2_gurl_, 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_code_only_ = false; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartAuthCodeForOAuth2TokenExchange( 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code) { 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting OAuth token pair fetch"; 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_ = MakeGetTokenPairBody(auth_code); 591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth2_token_gurl_, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this)); 59758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) fetch_pending_ = true; 59858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) fetcher_->Start(); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void GaiaAuthFetcher::StartGetUserInfo(const std::string& lsid) { 6024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Starting GetUserInfo for lsid=" << lsid; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeGetUserInfoBody(lsid); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_user_info_gurl_, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLoadFlagsIgnoreCookies, 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 613a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetcher_->Start(); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartMergeSession(const std::string& uber_token) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Starting MergeSession with uber_token=" << uber_token; 620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The continue URL is a required parameter of the MergeSession API, but in 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // this case we don't actually need or want to navigate to it. Setting it to 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an arbitrary Google URL. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In order for the new session to be merged correctly, the server needs to 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // know what sessions already exist in the browser. The fetcher needs to be 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created such that it sends the cookies with the request, which is 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // different from all other requests the fetcher can make. 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string continue_url("http://www.google.com"); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeMergeSessionBody(uber_token, continue_url, source_); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) merge_session_gurl_, 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetch_pending_ = true; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartTokenFetchForUberAuthExchange( 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& access_token) { 643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 64446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Starting StartTokenFetchForUberAuthExchange with access_token=" 646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << access_token; 64746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string authentication_header = 648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::StringPrintf(kOAuthHeaderFormat, access_token.c_str()); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authentication_header, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uberauth_token_gurl_, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::StartOAuthLogin(const std::string& access_token, 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_ = MakeOAuthLoginBody(service, source_); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string authentication_header = 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf(kOAuth2BearerHeaderFormat, access_token.c_str()); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_, 66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) authentication_header, 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_login_gurl_, 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) this)); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_pending_ = true; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 67546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void GaiaAuthFetcher::StartListAccounts() { 67758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher_.reset(CreateGaiaFetcher(getter_, 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " ", // To force an HTTP POST. 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Origin: https://www.google.com", 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_accounts_gurl_, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::LOAD_NORMAL, 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetch_pending_ = true; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status) { 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.is_success()) { 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() == net::URLRequestStatus::CANCELED) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 69758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << status.error(); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromConnectionError(status.error()); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsSecondFactorSuccess(data)) { 703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string url; 7084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string captcha_url; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string captcha_token; 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "ClientLogin failed with " << error; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kCaptchaError) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL image_url( 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->captcha_base_url().Resolve(captcha_url)); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL unlock_url(url); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token, image_url, unlock_url); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDeletedError) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDisabledError) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error == kBadAuthenticationError) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kServiceUnavailableError) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DLOG(WARNING) << "Incomprehensible response from Google Accounts servers."; 734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return GoogleServiceAuthError( 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 7434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)GoogleServiceAuthError GaiaAuthFetcher::GenerateOAuthLoginError( 7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& data, 7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const net::URLRequestStatus& status) { 7463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!status.is_success()) { 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (status.status() == net::URLRequestStatus::CANCELED) { 7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << status.error(); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromConnectionError(status.error()); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsSecondFactorSuccess(data)) { 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string error; 7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string url; 7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string captcha_url; 7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string captcha_token; 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "OAuthLogin failed with " << error; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kCaptchaErrorCode) { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL image_url( 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaUrls::GetInstance()->captcha_base_url().Resolve(captcha_url)); 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL unlock_url(url); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) captcha_token, image_url, unlock_url); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDeletedErrorCode) 774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kAccountDisabledErrorCode) 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == kBadAuthenticationErrorCode) { 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GoogleServiceAuthError( 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error == kServiceUnavailableErrorCode) { 7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GoogleServiceAuthError( 7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DLOG(WARNING) << "Incomprehensible response from Google Accounts servers."; 7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GoogleServiceAuthError( 7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); 7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnClientLoginFetched(const std::string& data, 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int response_code) { 7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(1) << "ClientLogin successful!"; 8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string sid; 8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string lsid; 8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string token; 8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ParseClientLoginResponse(data, &sid, &lsid, &token); 8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) consumer_->OnClientLoginSuccess( 8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaAuthFetcher::OnIssueAuthTokenFetched( 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::URLRequestStatus& status, 8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int response_code) { 8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (status.is_success() && response_code == net::HTTP_OK) { 8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Only the bare token is returned in the body of this Gaia call 8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // without any padding. 8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) consumer_->OnIssueAuthTokenSuccess(requested_service_, data); 8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) consumer_->OnIssueAuthTokenFailure(requested_service_, 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateAuthError(data, status)); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 82458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 825void GaiaAuthFetcher::OnClientLoginToOAuth2Fetched( 826 const std::string& data, 827 const net::ResponseCookies& cookies, 828 const net::URLRequestStatus& status, 829 int response_code) { 830 if (status.is_success() && response_code == net::HTTP_OK) { 831 std::string auth_code; 832 ParseClientLoginToOAuth2Response(cookies, &auth_code); 833 if (fetch_code_only_) 834 consumer_->OnClientOAuthCodeSuccess(auth_code); 835 else 836 StartAuthCodeForOAuth2TokenExchange(auth_code); 837 } else { 838 GoogleServiceAuthError auth_error(GenerateAuthError(data, status)); 839 if (fetch_code_only_) 840 consumer_->OnClientOAuthCodeFailure(auth_error); 841 else 842 consumer_->OnClientOAuthFailure(auth_error); 843 } 844} 845 846void GaiaAuthFetcher::OnOAuth2TokenPairFetched( 847 const std::string& data, 848 const net::URLRequestStatus& status, 849 int response_code) { 850 std::string refresh_token; 851 std::string access_token; 852 int expires_in_secs = 0; 853 854 bool success = false; 855 if (status.is_success() && response_code == net::HTTP_OK) { 856 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 857 if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) { 858 base::DictionaryValue* dict = 859 static_cast<base::DictionaryValue*>(value.get()); 860 success = ExtractOAuth2TokenPairResponse(dict, &refresh_token, 861 &access_token, &expires_in_secs); 862 } 863 } 864 865 if (success) { 866 consumer_->OnClientOAuthSuccess( 867 GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token, 868 expires_in_secs)); 869 } else { 870 consumer_->OnClientOAuthFailure(GenerateAuthError(data, status)); 871 } 872} 873 874void GaiaAuthFetcher::OnOAuth2RevokeTokenFetched( 875 const std::string& data, 876 const net::URLRequestStatus& status, 877 int response_code) { 878 consumer_->OnOAuth2RevokeTokenCompleted(); 879} 880 881void GaiaAuthFetcher::OnListAccountsFetched(const std::string& data, 882 const net::URLRequestStatus& status, 883 int response_code) { 884 if (status.is_success() && response_code == net::HTTP_OK) { 885 consumer_->OnListAccountsSuccess(data); 886 } else { 887 consumer_->OnListAccountsFailure(GenerateAuthError(data, status)); 888 } 889} 890 891void GaiaAuthFetcher::OnGetUserInfoFetched( 892 const std::string& data, 893 const net::URLRequestStatus& status, 894 int response_code) { 895 if (status.is_success() && response_code == net::HTTP_OK) { 896 std::vector<std::pair<std::string, std::string> > tokens; 897 UserInfoMap matches; 898 base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 899 std::vector<std::pair<std::string, std::string> >::iterator i; 900 for (i = tokens.begin(); i != tokens.end(); ++i) { 901 matches[i->first] = i->second; 902 } 903 consumer_->OnGetUserInfoSuccess(matches); 904 } else { 905 consumer_->OnGetUserInfoFailure(GenerateAuthError(data, status)); 906 } 907} 908 909void GaiaAuthFetcher::OnMergeSessionFetched(const std::string& data, 910 const net::URLRequestStatus& status, 911 int response_code) { 912 if (status.is_success() && response_code == net::HTTP_OK) { 913 consumer_->OnMergeSessionSuccess(data); 914 } else { 915 consumer_->OnMergeSessionFailure(GenerateAuthError(data, status)); 916 } 917} 918 919void GaiaAuthFetcher::OnUberAuthTokenFetch(const std::string& data, 920 const net::URLRequestStatus& status, 921 int response_code) { 922 if (status.is_success() && response_code == net::HTTP_OK) { 923 consumer_->OnUberAuthTokenSuccess(data); 924 } else { 925 consumer_->OnUberAuthTokenFailure(GenerateAuthError(data, status)); 926 } 927} 928 929void GaiaAuthFetcher::OnOAuthLoginFetched(const std::string& data, 930 const net::URLRequestStatus& status, 931 int response_code) { 932 if (status.is_success() && response_code == net::HTTP_OK) { 933 DVLOG(1) << "ClientLogin successful!"; 934 std::string sid; 935 std::string lsid; 936 std::string token; 937 ParseClientLoginResponse(data, &sid, &lsid, &token); 938 consumer_->OnClientLoginSuccess( 939 GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data)); 940 } else { 941 consumer_->OnClientLoginFailure(GenerateAuthError(data, status)); 942 } 943} 944 945void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 946 fetch_pending_ = false; 947 // Some of the GAIA requests perform redirects, which results in the final 948 // URL of the fetcher not being the original URL requested. Therefore use 949 // the original URL when determining which OnXXX function to call. 950 const GURL& url = source->GetOriginalURL(); 951 const net::URLRequestStatus& status = source->GetStatus(); 952 int response_code = source->GetResponseCode(); 953 std::string data; 954 source->GetResponseAsString(&data); 955#ifndef NDEBUG 956 std::string headers; 957 if (source->GetResponseHeaders()) 958 source->GetResponseHeaders()->GetNormalizedHeaders(&headers); 959 DVLOG(2) << "Response " << url.spec() << ", code = " << response_code << "\n" 960 << headers << "\n"; 961 DVLOG(2) << "data: " << data << "\n"; 962#endif 963 // Retrieve the response headers from the request. Must only be called after 964 // the OnURLFetchComplete callback has run. 965 if (url == client_login_gurl_) { 966 OnClientLoginFetched(data, status, response_code); 967 } else if (url == issue_auth_token_gurl_) { 968 OnIssueAuthTokenFetched(data, status, response_code); 969 } else if (url == client_login_to_oauth2_gurl_) { 970 OnClientLoginToOAuth2Fetched( 971 data, source->GetCookies(), status, response_code); 972 } else if (url == oauth2_token_gurl_) { 973 OnOAuth2TokenPairFetched(data, status, response_code); 974 } else if (url == get_user_info_gurl_) { 975 OnGetUserInfoFetched(data, status, response_code); 976 } else if (url == merge_session_gurl_) { 977 OnMergeSessionFetched(data, status, response_code); 978 } else if (url == uberauth_token_gurl_) { 979 OnUberAuthTokenFetch(data, status, response_code); 980 } else if (url == oauth_login_gurl_) { 981 OnOAuthLoginFetched(data, status, response_code); 982 } else if (url == oauth2_revoke_gurl_) { 983 OnOAuth2RevokeTokenFetched(data, status, response_code); 984 } else if (url == list_accounts_gurl_) { 985 OnListAccountsFetched(data, status, response_code); 986 } else { 987 NOTREACHED(); 988 } 989} 990 991// static 992bool GaiaAuthFetcher::IsSecondFactorSuccess( 993 const std::string& alleged_error) { 994 return alleged_error.find(kSecondFactor) != 995 std::string::npos; 996} 997