Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / gaia_auth_fetcher.h
1 // Copyright (c) 2012 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 GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_
6 #define GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_
7
8 #include <string>
9 #include <vector>
10
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "google_apis/gaia/gaia_auth_consumer.h"
14 #include "google_apis/gaia/google_service_auth_error.h"
15 #include "net/url_request/url_fetcher_delegate.h"
16 #include "url/gurl.h"
17
18 // Authenticate a user against the Google Accounts ClientLogin API
19 // with various capabilities and return results to a GaiaAuthConsumer.
20 //
21 // In the future, we will also issue auth tokens from this class.
22 // This class should be used on a single thread, but it can be whichever thread
23 // that you like.
24 //
25 // This class can handle one request at a time on any thread. To parallelize
26 // requests, create multiple GaiaAuthFetcher's.
27
28 class GaiaAuthFetcherTest;
29
30 namespace net {
31 class URLFetcher;
32 class URLRequestContextGetter;
33 class URLRequestStatus;
34 }
35
36 class GaiaAuthFetcher : public net::URLFetcherDelegate {
37  public:
38   enum HostedAccountsSetting {
39     HostedAccountsAllowed,
40     HostedAccountsNotAllowed
41   };
42
43   // Magic string indicating that, while a second factor is still
44   // needed to complete authentication, the user provided the right password.
45   static const char kSecondFactor[];
46
47   // This will later be hidden behind an auth service which caches
48   // tokens.
49   GaiaAuthFetcher(GaiaAuthConsumer* consumer,
50                   const std::string& source,
51                   net::URLRequestContextGetter* getter);
52   virtual ~GaiaAuthFetcher();
53
54   // Start a request to obtain the SID and LSID cookies for the the account
55   // identified by |username| and |password|.  If |service| is not null or
56   // empty, then also obtains a service token for specified service.
57   //
58   // If this is a second call because of captcha challenge, then the
59   // |login_token| and |login_captcha| arugment should correspond to the
60   // solution of the challenge.
61   //
62   // Either OnClientLoginSuccess or OnClientLoginFailure will be
63   // called on the consumer on the original thread.
64   void StartClientLogin(const std::string& username,
65                         const std::string& password,
66                         const char* const service,
67                         const std::string& login_token,
68                         const std::string& login_captcha,
69                         HostedAccountsSetting allow_hosted_accounts);
70
71   // Start a request to obtain service token for the the account identified by
72   // |sid| and |lsid| and the |service|.
73   //
74   // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be
75   // called on the consumer on the original thread.
76   void StartIssueAuthToken(const std::string& sid,
77                            const std::string& lsid,
78                            const char* const service);
79
80   // Start a request to obtain |service| token for the the account identified by
81   // |uber_token|.
82   //
83   // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be
84   // called on the consumer on the original thread.
85   void StartTokenAuth(const std::string& uber_token,
86                       const char* const service);
87
88   // Start a request to obtain service token for the the account identified by
89   // |oauth2_access_token| and the |service|.
90   //
91   // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be
92   // called on the consumer on the original thread.
93   void StartIssueAuthTokenForOAuth2(const std::string& oauth2_access_token,
94                                     const char* const service);
95
96   // Start a request to exchange an "lso" service token given by |auth_token|
97   // for an OAuthLogin-scoped oauth2 token.
98   //
99   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
100   // called on the consumer on the original thread.
101   void StartLsoForOAuthLoginTokenExchange(const std::string& auth_token);
102
103   // Start a request to revoke |auth_token|.
104   //
105   // OnOAuth2RevokeTokenCompleted will be called on the consumer on the original
106   // thread.
107   void StartRevokeOAuth2Token(const std::string& auth_token);
108
109   // Start a request to exchange the cookies of a signed-in user session
110   // for an OAuthLogin-scoped oauth2 token.  In the case of a session with
111   // multiple accounts signed in, |session_index| indicate the which of accounts
112   // within the session.
113   //
114   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
115   // called on the consumer on the original thread.
116   void StartCookieForOAuthLoginTokenExchange(const std::string& session_index);
117
118   // Start a request to exchange the cookies of a signed-in user session
119   // for an OAuthLogin-scoped oauth2 token. In the case of a session with
120   // multiple accounts signed in, |session_index| indicate the which of accounts
121   // within the session.
122   // Resulting refresh token is annotated on the server with |device_id|. Format
123   // of device_id on the server is at most 64 unicode characters.
124   //
125   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
126   // called on the consumer on the original thread.
127   void StartCookieForOAuthLoginTokenExchangeWithDeviceId(
128       const std::string& session_index,
129       const std::string& device_id);
130
131   // Start a request to exchange the authorization code for an OAuthLogin-scoped
132   // oauth2 token.
133   //
134   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
135   // called on the consumer on the original thread.
136   void StartAuthCodeForOAuth2TokenExchange(const std::string& auth_code);
137
138   // Start a request to get user info for the account identified by |lsid|.
139   //
140   // Either OnGetUserInfoSuccess or OnGetUserInfoFailure will be
141   // called on the consumer on the original thread.
142   void StartGetUserInfo(const std::string& lsid);
143
144   // Start a MergeSession request to pre-login the user with the given
145   // credentials.
146   //
147   // Start a MergeSession request to fill the browsing cookie jar with
148   // credentials represented by the account whose uber-auth token is
149   // |uber_token|.  This method will modify the cookies of the current profile.
150   //
151   // The |external_cc_result| string can specify the result of connetion checks
152   // for various google properties, and MergeSession will set cookies on those
153   // properties too if appropriate.  See StartGetCheckConnectionInfo() for
154   // details.  The string is a comma separated list of token/result pairs, where
155   // token and result are separated by a colon.  This string may be empty, in
156   // which case no specific handling is performed.
157   //
158   // Either OnMergeSessionSuccess or OnMergeSessionFailure will be
159   // called on the consumer on the original thread.
160   void StartMergeSession(const std::string& uber_token,
161                          const std::string& external_cc_result);
162
163   // Start a request to exchange an OAuthLogin-scoped oauth2 access token for an
164   // uber-auth token.  The returned token can be used with the method
165   // StartMergeSession().
166   //
167   // Either OnUberAuthTokenSuccess or OnUberAuthTokenFailure will be
168   // called on the consumer on the original thread.
169   void StartTokenFetchForUberAuthExchange(const std::string& access_token);
170
171   // Start a request to exchange an OAuthLogin-scoped oauth2 access token for a
172   // ClientLogin-style service tokens.  The response to this request is the
173   // same as the response to a ClientLogin request, except that captcha
174   // challenges are never issued.
175   //
176   // Either OnClientLoginSuccess or OnClientLoginFailure will be
177   // called on the consumer on the original thread. If |service| is empty,
178   // the call will attempt to fetch uber auth token.
179   void StartOAuthLogin(const std::string& access_token,
180                        const std::string& service);
181
182   // Starts a request to list the accounts in the GAIA cookie.
183   void StartListAccounts();
184
185   // Starts a request to get the list of URLs to check for connection info.
186   // Returns token/URL pairs to check, and the resulting status can be given to
187   // /MergeSession requests.
188   void StartGetCheckConnectionInfo();
189
190   // Implementation of net::URLFetcherDelegate
191   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
192
193   // StartClientLogin been called && results not back yet?
194   bool HasPendingFetch();
195
196   // Stop any URL fetches in progress.
197   void CancelRequest();
198
199   // From a URLFetcher result, generate an appropriate error.
200   // From the API documentation, both IssueAuthToken and ClientLogin have
201   // the same error returns.
202   static GoogleServiceAuthError GenerateOAuthLoginError(
203       const std::string& data,
204       const net::URLRequestStatus& status);
205
206  private:
207   // ClientLogin body constants that don't change
208   static const char kCookiePersistence[];
209   static const char kAccountTypeHostedOrGoogle[];
210   static const char kAccountTypeGoogle[];
211
212   // The format of the POST body for ClientLogin.
213   static const char kClientLoginFormat[];
214   // The format of said POST body when CAPTCHA token & answer are specified.
215   static const char kClientLoginCaptchaFormat[];
216   // The format of the POST body for IssueAuthToken.
217   static const char kIssueAuthTokenFormat[];
218   // The format of the POST body to get OAuth2 auth code from auth token.
219   static const char kClientLoginToOAuth2BodyFormat[];
220   // The format of the POST body to get OAuth2 auth code from auth token. This
221   // format is used for request annotated with device_id.
222   static const char kClientLoginToOAuth2WithDeviceTypeBodyFormat[];
223   // The format of the POST body to get OAuth2 token pair from auth code.
224   static const char kOAuth2CodeToTokenPairBodyFormat[];
225   // The format of the POST body to revoke an OAuth2 token.
226   static const char kOAuth2RevokeTokenBodyFormat[];
227   // The format of the POST body for GetUserInfo.
228   static const char kGetUserInfoFormat[];
229   // The format of the POST body for MergeSession.
230   static const char kMergeSessionFormat[];
231   // The format of the URL for UberAuthToken.
232   static const char kUberAuthTokenURLFormat[];
233   // The format of the body for OAuthLogin.
234   static const char kOAuthLoginFormat[];
235
236   // Constants for parsing ClientLogin errors.
237   static const char kAccountDeletedError[];
238   static const char kAccountDeletedErrorCode[];
239   static const char kAccountDisabledError[];
240   static const char kAccountDisabledErrorCode[];
241   static const char kBadAuthenticationError[];
242   static const char kBadAuthenticationErrorCode[];
243   static const char kCaptchaError[];
244   static const char kCaptchaErrorCode[];
245   static const char kServiceUnavailableError[];
246   static const char kServiceUnavailableErrorCode[];
247   static const char kErrorParam[];
248   static const char kErrorUrlParam[];
249   static const char kCaptchaUrlParam[];
250   static const char kCaptchaTokenParam[];
251
252   // Constants for parsing ClientOAuth errors.
253   static const char kNeedsAdditional[];
254   static const char kCaptcha[];
255   static const char kTwoFactor[];
256
257   // Constants for request/response for OAuth2 requests.
258   static const char kAuthHeaderFormat[];
259   static const char kOAuthHeaderFormat[];
260   static const char kOAuth2BearerHeaderFormat[];
261   static const char kDeviceIdHeaderFormat[];
262   static const char kClientLoginToOAuth2CookiePartSecure[];
263   static const char kClientLoginToOAuth2CookiePartHttpOnly[];
264   static const char kClientLoginToOAuth2CookiePartCodePrefix[];
265   static const int kClientLoginToOAuth2CookiePartCodePrefixLength;
266
267   // Process the results of a ClientLogin fetch.
268   void OnClientLoginFetched(const std::string& data,
269                             const net::URLRequestStatus& status,
270                             int response_code);
271
272   void OnIssueAuthTokenFetched(const std::string& data,
273                                const net::URLRequestStatus& status,
274                                int response_code);
275
276   void OnClientLoginToOAuth2Fetched(const std::string& data,
277                                     const net::ResponseCookies& cookies,
278                                     const net::URLRequestStatus& status,
279                                     int response_code);
280
281   void OnOAuth2TokenPairFetched(const std::string& data,
282                                 const net::URLRequestStatus& status,
283                                 int response_code);
284
285   void OnOAuth2RevokeTokenFetched(const std::string& data,
286                                   const net::URLRequestStatus& status,
287                                   int response_code);
288
289   void OnListAccountsFetched(const std::string& data,
290                              const net::URLRequestStatus& status,
291                              int response_code);
292
293   void OnGetUserInfoFetched(const std::string& data,
294                             const net::URLRequestStatus& status,
295                             int response_code);
296
297   void OnMergeSessionFetched(const std::string& data,
298                              const net::URLRequestStatus& status,
299                              int response_code);
300
301   void OnUberAuthTokenFetch(const std::string& data,
302                             const net::URLRequestStatus& status,
303                             int response_code);
304
305   void OnOAuthLoginFetched(const std::string& data,
306                            const net::URLRequestStatus& status,
307                            int response_code);
308
309   void OnGetCheckConnectionInfoFetched(const std::string& data,
310                                        const net::URLRequestStatus& status,
311                                        int response_code);
312
313   // Tokenize the results of a ClientLogin fetch.
314   static void ParseClientLoginResponse(const std::string& data,
315                                        std::string* sid,
316                                        std::string* lsid,
317                                        std::string* token);
318
319   static void ParseClientLoginFailure(const std::string& data,
320                                       std::string* error,
321                                       std::string* error_url,
322                                       std::string* captcha_url,
323                                       std::string* captcha_token);
324
325   // Parse ClientLogin to OAuth2 response.
326   static bool ParseClientLoginToOAuth2Response(
327       const net::ResponseCookies& cookies,
328       std::string* auth_code);
329
330   static bool ParseClientLoginToOAuth2Cookie(const std::string& cookie,
331                                              std::string* auth_code);
332
333   // Is this a special case Gaia error for TwoFactor auth?
334   static bool IsSecondFactorSuccess(const std::string& alleged_error);
335
336   // Given parameters, create a ClientLogin request body.
337   static std::string MakeClientLoginBody(
338       const std::string& username,
339       const std::string& password,
340       const std::string& source,
341       const char* const service,
342       const std::string& login_token,
343       const std::string& login_captcha,
344       HostedAccountsSetting allow_hosted_accounts);
345   // Supply the sid / lsid returned from ClientLogin in order to
346   // request a long lived auth token for a service.
347   static std::string MakeIssueAuthTokenBody(const std::string& sid,
348                                             const std::string& lsid,
349                                             const char* const service);
350   // Create body to get OAuth2 auth code.
351   static std::string MakeGetAuthCodeBody(bool include_device_type);
352   // Given auth code, create body to get OAuth2 token pair.
353   static std::string MakeGetTokenPairBody(const std::string& auth_code);
354   // Given an OAuth2 token, create body to revoke the token.
355   std::string MakeRevokeTokenBody(const std::string& auth_token);
356   // Supply the lsid returned from ClientLogin in order to fetch
357   // user information.
358   static std::string MakeGetUserInfoBody(const std::string& lsid);
359
360   // Supply the authentication token returned from StartIssueAuthToken.
361   static std::string MakeMergeSessionBody(const std::string& auth_token,
362                                           const std::string& external_cc_result,
363                                           const std::string& continue_url,
364                                           const std::string& source);
365
366   static std::string MakeGetAuthCodeHeader(const std::string& auth_token);
367
368   static std::string MakeOAuthLoginBody(const std::string& service,
369                                         const std::string& source);
370
371   // Create a fetcher usable for making any Gaia request.  |body| is used
372   // as the body of the POST request sent to GAIA.  Any strings listed in
373   // |headers| are added as extra HTTP headers in the request.
374   //
375   // |load_flags| are passed to directly to net::URLFetcher::Create() when
376   // creating the URL fetcher.
377   static net::URLFetcher* CreateGaiaFetcher(
378       net::URLRequestContextGetter* getter,
379       const std::string& body,
380       const std::string& headers,
381       const GURL& gaia_gurl,
382       int load_flags,
383       net::URLFetcherDelegate* delegate);
384
385   // From a URLFetcher result, generate an appropriate error.
386   // From the API documentation, both IssueAuthToken and ClientLogin have
387   // the same error returns.
388   static GoogleServiceAuthError GenerateAuthError(
389       const std::string& data,
390       const net::URLRequestStatus& status);
391
392   // These fields are common to GaiaAuthFetcher, same every request
393   GaiaAuthConsumer* const consumer_;
394   net::URLRequestContextGetter* const getter_;
395   std::string source_;
396   const GURL client_login_gurl_;
397   const GURL issue_auth_token_gurl_;
398   const GURL oauth2_token_gurl_;
399   const GURL oauth2_revoke_gurl_;
400   const GURL get_user_info_gurl_;
401   const GURL merge_session_gurl_;
402   const GURL uberauth_token_gurl_;
403   const GURL oauth_login_gurl_;
404   const GURL list_accounts_gurl_;
405   const GURL get_check_connection_info_url_;
406
407   // While a fetch is going on:
408   scoped_ptr<net::URLFetcher> fetcher_;
409   GURL client_login_to_oauth2_gurl_;
410   std::string request_body_;
411   std::string requested_service_; // Currently tracked for IssueAuthToken only.
412   bool fetch_pending_;
413
414   friend class GaiaAuthFetcherTest;
415   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CaptchaParse);
416   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDeletedError);
417   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDisabledError);
418   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationError);
419   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, IncomprehensibleError);
420   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ServiceUnavailableError);
421   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckNormalErrorCode);
422   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckTwoFactorResponse);
423   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, LoginNetFailure);
424   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest,
425       ParseClientLoginToOAuth2Response);
426   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ParseOAuth2TokenPairResponse);
427   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthSuccess);
428   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthWithQuote);
429   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeSuccess);
430   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeQuote);
431
432   DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcher);
433 };
434
435 #endif  // GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_