gaia_auth_fetcher_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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// A complete set of unit tests for GaiaAuthFetcher.
6// Originally ported from GoogleAuthenticator tests.
7
8#include <string>
9
10#include "base/json/json_reader.h"
11#include "base/message_loop.h"
12#include "base/stringprintf.h"
13#include "base/values.h"
14#include "chrome/test/base/testing_profile.h"
15#include "google_apis/gaia/gaia_auth_consumer.h"
16#include "google_apis/gaia/gaia_auth_fetcher.h"
17#include "google_apis/gaia/gaia_urls.h"
18#include "google_apis/gaia/google_service_auth_error.h"
19#include "google_apis/gaia/mock_url_fetcher_factory.h"
20#include "google_apis/google_api_keys.h"
21#include "googleurl/src/gurl.h"
22#include "net/base/load_flags.h"
23#include "net/base/net_errors.h"
24#include "net/http/http_status_code.h"
25#include "net/url_request/test_url_fetcher_factory.h"
26#include "net/url_request/url_fetcher_delegate.h"
27#include "net/url_request/url_request_status.h"
28#include "testing/gmock/include/gmock/gmock.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31using ::testing::_;
32using ::testing::Invoke;
33
34namespace {
35static const char kGetAuthCodeValidCookie[] =
36    "oauth_code=test-code; Path=/test; Secure; HttpOnly";
37static const char kGetAuthCodeCookieNoSecure[] =
38    "oauth_code=test-code; Path=/test; HttpOnly";
39static const char kGetAuthCodeCookieNoHttpOnly[] =
40    "oauth_code=test-code; Path=/test; Secure";
41static const char kGetAuthCodeCookieNoOAuthCode[] =
42    "Path=/test; Secure; HttpOnly";
43static const char kGetTokenPairValidResponse[] =
44    "{"
45    "  \"refresh_token\": \"rt1\","
46    "  \"access_token\": \"at1\","
47    "  \"expires_in\": 3600,"
48    "  \"token_type\": \"Bearer\""
49    "}";
50static const char kClientOAuthValidResponse[] =
51    "{"
52    "  \"oauth2\": {"
53    "    \"refresh_token\": \"rt1\","
54    "    \"access_token\": \"at1\","
55    "    \"expires_in\": 3600,"
56    "    \"token_type\": \"Bearer\""
57    "  }"
58    "}";
59
60static void ExpectCaptchaChallenge(const GoogleServiceAuthError& error) {
61  // Make sure this is a captcha server challange.
62  EXPECT_EQ(GoogleServiceAuthError::CAPTCHA_REQUIRED, error.state());
63  EXPECT_EQ("challengetokenblob", error.captcha().token);
64  EXPECT_EQ("http://www.audio.com/", error.captcha().audio_url.spec());
65  EXPECT_EQ("http://www.image.com/", error.captcha().image_url.spec());
66  EXPECT_EQ(640, error.captcha().image_width);
67  EXPECT_EQ(480, error.captcha().image_height);
68}
69
70static void ExpectBadAuth(const GoogleServiceAuthError& error) {
71  EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error.state());
72}
73
74static void ExpectTwoFactorChallenge(const GoogleServiceAuthError& error) {
75  // Make sure this is a captcha server challange.
76  EXPECT_EQ(GoogleServiceAuthError::TWO_FACTOR, error.state());
77  EXPECT_EQ("challengetokenblob", error.second_factor().token);
78  EXPECT_EQ("prompt_text", error.second_factor().prompt_text);
79  EXPECT_EQ("alternate_text", error.second_factor().alternate_text);
80  EXPECT_EQ(10, error.second_factor().field_length);
81}
82
83}  // namespace
84
85MockFetcher::MockFetcher(bool success,
86                         const GURL& url,
87                         const std::string& results,
88                         net::URLFetcher::RequestType request_type,
89                         net::URLFetcherDelegate* d)
90    : TestURLFetcher(0, url, d) {
91  set_url(url);
92  net::URLRequestStatus::Status code;
93
94  if (success) {
95    set_response_code(net::HTTP_OK);
96    code = net::URLRequestStatus::SUCCESS;
97  } else {
98    set_response_code(net::HTTP_FORBIDDEN);
99    code = net::URLRequestStatus::FAILED;
100  }
101
102  set_status(net::URLRequestStatus(code, 0));
103  SetResponseString(results);
104}
105
106MockFetcher::MockFetcher(const GURL& url,
107                         const net::URLRequestStatus& status,
108                         int response_code,
109                         const net::ResponseCookies& cookies,
110                         const std::string& results,
111                         net::URLFetcher::RequestType request_type,
112                         net::URLFetcherDelegate* d)
113    : TestURLFetcher(0, url, d) {
114  set_url(url);
115  set_status(status);
116  set_response_code(response_code);
117  set_cookies(cookies);
118  SetResponseString(results);
119}
120
121MockFetcher::~MockFetcher() {}
122
123void MockFetcher::Start() {
124  delegate()->OnURLFetchComplete(this);
125}
126
127class GaiaAuthFetcherTest : public testing::Test {
128 public:
129  GaiaAuthFetcherTest()
130      : client_login_source_(GaiaUrls::GetInstance()->client_login_url()),
131        issue_auth_token_source_(
132            GaiaUrls::GetInstance()->issue_auth_token_url()),
133        client_login_to_oauth2_source_(
134            GaiaUrls::GetInstance()->client_login_to_oauth2_url()),
135        oauth2_token_source_(GaiaUrls::GetInstance()->oauth2_token_url()),
136        token_auth_source_(GaiaUrls::GetInstance()->token_auth_url()),
137        merge_session_source_(GaiaUrls::GetInstance()->merge_session_url()),
138        uberauth_token_source_(base::StringPrintf(
139            "%s?source=&issueuberauth=1",
140            GaiaUrls::GetInstance()->oauth1_login_url().c_str())),
141        client_oauth_source_(GaiaUrls::GetInstance()->client_oauth_url()),
142        oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()) {}
143
144  void RunParsingTest(const std::string& data,
145                      const std::string& sid,
146                      const std::string& lsid,
147                      const std::string& token) {
148    std::string out_sid;
149    std::string out_lsid;
150    std::string out_token;
151
152    GaiaAuthFetcher::ParseClientLoginResponse(data,
153                                              &out_sid,
154                                              &out_lsid,
155                                              &out_token);
156    EXPECT_EQ(lsid, out_lsid);
157    EXPECT_EQ(sid, out_sid);
158    EXPECT_EQ(token, out_token);
159  }
160
161  void RunErrorParsingTest(const std::string& data,
162                           const std::string& error,
163                           const std::string& error_url,
164                           const std::string& captcha_url,
165                           const std::string& captcha_token) {
166    std::string out_error;
167    std::string out_error_url;
168    std::string out_captcha_url;
169    std::string out_captcha_token;
170
171    GaiaAuthFetcher::ParseClientLoginFailure(data,
172                                             &out_error,
173                                             &out_error_url,
174                                             &out_captcha_url,
175                                             &out_captcha_token);
176    EXPECT_EQ(error, out_error);
177    EXPECT_EQ(error_url, out_error_url);
178    EXPECT_EQ(captcha_url, out_captcha_url);
179    EXPECT_EQ(captcha_token, out_captcha_token);
180  }
181
182  net::ResponseCookies cookies_;
183  GURL client_login_source_;
184  GURL issue_auth_token_source_;
185  GURL client_login_to_oauth2_source_;
186  GURL oauth2_token_source_;
187  GURL token_auth_source_;
188  GURL merge_session_source_;
189  GURL uberauth_token_source_;
190  GURL client_oauth_source_;
191  GURL oauth_login_gurl_;
192  TestingProfile profile_;
193 protected:
194  MessageLoop message_loop_;
195};
196
197class MockGaiaConsumer : public GaiaAuthConsumer {
198 public:
199  MockGaiaConsumer() {}
200  ~MockGaiaConsumer() {}
201
202  MOCK_METHOD1(OnClientLoginSuccess, void(const ClientLoginResult& result));
203  MOCK_METHOD2(OnIssueAuthTokenSuccess, void(const std::string& service,
204      const std::string& token));
205  MOCK_METHOD1(OnClientOAuthSuccess,
206               void(const GaiaAuthConsumer::ClientOAuthResult& result));
207  MOCK_METHOD1(OnMergeSessionSuccess, void(const std::string& data));
208  MOCK_METHOD1(OnUberAuthTokenSuccess, void(const std::string& data));
209  MOCK_METHOD1(OnClientLoginFailure,
210      void(const GoogleServiceAuthError& error));
211  MOCK_METHOD2(OnIssueAuthTokenFailure, void(const std::string& service,
212      const GoogleServiceAuthError& error));
213  MOCK_METHOD1(OnClientOAuthFailure,
214      void(const GoogleServiceAuthError& error));
215  MOCK_METHOD1(OnMergeSessionFailure, void(
216      const GoogleServiceAuthError& error));
217  MOCK_METHOD1(OnUberAuthTokenFailure, void(
218      const GoogleServiceAuthError& error));
219};
220
221#if defined(OS_WIN)
222#define MAYBE_ErrorComparator DISABLED_ErrorComparator
223#else
224#define MAYBE_ErrorComparator ErrorComparator
225#endif
226
227TEST_F(GaiaAuthFetcherTest, MAYBE_ErrorComparator) {
228  GoogleServiceAuthError expected_error =
229      GoogleServiceAuthError::FromConnectionError(-101);
230
231  GoogleServiceAuthError matching_error =
232      GoogleServiceAuthError::FromConnectionError(-101);
233
234  EXPECT_TRUE(expected_error == matching_error);
235
236  expected_error = GoogleServiceAuthError::FromConnectionError(6);
237
238  EXPECT_FALSE(expected_error == matching_error);
239
240  expected_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE);
241
242  EXPECT_FALSE(expected_error == matching_error);
243
244  matching_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE);
245
246  EXPECT_TRUE(expected_error == matching_error);
247}
248
249TEST_F(GaiaAuthFetcherTest, LoginNetFailure) {
250  int error_no = net::ERR_CONNECTION_RESET;
251  net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no);
252
253  GoogleServiceAuthError expected_error =
254      GoogleServiceAuthError::FromConnectionError(error_no);
255
256  MockGaiaConsumer consumer;
257  EXPECT_CALL(consumer, OnClientLoginFailure(expected_error))
258      .Times(1);
259
260  GaiaAuthFetcher auth(&consumer, std::string(),
261      profile_.GetRequestContext());
262
263  MockFetcher mock_fetcher(
264      client_login_source_, status, 0, net::ResponseCookies(), std::string(),
265      net::URLFetcher::GET, &auth);
266  auth.OnURLFetchComplete(&mock_fetcher);
267}
268
269TEST_F(GaiaAuthFetcherTest, TokenNetFailure) {
270  int error_no = net::ERR_CONNECTION_RESET;
271  net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no);
272
273  GoogleServiceAuthError expected_error =
274      GoogleServiceAuthError::FromConnectionError(error_no);
275
276  MockGaiaConsumer consumer;
277  EXPECT_CALL(consumer, OnIssueAuthTokenFailure(_, expected_error))
278      .Times(1);
279
280  GaiaAuthFetcher auth(&consumer, std::string(),
281      profile_.GetRequestContext());
282
283  MockFetcher mock_fetcher(
284      issue_auth_token_source_, status, 0, cookies_, std::string(),
285      net::URLFetcher::GET, &auth);
286  auth.OnURLFetchComplete(&mock_fetcher);
287}
288
289
290TEST_F(GaiaAuthFetcherTest, LoginDenied) {
291  std::string data("Error=BadAuthentication");
292  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
293
294  GoogleServiceAuthError expected_error(
295      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
296
297  MockGaiaConsumer consumer;
298  EXPECT_CALL(consumer, OnClientLoginFailure(expected_error))
299      .Times(1);
300
301  GaiaAuthFetcher auth(&consumer, std::string(),
302      profile_.GetRequestContext());
303
304  MockFetcher mock_fetcher(
305      client_login_source_, status, net::HTTP_FORBIDDEN, cookies_, data,
306      net::URLFetcher::GET, &auth);
307  auth.OnURLFetchComplete(&mock_fetcher);
308}
309
310TEST_F(GaiaAuthFetcherTest, ParseRequest) {
311  RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth\n", "sid", "lsid", "auth");
312  RunParsingTest("LSID=lsid\nSID=sid\nAuth=auth\n", "sid", "lsid", "auth");
313  RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth", "sid", "lsid", "auth");
314  RunParsingTest("SID=sid\nAuth=auth\n", "sid", "", "auth");
315  RunParsingTest("LSID=lsid\nAuth=auth\n", "", "lsid", "auth");
316  RunParsingTest("\nAuth=auth\n", "", "", "auth");
317  RunParsingTest("SID=sid", "sid", "", "");
318}
319
320TEST_F(GaiaAuthFetcherTest, ParseErrorRequest) {
321  RunErrorParsingTest("Url=U\n"
322                      "Error=E\n"
323                      "CaptchaToken=T\n"
324                      "CaptchaUrl=C\n", "E", "U", "C", "T");
325  RunErrorParsingTest("CaptchaToken=T\n"
326                      "Error=E\n"
327                      "Url=U\n"
328                      "CaptchaUrl=C\n", "E", "U", "C", "T");
329  RunErrorParsingTest("\n\n\nCaptchaToken=T\n"
330                      "\nError=E\n"
331                      "\nUrl=U\n"
332                      "CaptchaUrl=C\n", "E", "U", "C", "T");
333}
334
335
336TEST_F(GaiaAuthFetcherTest, OnlineLogin) {
337  std::string data("SID=sid\nLSID=lsid\nAuth=auth\n");
338
339  GaiaAuthConsumer::ClientLoginResult result;
340  result.lsid = "lsid";
341  result.sid = "sid";
342  result.token = "auth";
343  result.data = data;
344
345  MockGaiaConsumer consumer;
346  EXPECT_CALL(consumer, OnClientLoginSuccess(result))
347      .Times(1);
348
349  GaiaAuthFetcher auth(&consumer, std::string(),
350      profile_.GetRequestContext());
351  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
352  MockFetcher mock_fetcher(
353      client_login_source_, status, net::HTTP_OK, cookies_, data,
354      net::URLFetcher::GET, &auth);
355  auth.OnURLFetchComplete(&mock_fetcher);
356}
357
358TEST_F(GaiaAuthFetcherTest, WorkingIssueAuthToken) {
359  MockGaiaConsumer consumer;
360  EXPECT_CALL(consumer, OnIssueAuthTokenSuccess(_, "token"))
361      .Times(1);
362
363  GaiaAuthFetcher auth(&consumer, std::string(),
364      profile_.GetRequestContext());
365  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
366  MockFetcher mock_fetcher(
367      issue_auth_token_source_, status, net::HTTP_OK, cookies_, "token",
368      net::URLFetcher::GET, &auth);
369  auth.OnURLFetchComplete(&mock_fetcher);
370}
371
372TEST_F(GaiaAuthFetcherTest, CheckTwoFactorResponse) {
373  std::string response =
374      base::StringPrintf("Error=BadAuthentication\n%s\n",
375                         GaiaAuthFetcher::kSecondFactor);
376  EXPECT_TRUE(GaiaAuthFetcher::IsSecondFactorSuccess(response));
377}
378
379TEST_F(GaiaAuthFetcherTest, CheckNormalErrorCode) {
380  std::string response = "Error=BadAuthentication\n";
381  EXPECT_FALSE(GaiaAuthFetcher::IsSecondFactorSuccess(response));
382}
383
384TEST_F(GaiaAuthFetcherTest, TwoFactorLogin) {
385  std::string response = base::StringPrintf("Error=BadAuthentication\n%s\n",
386      GaiaAuthFetcher::kSecondFactor);
387
388  GoogleServiceAuthError error =
389      GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR);
390
391  MockGaiaConsumer consumer;
392  EXPECT_CALL(consumer, OnClientLoginFailure(error))
393      .Times(1);
394
395  GaiaAuthFetcher auth(&consumer, std::string(),
396      profile_.GetRequestContext());
397  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
398  MockFetcher mock_fetcher(
399      client_login_source_, status, net::HTTP_FORBIDDEN, cookies_, response,
400      net::URLFetcher::GET, &auth);
401  auth.OnURLFetchComplete(&mock_fetcher);
402}
403
404TEST_F(GaiaAuthFetcherTest, CaptchaParse) {
405  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
406  std::string data = "Url=http://www.google.com/login/captcha\n"
407                     "Error=CaptchaRequired\n"
408                     "CaptchaToken=CCTOKEN\n"
409                     "CaptchaUrl=Captcha?ctoken=CCTOKEN\n";
410  GoogleServiceAuthError error =
411      GaiaAuthFetcher::GenerateAuthError(data, status);
412
413  std::string token = "CCTOKEN";
414  GURL image_url("http://accounts.google.com/Captcha?ctoken=CCTOKEN");
415  GURL unlock_url("http://www.google.com/login/captcha");
416
417  EXPECT_EQ(error.state(), GoogleServiceAuthError::CAPTCHA_REQUIRED);
418  EXPECT_EQ(error.captcha().token, token);
419  EXPECT_EQ(error.captcha().image_url, image_url);
420  EXPECT_EQ(error.captcha().unlock_url, unlock_url);
421}
422
423TEST_F(GaiaAuthFetcherTest, AccountDeletedError) {
424  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
425  std::string data = "Error=AccountDeleted\n";
426  GoogleServiceAuthError error =
427      GaiaAuthFetcher::GenerateAuthError(data, status);
428  EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DELETED);
429}
430
431TEST_F(GaiaAuthFetcherTest, AccountDisabledError) {
432  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
433  std::string data = "Error=AccountDisabled\n";
434  GoogleServiceAuthError error =
435      GaiaAuthFetcher::GenerateAuthError(data, status);
436  EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DISABLED);
437}
438
439TEST_F(GaiaAuthFetcherTest,BadAuthenticationError) {
440  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
441  std::string data = "Error=BadAuthentication\n";
442  GoogleServiceAuthError error =
443      GaiaAuthFetcher::GenerateAuthError(data, status);
444  EXPECT_EQ(error.state(), GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
445}
446
447TEST_F(GaiaAuthFetcherTest,IncomprehensibleError) {
448  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
449  std::string data = "Error=Gobbledygook\n";
450  GoogleServiceAuthError error =
451      GaiaAuthFetcher::GenerateAuthError(data, status);
452  EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE);
453}
454
455TEST_F(GaiaAuthFetcherTest,ServiceUnavailableError) {
456  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
457  std::string data = "Error=ServiceUnavailable\n";
458  GoogleServiceAuthError error =
459      GaiaAuthFetcher::GenerateOAuthLoginError(data, status);
460  EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE);
461}
462
463TEST_F(GaiaAuthFetcherTest, OAuthAccountDeletedError) {
464  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
465  std::string data = "Error=adel\n";
466  GoogleServiceAuthError error =
467      GaiaAuthFetcher::GenerateOAuthLoginError(data, status);
468  EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DELETED);
469}
470
471TEST_F(GaiaAuthFetcherTest, OAuthAccountDisabledError) {
472  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
473  std::string data = "Error=adis\n";
474  GoogleServiceAuthError error =
475      GaiaAuthFetcher::GenerateOAuthLoginError(data, status);
476  EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DISABLED);
477}
478
479TEST_F(GaiaAuthFetcherTest, OAuthBadAuthenticationError) {
480  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
481  std::string data = "Error=badauth\n";
482  GoogleServiceAuthError error =
483      GaiaAuthFetcher::GenerateOAuthLoginError(data, status);
484  EXPECT_EQ(error.state(), GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
485}
486
487TEST_F(GaiaAuthFetcherTest, OAuthServiceUnavailableError) {
488  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
489  std::string data = "Error=ire\n";
490  GoogleServiceAuthError error =
491      GaiaAuthFetcher::GenerateOAuthLoginError(data, status);
492  EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE);
493}
494
495TEST_F(GaiaAuthFetcherTest, FullLogin) {
496  MockGaiaConsumer consumer;
497  EXPECT_CALL(consumer, OnClientLoginSuccess(_))
498      .Times(1);
499
500  MockURLFetcherFactory<MockFetcher> factory;
501
502  GaiaAuthFetcher auth(&consumer, std::string(),
503      profile_.GetRequestContext());
504  auth.StartClientLogin("username",
505                        "password",
506                        "service",
507                        std::string(),
508                        std::string(),
509                        GaiaAuthFetcher::HostedAccountsAllowed);
510}
511
512TEST_F(GaiaAuthFetcherTest, FullLoginFailure) {
513  MockGaiaConsumer consumer;
514  EXPECT_CALL(consumer, OnClientLoginFailure(_))
515      .Times(1);
516
517  MockURLFetcherFactory<MockFetcher> factory;
518  factory.set_success(false);
519
520  GaiaAuthFetcher auth(&consumer, std::string(),
521      profile_.GetRequestContext());
522  auth.StartClientLogin("username",
523                        "password",
524                        "service",
525                        std::string(),
526                        std::string(),
527                        GaiaAuthFetcher::HostedAccountsAllowed);
528}
529
530TEST_F(GaiaAuthFetcherTest, ClientFetchPending) {
531  MockGaiaConsumer consumer;
532  EXPECT_CALL(consumer, OnClientLoginSuccess(_))
533      .Times(1);
534
535  net::TestURLFetcherFactory factory;
536
537  GaiaAuthFetcher auth(&consumer, std::string(),
538      profile_.GetRequestContext());
539  auth.StartClientLogin("username",
540                        "password",
541                        "service",
542                        std::string(),
543                        std::string(),
544                        GaiaAuthFetcher::HostedAccountsAllowed);
545
546  EXPECT_TRUE(auth.HasPendingFetch());
547  MockFetcher mock_fetcher(
548      client_login_source_,
549      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
550      net::HTTP_OK, cookies_, "SID=sid\nLSID=lsid\nAuth=auth\n",
551      net::URLFetcher::GET, &auth);
552  auth.OnURLFetchComplete(&mock_fetcher);
553  EXPECT_FALSE(auth.HasPendingFetch());
554}
555
556TEST_F(GaiaAuthFetcherTest, FullTokenSuccess) {
557  MockGaiaConsumer consumer;
558  EXPECT_CALL(consumer, OnIssueAuthTokenSuccess("service", "token"))
559      .Times(1);
560
561  net::TestURLFetcherFactory factory;
562  GaiaAuthFetcher auth(&consumer, std::string(),
563                       profile_.GetRequestContext());
564  auth.StartIssueAuthToken("sid", "lsid", "service");
565
566  EXPECT_TRUE(auth.HasPendingFetch());
567  MockFetcher mock_fetcher(
568      issue_auth_token_source_,
569      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
570      net::HTTP_OK, cookies_, "token",
571      net::URLFetcher::GET, &auth);
572  auth.OnURLFetchComplete(&mock_fetcher);
573  EXPECT_FALSE(auth.HasPendingFetch());
574}
575
576TEST_F(GaiaAuthFetcherTest, FullTokenFailure) {
577  MockGaiaConsumer consumer;
578  EXPECT_CALL(consumer, OnIssueAuthTokenFailure("service", _))
579      .Times(1);
580
581  net::TestURLFetcherFactory factory;
582
583  GaiaAuthFetcher auth(&consumer, std::string(),
584      profile_.GetRequestContext());
585  auth.StartIssueAuthToken("sid", "lsid", "service");
586
587  EXPECT_TRUE(auth.HasPendingFetch());
588  MockFetcher mock_fetcher(
589      issue_auth_token_source_,
590      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
591      net::HTTP_FORBIDDEN, cookies_, "", net::URLFetcher::GET, &auth);
592  auth.OnURLFetchComplete(&mock_fetcher);
593  EXPECT_FALSE(auth.HasPendingFetch());
594}
595
596TEST_F(GaiaAuthFetcherTest, OAuthLoginTokenSuccess) {
597  MockGaiaConsumer consumer;
598  EXPECT_CALL(consumer, OnClientOAuthSuccess(
599      GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600))).Times(1);
600
601  net::TestURLFetcherFactory factory;
602  GaiaAuthFetcher auth(&consumer, std::string(),
603                       profile_.GetRequestContext());
604  auth.StartLsoForOAuthLoginTokenExchange("lso_token");
605  net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
606  EXPECT_TRUE(NULL != fetcher);
607  EXPECT_EQ(net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES,
608            fetcher->GetLoadFlags());
609
610  net::ResponseCookies cookies;
611  cookies.push_back(kGetAuthCodeValidCookie);
612  EXPECT_TRUE(auth.HasPendingFetch());
613  MockFetcher mock_fetcher1(
614      client_login_to_oauth2_source_,
615      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
616      net::HTTP_OK, cookies, "",
617      net::URLFetcher::POST, &auth);
618  auth.OnURLFetchComplete(&mock_fetcher1);
619  EXPECT_TRUE(auth.HasPendingFetch());
620  MockFetcher mock_fetcher2(
621      oauth2_token_source_,
622      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
623      net::HTTP_OK, cookies_, kGetTokenPairValidResponse,
624      net::URLFetcher::POST, &auth);
625  auth.OnURLFetchComplete(&mock_fetcher2);
626  EXPECT_FALSE(auth.HasPendingFetch());
627}
628
629TEST_F(GaiaAuthFetcherTest, OAuthLoginTokenWithCookies) {
630  MockGaiaConsumer consumer;
631  net::TestURLFetcherFactory factory;
632  GaiaAuthFetcher auth(&consumer, std::string(),
633                       profile_.GetRequestContext());
634  auth.StartCookieForOAuthLoginTokenExchange("0");
635  net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
636  EXPECT_TRUE(NULL != fetcher);
637  EXPECT_EQ(net::LOAD_NORMAL, fetcher->GetLoadFlags());
638}
639
640TEST_F(GaiaAuthFetcherTest, OAuthLoginTokenClientLoginToOAuth2Failure) {
641  MockGaiaConsumer consumer;
642  EXPECT_CALL(consumer, OnClientOAuthFailure(_))
643      .Times(1);
644
645  net::TestURLFetcherFactory factory;
646  GaiaAuthFetcher auth(&consumer, std::string(),
647                       profile_.GetRequestContext());
648  auth.StartLsoForOAuthLoginTokenExchange("lso_token");
649
650  net::ResponseCookies cookies;
651  EXPECT_TRUE(auth.HasPendingFetch());
652  MockFetcher mock_fetcher(
653      client_login_to_oauth2_source_,
654      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
655      net::HTTP_FORBIDDEN, cookies, "",
656      net::URLFetcher::POST, &auth);
657  auth.OnURLFetchComplete(&mock_fetcher);
658  EXPECT_FALSE(auth.HasPendingFetch());
659}
660
661TEST_F(GaiaAuthFetcherTest, OAuthLoginTokenOAuth2TokenPairFailure) {
662  MockGaiaConsumer consumer;
663  EXPECT_CALL(consumer, OnClientOAuthFailure(_))
664      .Times(1);
665
666  net::TestURLFetcherFactory factory;
667  GaiaAuthFetcher auth(&consumer, std::string(),
668                       profile_.GetRequestContext());
669  auth.StartLsoForOAuthLoginTokenExchange("lso_token");
670
671  net::ResponseCookies cookies;
672  cookies.push_back(kGetAuthCodeValidCookie);
673  EXPECT_TRUE(auth.HasPendingFetch());
674  MockFetcher mock_fetcher1(
675      client_login_to_oauth2_source_,
676      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
677      net::HTTP_OK, cookies, "",
678      net::URLFetcher::POST, &auth);
679  auth.OnURLFetchComplete(&mock_fetcher1);
680  EXPECT_TRUE(auth.HasPendingFetch());
681  MockFetcher mock_fetcher2(
682      oauth2_token_source_,
683      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
684      net::HTTP_FORBIDDEN, cookies_, "",
685      net::URLFetcher::POST, &auth);
686  auth.OnURLFetchComplete(&mock_fetcher2);
687  EXPECT_FALSE(auth.HasPendingFetch());
688}
689
690TEST_F(GaiaAuthFetcherTest, MergeSessionSuccess) {
691  MockGaiaConsumer consumer;
692  EXPECT_CALL(consumer, OnMergeSessionSuccess("<html></html>"))
693      .Times(1);
694
695  net::TestURLFetcherFactory factory;
696
697  GaiaAuthFetcher auth(&consumer, std::string(),
698      profile_.GetRequestContext());
699  auth.StartMergeSession("myubertoken");
700
701  EXPECT_TRUE(auth.HasPendingFetch());
702  MockFetcher mock_fetcher(
703      merge_session_source_,
704      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
705      net::HTTP_OK, cookies_, "<html></html>", net::URLFetcher::GET,
706      &auth);
707  auth.OnURLFetchComplete(&mock_fetcher);
708  EXPECT_FALSE(auth.HasPendingFetch());
709}
710
711TEST_F(GaiaAuthFetcherTest, MergeSessionSuccessRedirect) {
712  MockGaiaConsumer consumer;
713  EXPECT_CALL(consumer, OnMergeSessionSuccess("<html></html>"))
714      .Times(1);
715
716  net::TestURLFetcherFactory factory;
717
718  GaiaAuthFetcher auth(&consumer, std::string(),
719      profile_.GetRequestContext());
720  auth.StartMergeSession("myubertoken");
721
722  // Make sure the fetcher created has the expected flags.  Set its url()
723  // properties to reflect a redirect.
724  net::TestURLFetcher* test_fetcher = factory.GetFetcherByID(0);
725  EXPECT_TRUE(test_fetcher != NULL);
726  EXPECT_TRUE(test_fetcher->GetLoadFlags() == net::LOAD_NORMAL);
727  EXPECT_TRUE(auth.HasPendingFetch());
728
729  GURL final_url("http://www.google.com/CheckCookie");
730  test_fetcher->set_url(final_url);
731  test_fetcher->set_status(
732      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
733  test_fetcher->set_response_code(net::HTTP_OK);
734  test_fetcher->set_cookies(cookies_);
735  test_fetcher->SetResponseString("<html></html>");
736
737  auth.OnURLFetchComplete(test_fetcher);
738  EXPECT_FALSE(auth.HasPendingFetch());
739}
740
741TEST_F(GaiaAuthFetcherTest, UberAuthTokenSuccess) {
742  MockGaiaConsumer consumer;
743  EXPECT_CALL(consumer, OnUberAuthTokenSuccess("uberToken"))
744      .Times(1);
745
746  net::TestURLFetcherFactory factory;
747
748  GaiaAuthFetcher auth(&consumer, std::string(),
749      profile_.GetRequestContext());
750  auth.StartTokenFetchForUberAuthExchange("myAccessToken");
751
752  EXPECT_TRUE(auth.HasPendingFetch());
753  MockFetcher mock_fetcher(
754      uberauth_token_source_,
755      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
756      net::HTTP_OK, cookies_, "uberToken", net::URLFetcher::POST,
757      &auth);
758  auth.OnURLFetchComplete(&mock_fetcher);
759  EXPECT_FALSE(auth.HasPendingFetch());
760}
761
762TEST_F(GaiaAuthFetcherTest, ParseClientLoginToOAuth2Response) {
763  {  // No cookies.
764    std::string auth_code;
765    net::ResponseCookies cookies;
766    EXPECT_FALSE(GaiaAuthFetcher::ParseClientLoginToOAuth2Response(
767        cookies, &auth_code));
768    EXPECT_EQ("", auth_code);
769  }
770  {  // Few cookies, nothing appropriate.
771    std::string auth_code;
772    net::ResponseCookies cookies;
773    cookies.push_back(kGetAuthCodeCookieNoSecure);
774    cookies.push_back(kGetAuthCodeCookieNoHttpOnly);
775    cookies.push_back(kGetAuthCodeCookieNoOAuthCode);
776    EXPECT_FALSE(GaiaAuthFetcher::ParseClientLoginToOAuth2Response(
777        cookies, &auth_code));
778    EXPECT_EQ("", auth_code);
779  }
780  {  // Few cookies, one of them is valid.
781    std::string auth_code;
782    net::ResponseCookies cookies;
783    cookies.push_back(kGetAuthCodeCookieNoSecure);
784    cookies.push_back(kGetAuthCodeCookieNoHttpOnly);
785    cookies.push_back(kGetAuthCodeCookieNoOAuthCode);
786    cookies.push_back(kGetAuthCodeValidCookie);
787    EXPECT_TRUE(GaiaAuthFetcher::ParseClientLoginToOAuth2Response(
788        cookies, &auth_code));
789    EXPECT_EQ("test-code", auth_code);
790  }
791  {  // Single valid cookie (like in real responses).
792    std::string auth_code;
793    net::ResponseCookies cookies;
794    cookies.push_back(kGetAuthCodeValidCookie);
795    EXPECT_TRUE(GaiaAuthFetcher::ParseClientLoginToOAuth2Response(
796        cookies, &auth_code));
797    EXPECT_EQ("test-code", auth_code);
798  }
799}
800
801TEST_F(GaiaAuthFetcherTest, ClientOAuthSuccess) {
802  MockURLFetcherFactory<MockFetcher> factory;
803  factory.set_results(kClientOAuthValidResponse);
804
805  MockGaiaConsumer consumer;
806  EXPECT_CALL(consumer, OnClientOAuthSuccess(
807      GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600))).Times(1);
808
809  GaiaAuthFetcher auth(&consumer, "tests", profile_.GetRequestContext());
810  std::vector<std::string> scopes;
811  scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope());
812  scopes.push_back("https://some.other.scope.com");
813  auth.StartClientOAuth("username", "password", scopes, "", "en");
814
815  std::string expected_text = base::StringPrintf(
816      "{"
817      "\"email\": \"username\","
818      "\"password\": \"password\","
819      "\"scopes\": [\"https://www.google.com/accounts/OAuthLogin\","
820      "             \"https://some.other.scope.com\"],"
821      "\"oauth2_client_id\": \"%s\","
822      "\"friendly_device_name\": \"tests\","
823      "\"accepts_challenges\": [\"Captcha\", \"TwoStep\"],"
824      "\"locale\": \"en\","
825      "\"fallback\": { \"name\": \"GetOAuth2Token\" }"
826      "}",
827      google_apis::GetOAuth2ClientID(google_apis::CLIENT_MAIN).c_str());
828
829  scoped_ptr<base::Value> actual(base::JSONReader::Read(auth.request_body_));
830  scoped_ptr<base::Value> expected(base::JSONReader::Read(expected_text));
831  EXPECT_TRUE(expected->Equals(actual.get()));
832}
833
834TEST_F(GaiaAuthFetcherTest, ClientOAuthWithQuote) {
835  MockURLFetcherFactory<MockFetcher> factory;
836  factory.set_results(kClientOAuthValidResponse);
837
838  MockGaiaConsumer consumer;
839  EXPECT_CALL(consumer, OnClientOAuthSuccess(
840      GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600))).Times(1);
841
842  GaiaAuthFetcher auth(&consumer, "te\"sts", profile_.GetRequestContext());
843  std::vector<std::string> scopes;
844  scopes.push_back("https://some.\"other.scope.com");
845  auth.StartClientOAuth("user\"name", "pass\"word", scopes, "", "e\"n");
846
847  std::string expected_text = base::StringPrintf(
848      "{"
849      "\"email\": \"user\\\"name\","
850      "\"password\": \"pass\\\"word\","
851      "\"scopes\": [\"https://some.\\\"other.scope.com\"],"
852      "\"oauth2_client_id\": \"%s\","
853      "\"friendly_device_name\": \"te\\\"sts\","
854      "\"accepts_challenges\": [\"Captcha\", \"TwoStep\"],"
855      "\"locale\": \"e\\\"n\","
856      "\"fallback\": { \"name\": \"GetOAuth2Token\" }"
857      "}",
858      google_apis::GetOAuth2ClientID(google_apis::CLIENT_MAIN).c_str());
859  scoped_ptr<base::Value> actual(base::JSONReader::Read(auth.request_body_));
860  scoped_ptr<base::Value> expected(base::JSONReader::Read(expected_text));
861  EXPECT_TRUE(expected->Equals(actual.get()));
862}
863
864TEST_F(GaiaAuthFetcherTest, ClientOAuthBadAuth) {
865  MockURLFetcherFactory<MockFetcher> factory;
866  factory.set_success(false);
867  factory.set_results("{"
868                      "  \"cause\" : \"BadAuthentication\","
869                      "  \"fallback\" : {"
870                      "    \"name\" : \"Terminating\","
871                      "    \"url\" : \"https://www.terminating.com\""
872                      "  }"
873                      "}");
874
875  MockGaiaConsumer consumer;
876  EXPECT_CALL(consumer, OnClientOAuthFailure(_))
877      .WillOnce(Invoke(ExpectBadAuth));
878
879  GaiaAuthFetcher auth(&consumer, "tests", profile_.GetRequestContext());
880  std::vector<std::string> scopes;
881  scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope());
882  auth.StartClientOAuth("username", "password", scopes, "", "en");
883}
884
885TEST_F(GaiaAuthFetcherTest, ClientOAuthCaptchaChallenge) {
886  MockURLFetcherFactory<MockFetcher> factory;
887  factory.set_success(false);
888  factory.set_results("{"
889                      "  \"cause\" : \"NeedsAdditional\","
890                      "  \"fallback\" : {"
891                      "    \"name\" : \"Terminating\","
892                      "    \"url\" : \"https://www.terminating.com\""
893                      "  },"
894                      "  \"challenge\" : {"
895                      "    \"name\" : \"Captcha\","
896                      "    \"image_url\" : \"http://www.image.com/\","
897                      "    \"image_width\" : 640,"
898                      "    \"image_height\" : 480,"
899                      "    \"audio_url\" : \"http://www.audio.com/\","
900                      "    \"challenge_token\" : \"challengetokenblob\""
901                      "  }"
902                      "}");
903
904  MockGaiaConsumer consumer;
905  EXPECT_CALL(consumer, OnClientOAuthFailure(_))
906      .WillOnce(Invoke(ExpectCaptchaChallenge));
907
908  GaiaAuthFetcher auth(&consumer, "tests", profile_.GetRequestContext());
909  std::vector<std::string> scopes;
910  scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope());
911  auth.StartClientOAuth("username", "password", scopes, "", "en");
912}
913
914TEST_F(GaiaAuthFetcherTest, ClientOAuthTwoFactorChallenge) {
915  MockURLFetcherFactory<MockFetcher> factory;
916  factory.set_success(false);
917  factory.set_results("{"
918                      "  \"cause\" : \"NeedsAdditional\","
919                      "  \"fallback\" : {"
920                      "    \"name\" : \"Terminating\","
921                      "    \"url\" : \"https://www.terminating.com\""
922                      "  },"
923                      "  \"challenge\" : {"
924                      "    \"name\" : \"TwoStep\","
925                      "    \"prompt_text\" : \"prompt_text\","
926                      "    \"alternate_text\" : \"alternate_text\","
927                      "    \"challenge_token\" : \"challengetokenblob\","
928                      "    \"field_length\" : 10"
929                      "  }"
930                      "}");
931
932  MockGaiaConsumer consumer;
933  EXPECT_CALL(consumer, OnClientOAuthFailure(_))
934      .WillOnce(Invoke(ExpectTwoFactorChallenge));
935
936  GaiaAuthFetcher auth(&consumer, "tests", profile_.GetRequestContext());
937  std::vector<std::string> scopes;
938  scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope());
939  auth.StartClientOAuth("username", "password", scopes, "", "en");
940}
941
942TEST_F(GaiaAuthFetcherTest, ClientOAuthChallengeSuccess) {
943  MockURLFetcherFactory<MockFetcher> factory;
944  factory.set_results(kClientOAuthValidResponse);
945
946  MockGaiaConsumer consumer;
947  EXPECT_CALL(consumer, OnClientOAuthSuccess(
948      GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600))).Times(2);
949
950  GaiaAuthFetcher auth1(&consumer, std::string(), profile_.GetRequestContext());
951  auth1.StartClientOAuthChallengeResponse(GoogleServiceAuthError::TWO_FACTOR,
952                                          "token", "mysolution");
953
954  scoped_ptr<base::Value> actual1(base::JSONReader::Read(auth1.request_body_));
955  scoped_ptr<base::Value> expected1(base::JSONReader::Read(
956      "{"
957      "  \"challenge_reply\" : {"
958      "    \"name\" : \"TwoStep\","
959      "    \"challenge_token\" : \"token\","
960      "    \"otp\" : \"mysolution\""
961      "  }"
962      "}"));
963  EXPECT_TRUE(expected1->Equals(actual1.get()));
964
965  GaiaAuthFetcher auth2(&consumer, "tests", profile_.GetRequestContext());
966  auth2.StartClientOAuthChallengeResponse(
967      GoogleServiceAuthError::CAPTCHA_REQUIRED, "token", "mysolution");
968
969  scoped_ptr<base::Value> actual2(base::JSONReader::Read(auth2.request_body_));
970  scoped_ptr<base::Value> expected2(base::JSONReader::Read(
971      "{"
972      "  \"challenge_reply\" : {"
973      "    \"name\" : \"Captcha\","
974      "    \"challenge_token\" : \"token\","
975      "    \"solution\" : \"mysolution\""
976      "  }"
977      "}"));
978  EXPECT_TRUE(expected2->Equals(actual2.get()));
979}
980
981TEST_F(GaiaAuthFetcherTest, ClientOAuthChallengeQuote) {
982  MockURLFetcherFactory<MockFetcher> factory;
983  factory.set_results(kClientOAuthValidResponse);
984
985  MockGaiaConsumer consumer;
986  EXPECT_CALL(consumer, OnClientOAuthSuccess(
987      GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600))).Times(1);
988
989  GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext());
990  auth.StartClientOAuthChallengeResponse(GoogleServiceAuthError::TWO_FACTOR,
991                                         "to\"ken", "my\"solution");
992
993  scoped_ptr<base::Value> actual(base::JSONReader::Read(auth.request_body_));
994  scoped_ptr<base::Value> expected(base::JSONReader::Read(
995      "{"
996      "  \"challenge_reply\" : {"
997      "    \"name\" : \"TwoStep\","
998      "    \"challenge_token\" : \"to\\\"ken\","
999      "    \"otp\" : \"my\\\"solution\""
1000      "  }"
1001      "}"));
1002  EXPECT_TRUE(expected->Equals(actual.get()));
1003}
1004
1005TEST_F(GaiaAuthFetcherTest, StartOAuthLogin) {
1006  // OAuthLogin returns the same as the ClientLogin endpoint, minus CAPTCHA
1007  // responses.
1008  std::string data("SID=sid\nLSID=lsid\nAuth=auth\n");
1009
1010  GaiaAuthConsumer::ClientLoginResult result;
1011  result.lsid = "lsid";
1012  result.sid = "sid";
1013  result.token = "auth";
1014  result.data = data;
1015
1016  MockGaiaConsumer consumer;
1017  EXPECT_CALL(consumer, OnClientLoginSuccess(result))
1018      .Times(1);
1019
1020  GaiaAuthFetcher auth(&consumer, std::string(),
1021      profile_.GetRequestContext());
1022  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
1023  MockFetcher mock_fetcher(
1024      oauth_login_gurl_, status, net::HTTP_OK, cookies_, data,
1025      net::URLFetcher::GET, &auth);
1026  auth.OnURLFetchComplete(&mock_fetcher);
1027}
1028