Upstream version 8.37.180.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   // Either OnMergeSessionSuccess or OnMergeSessionFailure will be
152   // called on the consumer on the original thread.
153   void StartMergeSession(const std::string& uber_token);
154
155   // Start a request to exchange an OAuthLogin-scoped oauth2 access token for an
156   // uber-auth token.  The returned token can be used with the method
157   // StartMergeSession().
158   //
159   // Either OnUberAuthTokenSuccess or OnUberAuthTokenFailure will be
160   // called on the consumer on the original thread.
161   void StartTokenFetchForUberAuthExchange(const std::string& access_token);
162
163   // Start a request to exchange an OAuthLogin-scoped oauth2 access token for a
164   // ClientLogin-style service tokens.  The response to this request is the
165   // same as the response to a ClientLogin request, except that captcha
166   // challenges are never issued.
167   //
168   // Either OnClientLoginSuccess or OnClientLoginFailure will be
169   // called on the consumer on the original thread. If |service| is empty,
170   // the call will attempt to fetch uber auth token.
171   void StartOAuthLogin(const std::string& access_token,
172                        const std::string& service);
173
174   // Starts a request to list the accounts in the GAIA cookie.
175   void StartListAccounts();
176
177   // Implementation of net::URLFetcherDelegate
178   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
179
180   // StartClientLogin been called && results not back yet?
181   bool HasPendingFetch();
182
183   // Stop any URL fetches in progress.
184   void CancelRequest();
185
186   // From a URLFetcher result, generate an appropriate error.
187   // From the API documentation, both IssueAuthToken and ClientLogin have
188   // the same error returns.
189   static GoogleServiceAuthError GenerateOAuthLoginError(
190       const std::string& data,
191       const net::URLRequestStatus& status);
192
193  private:
194   // ClientLogin body constants that don't change
195   static const char kCookiePersistence[];
196   static const char kAccountTypeHostedOrGoogle[];
197   static const char kAccountTypeGoogle[];
198
199   // The format of the POST body for ClientLogin.
200   static const char kClientLoginFormat[];
201   // The format of said POST body when CAPTCHA token & answer are specified.
202   static const char kClientLoginCaptchaFormat[];
203   // The format of the POST body for IssueAuthToken.
204   static const char kIssueAuthTokenFormat[];
205   // The format of the POST body to get OAuth2 auth code from auth token.
206   static const char kClientLoginToOAuth2BodyFormat[];
207   // The format of the POST body to get OAuth2 auth code from auth token. This
208   // format is used for request annotated with device_id.
209   static const char kClientLoginToOAuth2WithDeviceTypeBodyFormat[];
210   // The format of the POST body to get OAuth2 token pair from auth code.
211   static const char kOAuth2CodeToTokenPairBodyFormat[];
212   // The format of the POST body to revoke an OAuth2 token.
213   static const char kOAuth2RevokeTokenBodyFormat[];
214   // The format of the POST body for GetUserInfo.
215   static const char kGetUserInfoFormat[];
216   // The format of the POST body for MergeSession.
217   static const char kMergeSessionFormat[];
218   // The format of the URL for UberAuthToken.
219   static const char kUberAuthTokenURLFormat[];
220   // The format of the body for OAuthLogin.
221   static const char kOAuthLoginFormat[];
222
223   // Constants for parsing ClientLogin errors.
224   static const char kAccountDeletedError[];
225   static const char kAccountDeletedErrorCode[];
226   static const char kAccountDisabledError[];
227   static const char kAccountDisabledErrorCode[];
228   static const char kBadAuthenticationError[];
229   static const char kBadAuthenticationErrorCode[];
230   static const char kCaptchaError[];
231   static const char kCaptchaErrorCode[];
232   static const char kServiceUnavailableError[];
233   static const char kServiceUnavailableErrorCode[];
234   static const char kErrorParam[];
235   static const char kErrorUrlParam[];
236   static const char kCaptchaUrlParam[];
237   static const char kCaptchaTokenParam[];
238
239   // Constants for parsing ClientOAuth errors.
240   static const char kNeedsAdditional[];
241   static const char kCaptcha[];
242   static const char kTwoFactor[];
243
244   // Constants for request/response for OAuth2 requests.
245   static const char kAuthHeaderFormat[];
246   static const char kOAuthHeaderFormat[];
247   static const char kOAuth2BearerHeaderFormat[];
248   static const char kDeviceIdHeaderFormat[];
249   static const char kClientLoginToOAuth2CookiePartSecure[];
250   static const char kClientLoginToOAuth2CookiePartHttpOnly[];
251   static const char kClientLoginToOAuth2CookiePartCodePrefix[];
252   static const int kClientLoginToOAuth2CookiePartCodePrefixLength;
253
254   // Process the results of a ClientLogin fetch.
255   void OnClientLoginFetched(const std::string& data,
256                             const net::URLRequestStatus& status,
257                             int response_code);
258
259   void OnIssueAuthTokenFetched(const std::string& data,
260                                const net::URLRequestStatus& status,
261                                int response_code);
262
263   void OnClientLoginToOAuth2Fetched(const std::string& data,
264                                     const net::ResponseCookies& cookies,
265                                     const net::URLRequestStatus& status,
266                                     int response_code);
267
268   void OnOAuth2TokenPairFetched(const std::string& data,
269                                 const net::URLRequestStatus& status,
270                                 int response_code);
271
272   void OnOAuth2RevokeTokenFetched(const std::string& data,
273                                   const net::URLRequestStatus& status,
274                                   int response_code);
275
276   void OnListAccountsFetched(const std::string& data,
277                              const net::URLRequestStatus& status,
278                              int response_code);
279
280   void OnGetUserInfoFetched(const std::string& data,
281                             const net::URLRequestStatus& status,
282                             int response_code);
283
284   void OnMergeSessionFetched(const std::string& data,
285                              const net::URLRequestStatus& status,
286                              int response_code);
287
288   void OnUberAuthTokenFetch(const std::string& data,
289                             const net::URLRequestStatus& status,
290                             int response_code);
291
292   void OnOAuthLoginFetched(const std::string& data,
293                            const net::URLRequestStatus& status,
294                            int response_code);
295
296   // Tokenize the results of a ClientLogin fetch.
297   static void ParseClientLoginResponse(const std::string& data,
298                                        std::string* sid,
299                                        std::string* lsid,
300                                        std::string* token);
301
302   static void ParseClientLoginFailure(const std::string& data,
303                                       std::string* error,
304                                       std::string* error_url,
305                                       std::string* captcha_url,
306                                       std::string* captcha_token);
307
308   // Parse ClientLogin to OAuth2 response.
309   static bool ParseClientLoginToOAuth2Response(
310       const net::ResponseCookies& cookies,
311       std::string* auth_code);
312
313   static bool ParseClientLoginToOAuth2Cookie(const std::string& cookie,
314                                              std::string* auth_code);
315
316   // Is this a special case Gaia error for TwoFactor auth?
317   static bool IsSecondFactorSuccess(const std::string& alleged_error);
318
319   // Given parameters, create a ClientLogin request body.
320   static std::string MakeClientLoginBody(
321       const std::string& username,
322       const std::string& password,
323       const std::string& source,
324       const char* const service,
325       const std::string& login_token,
326       const std::string& login_captcha,
327       HostedAccountsSetting allow_hosted_accounts);
328   // Supply the sid / lsid returned from ClientLogin in order to
329   // request a long lived auth token for a service.
330   static std::string MakeIssueAuthTokenBody(const std::string& sid,
331                                             const std::string& lsid,
332                                             const char* const service);
333   // Create body to get OAuth2 auth code.
334   static std::string MakeGetAuthCodeBody(bool include_device_type);
335   // Given auth code, create body to get OAuth2 token pair.
336   static std::string MakeGetTokenPairBody(const std::string& auth_code);
337   // Given an OAuth2 token, create body to revoke the token.
338   std::string MakeRevokeTokenBody(const std::string& auth_token);
339   // Supply the lsid returned from ClientLogin in order to fetch
340   // user information.
341   static std::string MakeGetUserInfoBody(const std::string& lsid);
342
343   // Supply the authentication token returned from StartIssueAuthToken.
344   static std::string MakeMergeSessionBody(const std::string& auth_token,
345                                        const std::string& continue_url,
346                                        const std::string& source);
347
348   static std::string MakeGetAuthCodeHeader(const std::string& auth_token);
349
350   static std::string MakeOAuthLoginBody(const std::string& service,
351                                         const std::string& source);
352
353   // Create a fetcher usable for making any Gaia request.  |body| is used
354   // as the body of the POST request sent to GAIA.  Any strings listed in
355   // |headers| are added as extra HTTP headers in the request.
356   //
357   // |load_flags| are passed to directly to net::URLFetcher::Create() when
358   // creating the URL fetcher.
359   static net::URLFetcher* CreateGaiaFetcher(
360       net::URLRequestContextGetter* getter,
361       const std::string& body,
362       const std::string& headers,
363       const GURL& gaia_gurl,
364       int load_flags,
365       net::URLFetcherDelegate* delegate);
366
367   // From a URLFetcher result, generate an appropriate error.
368   // From the API documentation, both IssueAuthToken and ClientLogin have
369   // the same error returns.
370   static GoogleServiceAuthError GenerateAuthError(
371       const std::string& data,
372       const net::URLRequestStatus& status);
373
374   // These fields are common to GaiaAuthFetcher, same every request
375   GaiaAuthConsumer* const consumer_;
376   net::URLRequestContextGetter* const getter_;
377   std::string source_;
378   const GURL client_login_gurl_;
379   const GURL issue_auth_token_gurl_;
380   const GURL oauth2_token_gurl_;
381   const GURL oauth2_revoke_gurl_;
382   const GURL get_user_info_gurl_;
383   const GURL merge_session_gurl_;
384   const GURL uberauth_token_gurl_;
385   const GURL oauth_login_gurl_;
386   const GURL list_accounts_gurl_;
387
388   // While a fetch is going on:
389   scoped_ptr<net::URLFetcher> fetcher_;
390   GURL client_login_to_oauth2_gurl_;
391   std::string request_body_;
392   std::string requested_service_; // Currently tracked for IssueAuthToken only.
393   bool fetch_pending_;
394
395   friend class GaiaAuthFetcherTest;
396   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CaptchaParse);
397   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDeletedError);
398   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDisabledError);
399   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationError);
400   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, IncomprehensibleError);
401   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ServiceUnavailableError);
402   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckNormalErrorCode);
403   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckTwoFactorResponse);
404   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, LoginNetFailure);
405   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest,
406       ParseClientLoginToOAuth2Response);
407   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ParseOAuth2TokenPairResponse);
408   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthSuccess);
409   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthWithQuote);
410   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeSuccess);
411   FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeQuote);
412
413   DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcher);
414 };
415
416 #endif  // GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_