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