1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_COMMON_NET_GAIA_GAIA_AUTH_FETCHER_H_ 6 #define CHROME_COMMON_NET_GAIA_GAIA_AUTH_FETCHER_H_ 7 #pragma once 8 9 #include <string> 10 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "chrome/common/net/gaia/gaia_auth_consumer.h" 14 #include "chrome/common/net/url_fetcher.h" 15 #include "googleurl/src/gurl.h" 16 17 // Authenticate a user against the Google Accounts ClientLogin API 18 // with various capabilities and return results to a GaiaAuthConsumer. 19 // 20 // In the future, we will also issue auth tokens from this class. 21 // This class should be used on a single thread, but it can be whichever thread 22 // that you like. 23 // 24 // This class can handle one request at a time. To parallelize requests, 25 // create multiple GaiaAuthFetcher's. 26 27 class GaiaAuthFetcherTest; 28 29 class GaiaAuthFetcher : public URLFetcher::Delegate { 30 public: 31 enum HostedAccountsSetting { 32 HostedAccountsAllowed, 33 HostedAccountsNotAllowed 34 }; 35 36 // The URLs for different calls in the Google Accounts programmatic login API. 37 static const char kClientLoginUrl[]; 38 static const char kIssueAuthTokenUrl[]; 39 static const char kGetUserInfoUrl[]; 40 41 // Magic string indicating that, while a second factor is still 42 // needed to complete authentication, the user provided the right password. 43 static const char kSecondFactor[]; 44 45 // This will later be hidden behind an auth service which caches 46 // tokens. 47 GaiaAuthFetcher(GaiaAuthConsumer* consumer, 48 const std::string& source, 49 net::URLRequestContextGetter* getter); 50 virtual ~GaiaAuthFetcher(); 51 52 // GaiaAuthConsumer will be called on the original thread 53 // after results come back. This class is thread agnostic. 54 // You can't make more than request at a time. 55 void StartClientLogin(const std::string& username, 56 const std::string& password, 57 const char* const service, 58 const std::string& login_token, 59 const std::string& login_captcha, 60 HostedAccountsSetting allow_hosted_accounts); 61 62 // GaiaAuthConsumer will be called on the original thread 63 // after results come back. This class is thread agnostic. 64 // You can't make more than one request at a time. 65 void StartIssueAuthToken(const std::string& sid, 66 const std::string& lsid, 67 const char* const service); 68 69 // Start a request to get a particular key from user info. 70 // GaiaAuthConsumer will be called back on the same thread when 71 // results come back. 72 // You can't make more than one request at a time. 73 void StartGetUserInfo(const std::string& lsid, 74 const std::string& info_key); 75 76 // Implementation of URLFetcher::Delegate 77 virtual void OnURLFetchComplete(const URLFetcher* source, 78 const GURL& url, 79 const net::URLRequestStatus& status, 80 int response_code, 81 const ResponseCookies& cookies, 82 const std::string& data); 83 84 // StartClientLogin been called && results not back yet? 85 bool HasPendingFetch(); 86 87 // Stop any URL fetches in progress. 88 void CancelRequest(); 89 90 private: 91 // ClientLogin body constants that don't change 92 static const char kCookiePersistence[]; 93 static const char kAccountTypeHostedOrGoogle[]; 94 static const char kAccountTypeGoogle[]; 95 96 // The format of the POST body for ClientLogin. 97 static const char kClientLoginFormat[]; 98 // The format of said POST body when CAPTCHA token & answer are specified. 99 static const char kClientLoginCaptchaFormat[]; 100 // The format of the POST body for IssueAuthToken. 101 static const char kIssueAuthTokenFormat[]; 102 // The format of the POSt body for GetUserInfo. 103 static const char kGetUserInfoFormat[]; 104 105 // Constants for parsing ClientLogin errors. 106 static const char kAccountDeletedError[]; 107 static const char kAccountDisabledError[]; 108 static const char kBadAuthenticationError[]; 109 static const char kCaptchaError[]; 110 static const char kServiceUnavailableError[]; 111 static const char kErrorParam[]; 112 static const char kErrorUrlParam[]; 113 static const char kCaptchaUrlParam[]; 114 static const char kCaptchaTokenParam[]; 115 static const char kCaptchaUrlPrefix[]; 116 117 // Process the results of a ClientLogin fetch. 118 void OnClientLoginFetched(const std::string& data, 119 const net::URLRequestStatus& status, 120 int response_code); 121 122 void OnIssueAuthTokenFetched(const std::string& data, 123 const net::URLRequestStatus& status, 124 int response_code); 125 126 void OnGetUserInfoFetched(const std::string& data, 127 const net::URLRequestStatus& status, 128 int response_code); 129 130 // Tokenize the results of a ClientLogin fetch. 131 static void ParseClientLoginResponse(const std::string& data, 132 std::string* sid, 133 std::string* lsid, 134 std::string* token); 135 136 static void ParseClientLoginFailure(const std::string& data, 137 std::string* error, 138 std::string* error_url, 139 std::string* captcha_url, 140 std::string* captcha_token); 141 142 // From a URLFetcher result, generate an appropriate error. 143 // From the API documentation, both IssueAuthToken and ClientLogin have 144 // the same error returns. 145 static GoogleServiceAuthError GenerateAuthError( 146 const std::string& data, 147 const net::URLRequestStatus& status); 148 149 // Is this a special case Gaia error for TwoFactor auth? 150 static bool IsSecondFactorSuccess(const std::string& alleged_error); 151 152 // Given parameters, create a ClientLogin request body. 153 static std::string MakeClientLoginBody( 154 const std::string& username, 155 const std::string& password, 156 const std::string& source, 157 const char* const service, 158 const std::string& login_token, 159 const std::string& login_captcha, 160 HostedAccountsSetting allow_hosted_accounts); 161 // Supply the sid / lsid returned from ClientLogin in order to 162 // request a long lived auth token for a service. 163 static std::string MakeIssueAuthTokenBody(const std::string& sid, 164 const std::string& lsid, 165 const char* const service); 166 // Supply the lsid returned from ClientLogin in order to fetch 167 // user information. 168 static std::string MakeGetUserInfoBody(const std::string& lsid); 169 170 // Create a fetcher useable for making any Gaia request. 171 static URLFetcher* CreateGaiaFetcher(net::URLRequestContextGetter* getter, 172 const std::string& body, 173 const GURL& gaia_gurl_, 174 URLFetcher::Delegate* delegate); 175 176 177 // These fields are common to GaiaAuthFetcher, same every request 178 GaiaAuthConsumer* const consumer_; 179 net::URLRequestContextGetter* const getter_; 180 std::string source_; 181 const GURL client_login_gurl_; 182 const GURL issue_auth_token_gurl_; 183 const GURL get_user_info_gurl_; 184 185 // While a fetch is going on: 186 scoped_ptr<URLFetcher> fetcher_; 187 std::string request_body_; 188 std::string requested_service_; // Currently tracked for IssueAuthToken only 189 std::string requested_info_key_; // Currently tracked for GetUserInfo only 190 bool fetch_pending_; 191 192 friend class GaiaAuthFetcherTest; 193 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CaptchaParse); 194 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDeletedError); 195 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDisabledError); 196 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationError); 197 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, IncomprehensibleError); 198 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ServiceUnavailableError); 199 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckNormalErrorCode); 200 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckTwoFactorResponse); 201 FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, LoginNetFailure); 202 203 DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcher); 204 }; 205 206 #endif // CHROME_COMMON_NET_GAIA_GAIA_AUTH_FETCHER_H_ 207