oauth2_mint_token_flow_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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 OAuth2MintTokenFlow.
  6. #include "google_apis/gaia/oauth2_mint_token_flow.h"
  7. #include <memory>
  8. #include <set>
  9. #include <string>
  10. #include <vector>
  11. #include "base/json/json_reader.h"
  12. #include "base/strings/utf_string_conversions.h"
  13. #include "base/test/metrics/histogram_tester.h"
  14. #include "base/values.h"
  15. #include "google_apis/gaia/google_service_auth_error.h"
  16. #include "google_apis/gaia/oauth2_access_token_fetcher.h"
  17. #include "net/base/net_errors.h"
  18. #include "net/cookies/canonical_cookie.h"
  19. #include "services/network/public/mojom/url_response_head.mojom.h"
  20. #include "services/network/test/test_utils.h"
  21. #include "testing/gmock/include/gmock/gmock.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/abseil-cpp/absl/types/optional.h"
  24. using testing::_;
  25. using testing::ByRef;
  26. using testing::Eq;
  27. using testing::StrictMock;
  28. namespace {
  29. static const char kValidTokenResponse[] =
  30. "{"
  31. " \"token\": \"at1\","
  32. " \"issueAdvice\": \"Auto\","
  33. " \"expiresIn\": \"3600\","
  34. " \"grantedScopes\": \"http://scope1 http://scope2\""
  35. "}";
  36. static const char kTokenResponseNoGrantedScopes[] =
  37. "{"
  38. " \"token\": \"at1\","
  39. " \"issueAdvice\": \"Auto\","
  40. " \"expiresIn\": \"3600\""
  41. "}";
  42. static const char kTokenResponseEmptyGrantedScopes[] =
  43. "{"
  44. " \"token\": \"at1\","
  45. " \"issueAdvice\": \"Auto\","
  46. " \"expiresIn\": \"3600\","
  47. " \"grantedScopes\": \"\""
  48. "}";
  49. static const char kTokenResponseNoAccessToken[] =
  50. "{"
  51. " \"issueAdvice\": \"Auto\""
  52. "}";
  53. static const char kValidRemoteConsentResponse[] =
  54. "{"
  55. " \"issueAdvice\": \"remoteConsent\","
  56. " \"resolutionData\": {"
  57. " \"resolutionApproach\": \"resolveInBrowser\","
  58. " \"resolutionUrl\": \"https://test.com/consent?param=value\","
  59. " \"browserCookies\": ["
  60. " {"
  61. " \"name\": \"test_name\","
  62. " \"value\": \"test_value\","
  63. " \"domain\": \"test.com\","
  64. " \"path\": \"/\","
  65. " \"maxAgeSeconds\": \"60\","
  66. " \"isSecure\": false,"
  67. " \"isHttpOnly\": true,"
  68. " \"sameSite\": \"none\""
  69. " },"
  70. " {"
  71. " \"name\": \"test_name2\","
  72. " \"value\": \"test_value2\","
  73. " \"domain\": \"test.com\""
  74. " }"
  75. " ]"
  76. " }"
  77. "}";
  78. static const char kInvalidRemoteConsentResponse[] =
  79. "{"
  80. " \"issueAdvice\": \"remoteConsent\","
  81. " \"resolutionData\": {"
  82. " \"resolutionApproach\": \"resolveInBrowser\""
  83. " }"
  84. "}";
  85. std::vector<std::string> CreateTestScopes() {
  86. std::vector<std::string> scopes;
  87. scopes.push_back("http://scope1");
  88. scopes.push_back("http://scope2");
  89. return scopes;
  90. }
  91. static RemoteConsentResolutionData CreateRemoteConsentResolutionData() {
  92. RemoteConsentResolutionData resolution_data;
  93. resolution_data.url = GURL("https://test.com/consent?param=value");
  94. resolution_data.cookies.push_back(
  95. *net::CanonicalCookie::CreateSanitizedCookie(
  96. resolution_data.url, "test_name", "test_value", "test.com", "/",
  97. base::Time(), base::Time(), base::Time(), false, true,
  98. net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_DEFAULT, false,
  99. absl::nullopt));
  100. resolution_data.cookies.push_back(
  101. *net::CanonicalCookie::CreateSanitizedCookie(
  102. resolution_data.url, "test_name2", "test_value2", "test.com", "/",
  103. base::Time(), base::Time(), base::Time(), false, false,
  104. net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_DEFAULT, false,
  105. absl::nullopt));
  106. return resolution_data;
  107. }
  108. class MockDelegate : public OAuth2MintTokenFlow::Delegate {
  109. public:
  110. MockDelegate() {}
  111. ~MockDelegate() override {}
  112. MOCK_METHOD3(OnMintTokenSuccess,
  113. void(const std::string& access_token,
  114. const std::set<std::string>& granted_scopes,
  115. int time_to_live));
  116. MOCK_METHOD1(OnRemoteConsentSuccess,
  117. void(const RemoteConsentResolutionData& resolution_data));
  118. MOCK_METHOD1(OnMintTokenFailure,
  119. void(const GoogleServiceAuthError& error));
  120. };
  121. class MockMintTokenFlow : public OAuth2MintTokenFlow {
  122. public:
  123. explicit MockMintTokenFlow(MockDelegate* delegate,
  124. const OAuth2MintTokenFlow::Parameters& parameters)
  125. : OAuth2MintTokenFlow(delegate, parameters) {}
  126. ~MockMintTokenFlow() override {}
  127. MOCK_METHOD0(CreateAccessTokenFetcher,
  128. std::unique_ptr<OAuth2AccessTokenFetcher>());
  129. };
  130. } // namespace
  131. class OAuth2MintTokenFlowTest : public testing::Test {
  132. public:
  133. OAuth2MintTokenFlowTest()
  134. : head_200_(network::CreateURLResponseHead(net::HTTP_OK)) {}
  135. ~OAuth2MintTokenFlowTest() override {}
  136. protected:
  137. const network::mojom::URLResponseHeadPtr head_200_;
  138. void CreateFlow(OAuth2MintTokenFlow::Mode mode) {
  139. return CreateFlow(&delegate_, mode, false, "", "", "");
  140. }
  141. void CreateFlowWithEnableGranularPermissions(
  142. const bool enable_granular_permissions) {
  143. return CreateFlow(&delegate_, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE,
  144. enable_granular_permissions, "", "", "");
  145. }
  146. void CreateFlowWithDeviceId(const std::string& device_id) {
  147. return CreateFlow(&delegate_, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE, false,
  148. device_id, "", "");
  149. }
  150. void CreateFlowWithSelectedUserId(const std::string& selected_user_id) {
  151. return CreateFlow(&delegate_, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE, false,
  152. "", selected_user_id, "");
  153. }
  154. void CreateFlowWithConsentResult(const std::string& consent_result) {
  155. return CreateFlow(&delegate_, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE,
  156. false, "", "", consent_result);
  157. }
  158. void CreateFlow(MockDelegate* delegate,
  159. OAuth2MintTokenFlow::Mode mode,
  160. const bool enable_granular_permissions,
  161. const std::string& device_id,
  162. const std::string& selected_user_id,
  163. const std::string& consent_result) {
  164. std::string ext_id = "ext1";
  165. std::string client_id = "client1";
  166. std::string version = "test_version";
  167. std::string channel = "test_channel";
  168. std::vector<std::string> scopes(CreateTestScopes());
  169. flow_ = std::make_unique<MockMintTokenFlow>(
  170. delegate,
  171. OAuth2MintTokenFlow::Parameters(
  172. ext_id, client_id, scopes, enable_granular_permissions, device_id,
  173. selected_user_id, consent_result, version, channel, mode));
  174. }
  175. void ProcessApiCallSuccess(const network::mojom::URLResponseHead* head,
  176. std::unique_ptr<std::string> body) {
  177. flow_->ProcessApiCallSuccess(head, std::move(body));
  178. }
  179. void ProcessApiCallFailure(int net_error,
  180. const network::mojom::URLResponseHead* head,
  181. std::unique_ptr<std::string> body) {
  182. flow_->ProcessApiCallFailure(net_error, head, std::move(body));
  183. }
  184. // Helper to parse the given string to base::Value.
  185. static std::unique_ptr<base::Value> ParseJson(const std::string& str) {
  186. absl::optional<base::Value> value = base::JSONReader::Read(str);
  187. EXPECT_TRUE(value.has_value());
  188. EXPECT_TRUE(value->is_dict());
  189. return std::make_unique<base::Value>(std::move(*value));
  190. }
  191. std::unique_ptr<MockMintTokenFlow> flow_;
  192. StrictMock<MockDelegate> delegate_;
  193. base::HistogramTester histogram_tester_;
  194. };
  195. TEST_F(OAuth2MintTokenFlowTest, CreateApiCallBody) {
  196. { // Issue advice mode.
  197. CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
  198. std::string body = flow_->CreateApiCallBody();
  199. std::string expected_body(
  200. "force=false"
  201. "&response_type=none"
  202. "&scope=http://scope1+http://scope2"
  203. "&enable_granular_permissions=false"
  204. "&client_id=client1"
  205. "&origin=ext1"
  206. "&lib_ver=test_version"
  207. "&release_channel=test_channel");
  208. EXPECT_EQ(expected_body, body);
  209. }
  210. { // Record grant mode.
  211. CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT);
  212. std::string body = flow_->CreateApiCallBody();
  213. std::string expected_body(
  214. "force=true"
  215. "&response_type=none"
  216. "&scope=http://scope1+http://scope2"
  217. "&enable_granular_permissions=false"
  218. "&client_id=client1"
  219. "&origin=ext1"
  220. "&lib_ver=test_version"
  221. "&release_channel=test_channel");
  222. EXPECT_EQ(expected_body, body);
  223. }
  224. { // Mint token no force mode.
  225. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  226. std::string body = flow_->CreateApiCallBody();
  227. std::string expected_body(
  228. "force=false"
  229. "&response_type=token"
  230. "&scope=http://scope1+http://scope2"
  231. "&enable_granular_permissions=false"
  232. "&client_id=client1"
  233. "&origin=ext1"
  234. "&lib_ver=test_version"
  235. "&release_channel=test_channel");
  236. EXPECT_EQ(expected_body, body);
  237. }
  238. { // Mint token force mode.
  239. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
  240. std::string body = flow_->CreateApiCallBody();
  241. std::string expected_body(
  242. "force=true"
  243. "&response_type=token"
  244. "&scope=http://scope1+http://scope2"
  245. "&enable_granular_permissions=false"
  246. "&client_id=client1"
  247. "&origin=ext1"
  248. "&lib_ver=test_version"
  249. "&release_channel=test_channel");
  250. EXPECT_EQ(expected_body, body);
  251. }
  252. { // Mint token with granular permissions enabled.
  253. CreateFlowWithEnableGranularPermissions(true);
  254. std::string body = flow_->CreateApiCallBody();
  255. std::string expected_body(
  256. "force=false"
  257. "&response_type=none"
  258. "&scope=http://scope1+http://scope2"
  259. "&enable_granular_permissions=true"
  260. "&client_id=client1"
  261. "&origin=ext1"
  262. "&lib_ver=test_version"
  263. "&release_channel=test_channel");
  264. EXPECT_EQ(expected_body, body);
  265. }
  266. { // Mint token with device_id.
  267. CreateFlowWithDeviceId("device_id1");
  268. std::string body = flow_->CreateApiCallBody();
  269. std::string expected_body(
  270. "force=false"
  271. "&response_type=none"
  272. "&scope=http://scope1+http://scope2"
  273. "&enable_granular_permissions=false"
  274. "&client_id=client1"
  275. "&origin=ext1"
  276. "&lib_ver=test_version"
  277. "&release_channel=test_channel"
  278. "&device_id=device_id1"
  279. "&device_type=chrome");
  280. EXPECT_EQ(expected_body, body);
  281. }
  282. {
  283. CreateFlowWithSelectedUserId("user_id1");
  284. std::string body = flow_->CreateApiCallBody();
  285. std::string expected_body(
  286. "force=false"
  287. "&response_type=none"
  288. "&scope=http://scope1+http://scope2"
  289. "&enable_granular_permissions=false"
  290. "&client_id=client1"
  291. "&origin=ext1"
  292. "&lib_ver=test_version"
  293. "&release_channel=test_channel"
  294. "&selected_user_id=user_id1");
  295. EXPECT_EQ(expected_body, body);
  296. }
  297. {
  298. CreateFlowWithConsentResult("consent1");
  299. std::string body = flow_->CreateApiCallBody();
  300. std::string expected_body(
  301. "force=false"
  302. "&response_type=token"
  303. "&scope=http://scope1+http://scope2"
  304. "&enable_granular_permissions=false"
  305. "&client_id=client1"
  306. "&origin=ext1"
  307. "&lib_ver=test_version"
  308. "&release_channel=test_channel"
  309. "&consent_result=consent1");
  310. EXPECT_EQ(expected_body, body);
  311. }
  312. }
  313. TEST_F(OAuth2MintTokenFlowTest, ParseMintTokenResponse) {
  314. { // Access token missing.
  315. std::unique_ptr<base::Value> json = ParseJson(kTokenResponseNoAccessToken);
  316. std::string access_token;
  317. std::set<std::string> granted_scopes;
  318. int time_to_live;
  319. EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
  320. json.get(), &access_token, &granted_scopes, &time_to_live));
  321. EXPECT_TRUE(access_token.empty());
  322. }
  323. { // Granted scopes parameter is there but is empty.
  324. std::unique_ptr<base::Value> json =
  325. ParseJson(kTokenResponseEmptyGrantedScopes);
  326. std::string access_token;
  327. std::set<std::string> granted_scopes;
  328. int time_to_live;
  329. EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
  330. json.get(), &access_token, &granted_scopes, &time_to_live));
  331. EXPECT_TRUE(granted_scopes.empty());
  332. }
  333. { // Granted scopes parameter is missing.
  334. std::unique_ptr<base::Value> json =
  335. ParseJson(kTokenResponseNoGrantedScopes);
  336. std::string access_token;
  337. std::set<std::string> granted_scopes;
  338. int time_to_live;
  339. EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
  340. json.get(), &access_token, &granted_scopes, &time_to_live));
  341. EXPECT_TRUE(granted_scopes.empty());
  342. }
  343. { // All good.
  344. std::unique_ptr<base::Value> json = ParseJson(kValidTokenResponse);
  345. std::string access_token;
  346. std::set<std::string> granted_scopes;
  347. int time_to_live;
  348. EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(
  349. json.get(), &access_token, &granted_scopes, &time_to_live));
  350. EXPECT_EQ("at1", access_token);
  351. EXPECT_EQ(3600, time_to_live);
  352. EXPECT_EQ(std::set<std::string>({"http://scope1", "http://scope2"}),
  353. granted_scopes);
  354. }
  355. }
  356. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse) {
  357. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  358. RemoteConsentResolutionData resolution_data;
  359. ASSERT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  360. json.get(), &resolution_data));
  361. RemoteConsentResolutionData expected_resolution_data =
  362. CreateRemoteConsentResolutionData();
  363. EXPECT_EQ(resolution_data, expected_resolution_data);
  364. }
  365. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_EmptyCookies) {
  366. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  367. json->FindListPath("resolutionData.browserCookies")->ClearList();
  368. RemoteConsentResolutionData resolution_data;
  369. EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  370. json.get(), &resolution_data));
  371. RemoteConsentResolutionData expected_resolution_data =
  372. CreateRemoteConsentResolutionData();
  373. expected_resolution_data.cookies.clear();
  374. EXPECT_EQ(resolution_data, expected_resolution_data);
  375. }
  376. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoCookies) {
  377. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  378. EXPECT_TRUE(json->RemovePath("resolutionData.browserCookies"));
  379. RemoteConsentResolutionData resolution_data;
  380. EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  381. json.get(), &resolution_data));
  382. RemoteConsentResolutionData expected_resolution_data =
  383. CreateRemoteConsentResolutionData();
  384. expected_resolution_data.cookies.clear();
  385. EXPECT_EQ(resolution_data, expected_resolution_data);
  386. }
  387. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoResolutionData) {
  388. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  389. EXPECT_TRUE(json->RemoveKey("resolutionData"));
  390. RemoteConsentResolutionData resolution_data;
  391. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  392. json.get(), &resolution_data));
  393. EXPECT_TRUE(resolution_data.url.is_empty());
  394. EXPECT_TRUE(resolution_data.cookies.empty());
  395. }
  396. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoUrl) {
  397. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  398. EXPECT_TRUE(json->RemovePath("resolutionData.resolutionUrl"));
  399. RemoteConsentResolutionData resolution_data;
  400. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  401. json.get(), &resolution_data));
  402. EXPECT_TRUE(resolution_data.url.is_empty());
  403. EXPECT_TRUE(resolution_data.cookies.empty());
  404. }
  405. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadUrl) {
  406. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  407. EXPECT_TRUE(json->SetStringPath("resolutionData.resolutionUrl", "not-a-url"));
  408. RemoteConsentResolutionData resolution_data;
  409. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  410. json.get(), &resolution_data));
  411. EXPECT_TRUE(resolution_data.url.is_empty());
  412. EXPECT_TRUE(resolution_data.cookies.empty());
  413. }
  414. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoApproach) {
  415. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  416. EXPECT_TRUE(json->RemovePath("resolutionData.resolutionApproach"));
  417. RemoteConsentResolutionData resolution_data;
  418. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  419. json.get(), &resolution_data));
  420. EXPECT_TRUE(resolution_data.url.is_empty());
  421. EXPECT_TRUE(resolution_data.cookies.empty());
  422. }
  423. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadApproach) {
  424. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  425. EXPECT_TRUE(
  426. json->SetStringPath("resolutionData.resolutionApproach", "badApproach"));
  427. RemoteConsentResolutionData resolution_data;
  428. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  429. json.get(), &resolution_data));
  430. EXPECT_TRUE(resolution_data.url.is_empty());
  431. EXPECT_TRUE(resolution_data.cookies.empty());
  432. }
  433. TEST_F(OAuth2MintTokenFlowTest,
  434. ParseRemoteConsentResponse_BadCookie_MissingRequiredField) {
  435. static const char* kRequiredFields[] = {"name", "value", "domain"};
  436. for (const auto* required_field : kRequiredFields) {
  437. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  438. base::Value::ListView cookies =
  439. json->FindListPath("resolutionData.browserCookies")
  440. ->GetListDeprecated();
  441. EXPECT_TRUE(cookies[0].RemoveKey(required_field));
  442. RemoteConsentResolutionData resolution_data;
  443. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  444. json.get(), &resolution_data));
  445. EXPECT_TRUE(resolution_data.url.is_empty());
  446. EXPECT_TRUE(resolution_data.cookies.empty());
  447. }
  448. }
  449. TEST_F(OAuth2MintTokenFlowTest,
  450. ParseRemoteConsentResponse_MissingCookieOptionalField) {
  451. static const char* kOptionalFields[] = {"path", "maxAgeSeconds", "isSecure",
  452. "isHttpOnly", "sameSite"};
  453. for (const auto* optional_field : kOptionalFields) {
  454. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  455. base::Value::ListView cookies =
  456. json->FindListPath("resolutionData.browserCookies")
  457. ->GetListDeprecated();
  458. EXPECT_TRUE(cookies[0].RemoveKey(optional_field));
  459. RemoteConsentResolutionData resolution_data;
  460. EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  461. json.get(), &resolution_data));
  462. RemoteConsentResolutionData expected_resolution_data =
  463. CreateRemoteConsentResolutionData();
  464. EXPECT_EQ(resolution_data, expected_resolution_data);
  465. }
  466. }
  467. TEST_F(OAuth2MintTokenFlowTest,
  468. ParseRemoteConsentResponse_BadCookie_BadMaxAge) {
  469. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  470. base::Value::ListView cookies =
  471. json->FindListPath("resolutionData.browserCookies")->GetListDeprecated();
  472. cookies[0].SetStringKey("maxAgeSeconds", "not-a-number");
  473. RemoteConsentResolutionData resolution_data;
  474. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  475. json.get(), &resolution_data));
  476. EXPECT_TRUE(resolution_data.url.is_empty());
  477. EXPECT_TRUE(resolution_data.cookies.empty());
  478. }
  479. TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadCookieList) {
  480. std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
  481. json->FindListPath("resolutionData.browserCookies")->Append(42);
  482. RemoteConsentResolutionData resolution_data;
  483. EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
  484. json.get(), &resolution_data));
  485. EXPECT_TRUE(resolution_data.url.is_empty());
  486. EXPECT_TRUE(resolution_data.cookies.empty());
  487. }
  488. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_NoBody) {
  489. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  490. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  491. ProcessApiCallSuccess(head_200_.get(), nullptr);
  492. histogram_tester_.ExpectUniqueSample(
  493. kOAuth2MintTokenApiCallResultHistogram,
  494. OAuth2MintTokenApiCallResult::kParseJsonFailure, 1);
  495. }
  496. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_BadJson) {
  497. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  498. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  499. ProcessApiCallSuccess(head_200_.get(), std::make_unique<std::string>("foo"));
  500. histogram_tester_.ExpectUniqueSample(
  501. kOAuth2MintTokenApiCallResultHistogram,
  502. OAuth2MintTokenApiCallResult::kParseJsonFailure, 1);
  503. }
  504. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_NoAccessToken) {
  505. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  506. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  507. ProcessApiCallSuccess(head_200_.get(), std::make_unique<std::string>(
  508. kTokenResponseNoAccessToken));
  509. histogram_tester_.ExpectUniqueSample(
  510. kOAuth2MintTokenApiCallResultHistogram,
  511. OAuth2MintTokenApiCallResult::kParseMintTokenFailure, 1);
  512. }
  513. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_GoodToken) {
  514. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  515. std::set<std::string> granted_scopes = {"http://scope1", "http://scope2"};
  516. EXPECT_CALL(delegate_, OnMintTokenSuccess("at1", granted_scopes, 3600));
  517. ProcessApiCallSuccess(head_200_.get(),
  518. std::make_unique<std::string>(kValidTokenResponse));
  519. histogram_tester_.ExpectUniqueSample(
  520. kOAuth2MintTokenApiCallResultHistogram,
  521. OAuth2MintTokenApiCallResult::kMintTokenSuccess, 1);
  522. }
  523. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_GoodRemoteConsent) {
  524. CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
  525. RemoteConsentResolutionData resolution_data =
  526. CreateRemoteConsentResolutionData();
  527. EXPECT_CALL(delegate_, OnRemoteConsentSuccess(Eq(ByRef(resolution_data))));
  528. ProcessApiCallSuccess(head_200_.get(), std::make_unique<std::string>(
  529. kValidRemoteConsentResponse));
  530. histogram_tester_.ExpectUniqueSample(
  531. kOAuth2MintTokenApiCallResultHistogram,
  532. OAuth2MintTokenApiCallResult::kRemoteConsentSuccess, 1);
  533. }
  534. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_RemoteConsentFailure) {
  535. CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
  536. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  537. ProcessApiCallSuccess(head_200_.get(), std::make_unique<std::string>(
  538. kInvalidRemoteConsentResponse));
  539. histogram_tester_.ExpectUniqueSample(
  540. kOAuth2MintTokenApiCallResultHistogram,
  541. OAuth2MintTokenApiCallResult::kParseRemoteConsentFailure, 1);
  542. }
  543. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallFailure_NullDelegate) {
  544. network::mojom::URLResponseHead head;
  545. CreateFlow(nullptr, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE, false, "",
  546. "", "");
  547. ProcessApiCallFailure(net::ERR_FAILED, &head, nullptr);
  548. histogram_tester_.ExpectUniqueSample(
  549. kOAuth2MintTokenApiCallResultHistogram,
  550. OAuth2MintTokenApiCallResult::kApiCallFailure, 1);
  551. }
  552. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallFailure_NonNullDelegate) {
  553. network::mojom::URLResponseHead head;
  554. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  555. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  556. ProcessApiCallFailure(net::ERR_FAILED, &head, nullptr);
  557. histogram_tester_.ExpectUniqueSample(
  558. kOAuth2MintTokenApiCallResultHistogram,
  559. OAuth2MintTokenApiCallResult::kApiCallFailure, 1);
  560. }
  561. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallFailure_NullHead) {
  562. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  563. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  564. ProcessApiCallFailure(net::ERR_FAILED, nullptr, nullptr);
  565. histogram_tester_.ExpectUniqueSample(
  566. kOAuth2MintTokenApiCallResultHistogram,
  567. OAuth2MintTokenApiCallResult::kApiCallFailure, 1);
  568. }
  569. TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess_NoGrantedScopes) {
  570. CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
  571. std::set<std::string> granted_scopes = {"http://scope1", "http://scope2"};
  572. EXPECT_CALL(delegate_, OnMintTokenFailure(_));
  573. ProcessApiCallSuccess(head_200_.get(), std::make_unique<std::string>(
  574. kTokenResponseNoGrantedScopes));
  575. histogram_tester_.ExpectUniqueSample(
  576. kOAuth2MintTokenApiCallResultHistogram,
  577. OAuth2MintTokenApiCallResult::kParseMintTokenFailure, 1);
  578. }