sync_auth_manager_unittest.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  1. // Copyright 2018 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. #include "components/sync/driver/sync_auth_manager.h"
  5. #include "base/callback_helpers.h"
  6. #include "base/run_loop.h"
  7. #include "base/test/mock_callback.h"
  8. #include "base/test/task_environment.h"
  9. #include "build/build_config.h"
  10. #include "build/chromeos_buildflags.h"
  11. #include "components/signin/public/identity_manager/identity_test_environment.h"
  12. #include "components/signin/public/identity_manager/primary_account_mutator.h"
  13. #include "components/sync/engine/connection_status.h"
  14. #include "components/sync/engine/sync_credentials.h"
  15. #include "net/base/net_errors.h"
  16. #include "services/network/test/test_url_loader_factory.h"
  17. #include "testing/gmock/include/gmock/gmock.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. namespace syncer {
  20. namespace {
  21. class SyncAuthManagerTest : public testing::Test {
  22. protected:
  23. using AccountStateChangedCallback =
  24. SyncAuthManager::AccountStateChangedCallback;
  25. using CredentialsChangedCallback =
  26. SyncAuthManager::CredentialsChangedCallback;
  27. SyncAuthManagerTest() : identity_env_(&test_url_loader_factory_) {}
  28. ~SyncAuthManagerTest() override = default;
  29. std::unique_ptr<SyncAuthManager> CreateAuthManager() {
  30. return CreateAuthManager(base::DoNothing(), base::DoNothing());
  31. }
  32. std::unique_ptr<SyncAuthManager> CreateAuthManager(
  33. const AccountStateChangedCallback& account_state_changed,
  34. const CredentialsChangedCallback& credentials_changed) {
  35. return std::make_unique<SyncAuthManager>(identity_env_.identity_manager(),
  36. account_state_changed,
  37. credentials_changed);
  38. }
  39. std::unique_ptr<SyncAuthManager> CreateAuthManagerForLocalSync() {
  40. return std::make_unique<SyncAuthManager>(nullptr, base::DoNothing(),
  41. base::DoNothing());
  42. }
  43. signin::IdentityTestEnvironment* identity_env() { return &identity_env_; }
  44. private:
  45. base::test::SingleThreadTaskEnvironment task_environment_;
  46. network::TestURLLoaderFactory test_url_loader_factory_;
  47. signin::IdentityTestEnvironment identity_env_;
  48. };
  49. TEST_F(SyncAuthManagerTest, ProvidesNothingInLocalSyncMode) {
  50. std::unique_ptr<SyncAuthManager> auth_manager =
  51. CreateAuthManagerForLocalSync();
  52. EXPECT_TRUE(auth_manager->GetActiveAccountInfo().account_info.IsEmpty());
  53. syncer::SyncCredentials credentials = auth_manager->GetCredentials();
  54. EXPECT_TRUE(credentials.email.empty());
  55. EXPECT_TRUE(credentials.access_token.empty());
  56. EXPECT_TRUE(auth_manager->access_token().empty());
  57. // Note: Calling RegisterForAuthNotifications or any of the Connection*()
  58. // methods is illegal in local Sync mode, so we don't test that.
  59. }
  60. TEST_F(SyncAuthManagerTest, IgnoresEventsIfNotRegistered) {
  61. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  62. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  63. EXPECT_CALL(account_state_changed, Run()).Times(0);
  64. EXPECT_CALL(credentials_changed, Run()).Times(0);
  65. std::unique_ptr<SyncAuthManager> auth_manager =
  66. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  67. // Fire some auth events. We haven't called RegisterForAuthNotifications, so
  68. // none of this should result in any callback calls.
  69. CoreAccountId account_id =
  70. identity_env()
  71. ->MakePrimaryAccountAvailable("test@email.com",
  72. signin::ConsentLevel::kSync)
  73. .account_id;
  74. // Without RegisterForAuthNotifications, the active account should always be
  75. // reported as empty.
  76. EXPECT_TRUE(
  77. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  78. identity_env()->SetRefreshTokenForPrimaryAccount();
  79. EXPECT_TRUE(
  80. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  81. // ChromeOS doesn't support sign-out.
  82. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  83. identity_env()->ClearPrimaryAccount();
  84. EXPECT_TRUE(
  85. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  86. #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
  87. }
  88. // ChromeOS doesn't support sign-out.
  89. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  90. TEST_F(SyncAuthManagerTest, ForwardsPrimaryAccountEvents) {
  91. // Start out already signed in before the SyncAuthManager is created.
  92. CoreAccountId account_id =
  93. identity_env()
  94. ->MakePrimaryAccountAvailable("test@email.com",
  95. signin::ConsentLevel::kSync)
  96. .account_id;
  97. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  98. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  99. EXPECT_CALL(account_state_changed, Run()).Times(0);
  100. EXPECT_CALL(credentials_changed, Run()).Times(0);
  101. std::unique_ptr<SyncAuthManager> auth_manager =
  102. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  103. auth_manager->RegisterForAuthNotifications();
  104. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  105. account_id);
  106. // Sign out of the account.
  107. EXPECT_CALL(account_state_changed, Run());
  108. // Note: The ordering of removing the refresh token and the actual sign-out is
  109. // undefined, see comment on IdentityManager::Observer. So we might or might
  110. // not get a |credentials_changed| call here.
  111. EXPECT_CALL(credentials_changed, Run()).Times(testing::AtMost(1));
  112. identity_env()->ClearPrimaryAccount();
  113. EXPECT_TRUE(
  114. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  115. // Sign in to a different account.
  116. EXPECT_CALL(account_state_changed, Run());
  117. CoreAccountId second_account_id =
  118. identity_env()
  119. ->MakePrimaryAccountAvailable("test@email.com",
  120. signin::ConsentLevel::kSync)
  121. .account_id;
  122. EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  123. second_account_id);
  124. }
  125. TEST_F(SyncAuthManagerTest, NotifiesOfSignoutBeforeAccessTokenIsGone) {
  126. // Start out already signed in before the SyncAuthManager is created.
  127. CoreAccountId account_id =
  128. identity_env()
  129. ->MakePrimaryAccountAvailable("test@email.com",
  130. signin::ConsentLevel::kSync)
  131. .account_id;
  132. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  133. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  134. std::unique_ptr<SyncAuthManager> auth_manager =
  135. CreateAuthManager(account_state_changed.Get(), base::DoNothing());
  136. auth_manager->RegisterForAuthNotifications();
  137. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  138. account_id);
  139. auth_manager->ConnectionOpened();
  140. // Make sure an access token is available.
  141. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  142. "access_token", base::Time::Now() + base::Hours(1));
  143. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  144. // Sign out of the account.
  145. EXPECT_CALL(account_state_changed, Run()).WillOnce([&]() {
  146. // At the time the callback gets run, the access token should still be here.
  147. EXPECT_FALSE(auth_manager->GetCredentials().access_token.empty());
  148. });
  149. identity_env()->ClearPrimaryAccount();
  150. // After the signout is complete, the access token should be gone.
  151. EXPECT_TRUE(
  152. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  153. }
  154. #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
  155. // Unconsented primary accounts (aka secondary accounts) are only supported on
  156. // Win/Mac/Linux.
  157. #if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
  158. TEST_F(SyncAuthManagerTest, ForwardsSecondaryAccountEvents) {
  159. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  160. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  161. EXPECT_CALL(account_state_changed, Run()).Times(0);
  162. EXPECT_CALL(credentials_changed, Run()).Times(0);
  163. std::unique_ptr<SyncAuthManager> auth_manager =
  164. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  165. auth_manager->RegisterForAuthNotifications();
  166. ASSERT_TRUE(
  167. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  168. // Make a non-primary account available with both a refresh token and cookie.
  169. EXPECT_CALL(account_state_changed, Run());
  170. AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
  171. "test@email.com", signin::ConsentLevel::kSignin);
  172. EXPECT_FALSE(auth_manager->GetActiveAccountInfo().is_sync_consented);
  173. EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  174. account_info.account_id);
  175. // Make the account primary.
  176. EXPECT_CALL(account_state_changed, Run());
  177. signin::PrimaryAccountMutator* primary_account_mutator =
  178. identity_env()->identity_manager()->GetPrimaryAccountMutator();
  179. primary_account_mutator->SetPrimaryAccount(account_info.account_id,
  180. signin::ConsentLevel::kSync);
  181. EXPECT_TRUE(auth_manager->GetActiveAccountInfo().is_sync_consented);
  182. }
  183. #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) &&
  184. // !BUILDFLAG(IS_IOS)
  185. // ChromeOS doesn't support sign-out.
  186. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  187. TEST_F(SyncAuthManagerTest, ClearsAuthErrorOnSignout) {
  188. // Start out already signed in before the SyncAuthManager is created.
  189. CoreAccountId account_id =
  190. identity_env()
  191. ->MakePrimaryAccountAvailable("test@email.com",
  192. signin::ConsentLevel::kSync)
  193. .account_id;
  194. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  195. auth_manager->RegisterForAuthNotifications();
  196. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  197. account_id);
  198. ASSERT_EQ(auth_manager->GetLastAuthError().state(),
  199. GoogleServiceAuthError::NONE);
  200. // Sign out of the account.
  201. // The ordering of removing the refresh token and the actual sign-out is
  202. // undefined, see comment on IdentityManager::Observer. Here, explicitly
  203. // revoke the refresh token first to force an auth error.
  204. identity_env()->RemoveRefreshTokenForPrimaryAccount();
  205. ASSERT_NE(auth_manager->GetLastAuthError().state(),
  206. GoogleServiceAuthError::NONE);
  207. // Now actually sign out, i.e. remove the primary account. This should clear
  208. // the auth error, since it's now not meaningful anymore.
  209. identity_env()->ClearPrimaryAccount();
  210. EXPECT_EQ(auth_manager->GetLastAuthError().state(),
  211. GoogleServiceAuthError::NONE);
  212. }
  213. #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
  214. TEST_F(SyncAuthManagerTest, DoesNotClearAuthErrorOnSyncDisable) {
  215. // Start out already signed in before the SyncAuthManager is created.
  216. CoreAccountId account_id =
  217. identity_env()
  218. ->MakePrimaryAccountAvailable("test@email.com",
  219. signin::ConsentLevel::kSync)
  220. .account_id;
  221. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  222. auth_manager->RegisterForAuthNotifications();
  223. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  224. account_id);
  225. ASSERT_EQ(auth_manager->GetLastAuthError().state(),
  226. GoogleServiceAuthError::NONE);
  227. auth_manager->ConnectionOpened();
  228. // Force an auth error by revoking the refresh token.
  229. identity_env()->RemoveRefreshTokenForPrimaryAccount();
  230. ASSERT_NE(auth_manager->GetLastAuthError().state(),
  231. GoogleServiceAuthError::NONE);
  232. // Now Sync gets turned off, e.g. because the user disabled it.
  233. auth_manager->ConnectionClosed();
  234. // Since the user is still signed in, the auth error should have remained.
  235. EXPECT_NE(auth_manager->GetLastAuthError().state(),
  236. GoogleServiceAuthError::NONE);
  237. }
  238. TEST_F(SyncAuthManagerTest, ForwardsCredentialsEvents) {
  239. // Start out already signed in before the SyncAuthManager is created.
  240. CoreAccountId account_id =
  241. identity_env()
  242. ->MakePrimaryAccountAvailable("test@email.com",
  243. signin::ConsentLevel::kSync)
  244. .account_id;
  245. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  246. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  247. EXPECT_CALL(account_state_changed, Run()).Times(0);
  248. EXPECT_CALL(credentials_changed, Run()).Times(0);
  249. std::unique_ptr<SyncAuthManager> auth_manager =
  250. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  251. auth_manager->RegisterForAuthNotifications();
  252. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  253. account_id);
  254. auth_manager->ConnectionOpened();
  255. // Once an access token is available, the callback should get run.
  256. EXPECT_CALL(credentials_changed, Run());
  257. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  258. "access_token", base::Time::Now() + base::Hours(1));
  259. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  260. // Now the refresh token gets updated. The access token will get dropped, so
  261. // this should cause another notification.
  262. EXPECT_CALL(credentials_changed, Run());
  263. identity_env()->SetRefreshTokenForPrimaryAccount();
  264. ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
  265. // Once a new token is available, there's another notification.
  266. EXPECT_CALL(credentials_changed, Run());
  267. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  268. "access_token_2", base::Time::Now() + base::Hours(1));
  269. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
  270. // Revoking the refresh token should also cause the access token to get
  271. // dropped.
  272. EXPECT_CALL(credentials_changed, Run());
  273. identity_env()->RemoveRefreshTokenForPrimaryAccount();
  274. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  275. }
  276. TEST_F(SyncAuthManagerTest, RequestsAccessTokenOnSyncStartup) {
  277. CoreAccountId account_id =
  278. identity_env()
  279. ->MakePrimaryAccountAvailable("test@email.com",
  280. signin::ConsentLevel::kSync)
  281. .account_id;
  282. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  283. auth_manager->RegisterForAuthNotifications();
  284. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  285. account_id);
  286. auth_manager->ConnectionOpened();
  287. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  288. "access_token", base::Time::Now() + base::Hours(1));
  289. EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  290. }
  291. TEST_F(SyncAuthManagerTest,
  292. RetriesAccessTokenFetchWithBackoffOnTransientFailure) {
  293. CoreAccountId account_id =
  294. identity_env()
  295. ->MakePrimaryAccountAvailable("test@email.com",
  296. signin::ConsentLevel::kSync)
  297. .account_id;
  298. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  299. auth_manager->RegisterForAuthNotifications();
  300. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  301. account_id);
  302. auth_manager->ConnectionOpened();
  303. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
  304. GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
  305. // The access token fetch should get retried (with backoff, hence no actual
  306. // request yet), without exposing an auth error.
  307. EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
  308. EXPECT_EQ(auth_manager->GetLastAuthError(),
  309. GoogleServiceAuthError::AuthErrorNone());
  310. }
  311. TEST_F(SyncAuthManagerTest,
  312. RetriesAccessTokenFetchWithoutBackoffOnceOnFirstCancelTransientFailure) {
  313. CoreAccountId account_id =
  314. identity_env()
  315. ->MakePrimaryAccountAvailable("test@email.com",
  316. signin::ConsentLevel::kSync)
  317. .account_id;
  318. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  319. auth_manager->RegisterForAuthNotifications();
  320. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  321. account_id);
  322. auth_manager->ConnectionOpened();
  323. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
  324. GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
  325. // Expect no backoff the first time the request is canceled.
  326. EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
  327. // Cancel the retry as well.
  328. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
  329. GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
  330. // Expect retry with backoff when the first retry was also canceled.
  331. EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
  332. }
  333. TEST_F(SyncAuthManagerTest,
  334. RetriesAccessTokenFetchOnFirstCancelTransientFailure) {
  335. CoreAccountId account_id =
  336. identity_env()
  337. ->MakePrimaryAccountAvailable("test@email.com",
  338. signin::ConsentLevel::kSync)
  339. .account_id;
  340. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  341. auth_manager->RegisterForAuthNotifications();
  342. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  343. account_id);
  344. auth_manager->ConnectionOpened();
  345. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
  346. GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
  347. // Expect no backoff the first time the request is canceled.
  348. EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
  349. // Retry is a success.
  350. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  351. "access_token", base::Time::Now() + base::Hours(1));
  352. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  353. // Don't expect any backoff when the retry is a success.
  354. EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
  355. }
  356. TEST_F(SyncAuthManagerTest, AbortsAccessTokenFetchOnPersistentFailure) {
  357. CoreAccountId account_id =
  358. identity_env()
  359. ->MakePrimaryAccountAvailable("test@email.com",
  360. signin::ConsentLevel::kSync)
  361. .account_id;
  362. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  363. auth_manager->RegisterForAuthNotifications();
  364. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  365. account_id);
  366. auth_manager->ConnectionOpened();
  367. GoogleServiceAuthError auth_error =
  368. GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
  369. GoogleServiceAuthError::InvalidGaiaCredentialsReason::
  370. CREDENTIALS_REJECTED_BY_SERVER);
  371. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
  372. auth_error);
  373. // Auth error should get exposed; no retry.
  374. EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
  375. EXPECT_EQ(auth_manager->GetLastAuthError(), auth_error);
  376. }
  377. TEST_F(SyncAuthManagerTest, FetchesNewAccessTokenWithBackoffOnServerError) {
  378. CoreAccountId account_id =
  379. identity_env()
  380. ->MakePrimaryAccountAvailable("test@email.com",
  381. signin::ConsentLevel::kSync)
  382. .account_id;
  383. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  384. auth_manager->RegisterForAuthNotifications();
  385. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  386. account_id);
  387. auth_manager->ConnectionOpened();
  388. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  389. "access_token", base::Time::Now() + base::Hours(1));
  390. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  391. // The server is returning AUTH_ERROR - maybe something's wrong with the
  392. // token we got.
  393. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_AUTH_ERROR);
  394. // The access token fetch should get retried (with backoff, hence no actual
  395. // request yet), without exposing an auth error.
  396. EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
  397. EXPECT_EQ(auth_manager->GetLastAuthError(),
  398. GoogleServiceAuthError::AuthErrorNone());
  399. }
  400. TEST_F(SyncAuthManagerTest, ExposesServerError) {
  401. CoreAccountId account_id =
  402. identity_env()
  403. ->MakePrimaryAccountAvailable("test@email.com",
  404. signin::ConsentLevel::kSync)
  405. .account_id;
  406. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  407. auth_manager->RegisterForAuthNotifications();
  408. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  409. account_id);
  410. auth_manager->ConnectionOpened();
  411. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  412. "access_token", base::Time::Now() + base::Hours(1));
  413. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  414. // Now a server error happens.
  415. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_SERVER_ERROR);
  416. // The error should be reported.
  417. EXPECT_NE(auth_manager->GetLastAuthError(),
  418. GoogleServiceAuthError::AuthErrorNone());
  419. // But the access token should still be there - this might just be some
  420. // non-auth-related problem with the server.
  421. EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  422. }
  423. TEST_F(SyncAuthManagerTest, ClearsServerErrorOnSyncDisable) {
  424. CoreAccountId account_id =
  425. identity_env()
  426. ->MakePrimaryAccountAvailable("test@email.com",
  427. signin::ConsentLevel::kSync)
  428. .account_id;
  429. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  430. auth_manager->RegisterForAuthNotifications();
  431. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  432. account_id);
  433. auth_manager->ConnectionOpened();
  434. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  435. "access_token", base::Time::Now() + base::Hours(1));
  436. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  437. // A server error happens.
  438. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_SERVER_ERROR);
  439. ASSERT_NE(auth_manager->GetLastAuthError(),
  440. GoogleServiceAuthError::AuthErrorNone());
  441. // Now Sync gets turned off, e.g. because the user disabled it.
  442. auth_manager->ConnectionClosed();
  443. // This should have cleared the auth error, because it was due to a server
  444. // error which is now not meaningful anymore.
  445. EXPECT_EQ(auth_manager->GetLastAuthError(),
  446. GoogleServiceAuthError::AuthErrorNone());
  447. }
  448. TEST_F(SyncAuthManagerTest, RequestsNewAccessTokenOnExpiry) {
  449. CoreAccountId account_id =
  450. identity_env()
  451. ->MakePrimaryAccountAvailable("test@email.com",
  452. signin::ConsentLevel::kSync)
  453. .account_id;
  454. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  455. auth_manager->RegisterForAuthNotifications();
  456. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  457. account_id);
  458. auth_manager->ConnectionOpened();
  459. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  460. "access_token", base::Time::Now() + base::Hours(1));
  461. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  462. // Now everything is okay for a while.
  463. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
  464. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  465. ASSERT_EQ(auth_manager->GetLastAuthError(),
  466. GoogleServiceAuthError::AuthErrorNone());
  467. // But then the token expires, resulting in an auth error from the server.
  468. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_AUTH_ERROR);
  469. // Should immediately drop the access token and fetch a new one (no backoff).
  470. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  471. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  472. "access_token_2", base::Time::Now() + base::Hours(1));
  473. EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
  474. }
  475. TEST_F(SyncAuthManagerTest, RequestsNewAccessTokenOnRefreshTokenUpdate) {
  476. CoreAccountId account_id =
  477. identity_env()
  478. ->MakePrimaryAccountAvailable("test@email.com",
  479. signin::ConsentLevel::kSync)
  480. .account_id;
  481. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  482. auth_manager->RegisterForAuthNotifications();
  483. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  484. account_id);
  485. auth_manager->ConnectionOpened();
  486. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  487. "access_token", base::Time::Now() + base::Hours(1));
  488. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  489. // Now everything is okay for a while.
  490. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
  491. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  492. ASSERT_EQ(auth_manager->GetLastAuthError(),
  493. GoogleServiceAuthError::AuthErrorNone());
  494. // But then the refresh token changes.
  495. identity_env()->SetRefreshTokenForPrimaryAccount();
  496. // Should immediately drop the access token and fetch a new one (no backoff).
  497. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  498. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  499. "access_token_2", base::Time::Now() + base::Hours(1));
  500. EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
  501. }
  502. TEST_F(SyncAuthManagerTest, DoesNotRequestAccessTokenAutonomously) {
  503. CoreAccountId account_id =
  504. identity_env()
  505. ->MakePrimaryAccountAvailable("test@email.com",
  506. signin::ConsentLevel::kSync)
  507. .account_id;
  508. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  509. auth_manager->RegisterForAuthNotifications();
  510. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  511. account_id);
  512. // Do *not* call ConnectionStatusChanged here (which is what usually kicks off
  513. // the token fetch).
  514. // Now the refresh token gets updated. If we already had an access token
  515. // before, then this should trigger a new fetch. But since that initial fetch
  516. // never happened (e.g. because Sync is turned off), this should do nothing.
  517. base::MockCallback<base::OnceClosure> access_token_requested;
  518. EXPECT_CALL(access_token_requested, Run()).Times(0);
  519. identity_env()->SetCallbackForNextAccessTokenRequest(
  520. access_token_requested.Get());
  521. identity_env()->SetRefreshTokenForPrimaryAccount();
  522. // Make sure no access token request was sent. Since the request goes through
  523. // posted tasks, we have to spin the message loop.
  524. base::RunLoop().RunUntilIdle();
  525. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  526. }
  527. TEST_F(SyncAuthManagerTest, ClearsCredentialsOnRefreshTokenRemoval) {
  528. CoreAccountId account_id =
  529. identity_env()
  530. ->MakePrimaryAccountAvailable("test@email.com",
  531. signin::ConsentLevel::kSync)
  532. .account_id;
  533. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  534. auth_manager->RegisterForAuthNotifications();
  535. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  536. account_id);
  537. auth_manager->ConnectionOpened();
  538. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  539. "access_token", base::Time::Now() + base::Hours(1));
  540. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  541. // Now everything is okay for a while.
  542. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
  543. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  544. ASSERT_EQ(auth_manager->GetLastAuthError(),
  545. GoogleServiceAuthError::AuthErrorNone());
  546. // But then the refresh token gets revoked. No new access token should get
  547. // requested due to this.
  548. base::MockCallback<base::OnceClosure> access_token_requested;
  549. EXPECT_CALL(access_token_requested, Run()).Times(0);
  550. identity_env()->SetCallbackForNextAccessTokenRequest(
  551. access_token_requested.Get());
  552. identity_env()->RemoveRefreshTokenForPrimaryAccount();
  553. // Should immediately drop the access token and expose an auth error.
  554. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  555. EXPECT_NE(auth_manager->GetLastAuthError(),
  556. GoogleServiceAuthError::AuthErrorNone());
  557. // No new access token should have been requested. Since the request goes
  558. // through posted tasks, we have to spin the message loop.
  559. base::RunLoop().RunUntilIdle();
  560. }
  561. TEST_F(SyncAuthManagerTest, ClearsCredentialsOnInvalidRefreshToken) {
  562. CoreAccountId account_id =
  563. identity_env()
  564. ->MakePrimaryAccountAvailable("test@email.com",
  565. signin::ConsentLevel::kSync)
  566. .account_id;
  567. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  568. auth_manager->RegisterForAuthNotifications();
  569. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  570. account_id);
  571. auth_manager->ConnectionOpened();
  572. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  573. "access_token", base::Time::Now() + base::Hours(1));
  574. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  575. // Now everything is okay for a while.
  576. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
  577. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  578. ASSERT_EQ(auth_manager->GetLastAuthError(),
  579. GoogleServiceAuthError::AuthErrorNone());
  580. // But now an invalid refresh token gets set, i.e. we enter the "Sync paused"
  581. // state. No new access token should get requested due to this.
  582. base::MockCallback<base::OnceClosure> access_token_requested;
  583. EXPECT_CALL(access_token_requested, Run()).Times(0);
  584. identity_env()->SetCallbackForNextAccessTokenRequest(
  585. access_token_requested.Get());
  586. identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
  587. // Should immediately drop the access token and expose a special auth error.
  588. EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
  589. GoogleServiceAuthError invalid_token_error =
  590. GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
  591. GoogleServiceAuthError::InvalidGaiaCredentialsReason::
  592. CREDENTIALS_REJECTED_BY_CLIENT);
  593. EXPECT_EQ(auth_manager->GetLastAuthError(), invalid_token_error);
  594. EXPECT_TRUE(auth_manager->IsSyncPaused());
  595. // No new access token should have been requested. Since the request goes
  596. // through posted tasks, we have to spin the message loop.
  597. base::RunLoop().RunUntilIdle();
  598. }
  599. TEST_F(SyncAuthManagerTest,
  600. RequestsAccessTokenWhenInvalidRefreshTokenResolved) {
  601. CoreAccountId account_id =
  602. identity_env()
  603. ->MakePrimaryAccountAvailable("test@email.com",
  604. signin::ConsentLevel::kSync)
  605. .account_id;
  606. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  607. auth_manager->RegisterForAuthNotifications();
  608. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  609. account_id);
  610. // Sync starts up normally.
  611. auth_manager->ConnectionOpened();
  612. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  613. "access_token", base::Time::Now() + base::Hours(1));
  614. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  615. auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
  616. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
  617. ASSERT_EQ(auth_manager->GetLastAuthError(),
  618. GoogleServiceAuthError::AuthErrorNone());
  619. // But now an invalid refresh token gets set, i.e. we enter the "Sync paused"
  620. // state.
  621. identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
  622. ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
  623. ASSERT_TRUE(auth_manager->IsSyncPaused());
  624. // Once the user signs in again and we have a valid refresh token, we should
  625. // also request a new access token.
  626. identity_env()->SetRefreshTokenForPrimaryAccount();
  627. identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
  628. "access_token_2", base::Time::Now() + base::Hours(1));
  629. ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
  630. }
  631. TEST_F(SyncAuthManagerTest, DoesNotRequestAccessTokenIfSyncInactive) {
  632. CoreAccountId account_id =
  633. identity_env()
  634. ->MakePrimaryAccountAvailable("test@email.com",
  635. signin::ConsentLevel::kSync)
  636. .account_id;
  637. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  638. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  639. EXPECT_CALL(account_state_changed, Run()).Times(0);
  640. EXPECT_CALL(credentials_changed, Run()).Times(0);
  641. std::unique_ptr<SyncAuthManager> auth_manager =
  642. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  643. auth_manager->RegisterForAuthNotifications();
  644. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  645. account_id);
  646. // Sync is *not* enabled; in particular we don't call ConnectionOpened().
  647. // An invalid refresh token gets set, i.e. we enter the "Sync paused" state
  648. // (only from SyncAuthManager's point of view - Sync as a whole is still
  649. // disabled).
  650. EXPECT_CALL(credentials_changed, Run());
  651. identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
  652. ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
  653. ASSERT_TRUE(auth_manager->IsSyncPaused());
  654. // Once the user signs in again and we have a valid refresh token, we should
  655. // *not* request a new access token, since Sync isn't active.
  656. base::MockCallback<base::OnceClosure> access_token_requested;
  657. EXPECT_CALL(access_token_requested, Run()).Times(0);
  658. identity_env()->SetCallbackForNextAccessTokenRequest(
  659. access_token_requested.Get());
  660. // This *should* notify about changed credentials though, so that the
  661. // SyncService can decide to start syncing.
  662. EXPECT_CALL(credentials_changed, Run());
  663. identity_env()->SetRefreshTokenForPrimaryAccount();
  664. ASSERT_FALSE(auth_manager->IsSyncPaused());
  665. // Since the access token request goes through posted tasks, we have to spin
  666. // the message loop to make sure it didn't happen.
  667. base::RunLoop().RunUntilIdle();
  668. }
  669. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
  670. // Primary account with no sync consent is not supported on Android and iOS.
  671. TEST_F(SyncAuthManagerTest, PrimaryAccountWithNoSyncConsent) {
  672. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  673. auth_manager->RegisterForAuthNotifications();
  674. ASSERT_TRUE(
  675. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  676. // Make a primary account with no sync consent available.
  677. AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
  678. "test@email.com", signin::ConsentLevel::kSignin);
  679. // Since unconsented primary account support is enabled, SyncAuthManager
  680. // should have picked up this account.
  681. EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  682. account_info.account_id);
  683. }
  684. #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
  685. #if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
  686. // Primary account with no sync consent is not supported on Android and iOS.
  687. // On crOS the unconsented primary account can't be changed or removed, but can
  688. // be granted sync consent.
  689. TEST_F(SyncAuthManagerTest, PicksNewPrimaryAccountWithSyncConsent) {
  690. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  691. auth_manager->RegisterForAuthNotifications();
  692. ASSERT_TRUE(
  693. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  694. // Make a primary account with no sync consent available.
  695. AccountInfo unconsented_primary_account_info =
  696. identity_env()->MakePrimaryAccountAvailable(
  697. "test@email.com", signin::ConsentLevel::kSignin);
  698. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  699. unconsented_primary_account_info.account_id);
  700. // Once a primary account with sync consent becomes available, the unconsented
  701. // primary account should be overridden.
  702. AccountInfo primary_account_info =
  703. identity_env()->MakePrimaryAccountAvailable("primary@email.com",
  704. signin::ConsentLevel::kSync);
  705. EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  706. primary_account_info.account_id);
  707. }
  708. TEST_F(SyncAuthManagerTest,
  709. DropsAccountWhenPrimaryAccountWithNoSyncConsentGoesAway) {
  710. std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
  711. auth_manager->RegisterForAuthNotifications();
  712. // Make a primary account with no sync consent available.
  713. AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
  714. "test@email.com", signin::ConsentLevel::kSignin);
  715. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  716. account_info.account_id);
  717. identity_env()->ClearPrimaryAccount();
  718. EXPECT_TRUE(
  719. auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
  720. }
  721. #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) &&
  722. // !BUILDFLAG(IS_IOS)
  723. TEST_F(SyncAuthManagerTest, DetectsInvalidRefreshTokenAtStartup) {
  724. // There is a primary account, but it has an invalid refresh token (with a
  725. // persistent auth error).
  726. CoreAccountId account_id =
  727. identity_env()
  728. ->MakePrimaryAccountAvailable("test@email.com",
  729. signin::ConsentLevel::kSync)
  730. .account_id;
  731. identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
  732. // On initialization, SyncAuthManager should pick up the auth error. This
  733. // should not result in a notification.
  734. base::MockCallback<AccountStateChangedCallback> account_state_changed;
  735. base::MockCallback<CredentialsChangedCallback> credentials_changed;
  736. EXPECT_CALL(account_state_changed, Run()).Times(0);
  737. EXPECT_CALL(credentials_changed, Run()).Times(0);
  738. std::unique_ptr<SyncAuthManager> auth_manager =
  739. CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
  740. auth_manager->RegisterForAuthNotifications();
  741. ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
  742. account_id);
  743. EXPECT_TRUE(auth_manager->GetLastAuthError().IsPersistentError());
  744. }
  745. } // namespace
  746. } // namespace syncer