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