• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/device_bound_sessions/registration_fetcher_param.h"
6 
7 #include <optional>
8 
9 #include "base/strings/strcat.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/test/bind.h"
12 #include "base/test/task_environment.h"
13 #include "crypto/signature_verifier.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/structured_headers.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace net::device_bound_sessions {
20 
21 namespace {
22 
23 constexpr char kRegistrationHeader[] = "Sec-Session-Registration";
24 using crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256;
25 using crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256;
26 using ::testing::UnorderedElementsAre;
27 
CreateHeaders(std::optional<std::string> path,std::optional<std::string> algs,std::optional<std::string> challenge,std::optional<std::string> authorization,scoped_refptr<net::HttpResponseHeaders> headers=nullptr)28 scoped_refptr<net::HttpResponseHeaders> CreateHeaders(
29     std::optional<std::string> path,
30     std::optional<std::string> algs,
31     std::optional<std::string> challenge,
32     std::optional<std::string> authorization,
33     scoped_refptr<net::HttpResponseHeaders> headers = nullptr) {
34   const std::string algs_string = (algs && !algs->empty()) ? *algs : "()";
35   const std::string path_string =
36       path ? base::StrCat({";path=\"", *path, "\""}) : "";
37   const std::string challenge_string =
38       challenge ? base::StrCat({";challenge=\"", *challenge, "\""}) : "";
39   std::string authorization_string;
40   if (authorization) {
41     authorization_string =
42         base::StrCat({";authorization=\"", *authorization, "\""});
43   }
44   const std::string full_string = base::StrCat(
45       {algs_string, path_string, challenge_string, authorization_string});
46 
47   if (!headers) {
48     headers = HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
49   }
50   headers->AddHeader(kRegistrationHeader, full_string);
51 
52   return headers;
53 }
54 
TEST(RegistrationFetcherParamTest,BasicValid)55 TEST(RegistrationFetcherParamTest, BasicValid) {
56   const GURL registration_request("https://www.example.com/registration");
57   scoped_refptr<net::HttpResponseHeaders> response_headers =
58       CreateHeaders("startsession", "(ES256 RS256)", "c1", "auth");
59   std::vector<RegistrationFetcherParam> params =
60       RegistrationFetcherParam::CreateIfValid(registration_request,
61                                               response_headers.get());
62   ASSERT_EQ(params.size(), 1U);
63   const auto& param = params[0];
64   EXPECT_EQ(param.registration_endpoint(),
65             GURL("https://www.example.com/startsession"));
66   EXPECT_THAT(param.supported_algos(),
67               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
68   EXPECT_EQ(param.challenge(), "c1");
69   EXPECT_EQ(param.authorization(), "auth");
70 }
71 
TEST(RegistrationFetcherParamTest,ExtraUnrecognizedAlgorithm)72 TEST(RegistrationFetcherParamTest, ExtraUnrecognizedAlgorithm) {
73   const GURL registration_request("https://www.example.com/registration");
74   scoped_refptr<net::HttpResponseHeaders> response_headers =
75       CreateHeaders("startsession", "(ES256 bf512)", "c1", "auth");
76   std::vector<RegistrationFetcherParam> params =
77       RegistrationFetcherParam::CreateIfValid(registration_request,
78                                               response_headers.get());
79   ASSERT_EQ(params.size(), 1U);
80   const auto& param = params[0];
81   EXPECT_EQ(param.registration_endpoint(),
82             GURL("https://www.example.com/startsession"));
83   EXPECT_THAT(param.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
84   EXPECT_EQ(param.challenge(), "c1");
85   EXPECT_EQ(param.authorization(), "auth");
86 }
87 
TEST(RegistrationFetcherParamTest,NoHeader)88 TEST(RegistrationFetcherParamTest, NoHeader) {
89   const GURL registration_request("https://www.example.com/registration");
90   scoped_refptr<net::HttpResponseHeaders> response_headers =
91       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
92   std::vector<RegistrationFetcherParam> params =
93       RegistrationFetcherParam::CreateIfValid(registration_request,
94                                               response_headers.get());
95   ASSERT_TRUE(params.empty());
96 }
97 
TEST(RegistrationFetcherParamTest,ChallengeFirst)98 TEST(RegistrationFetcherParamTest, ChallengeFirst) {
99   const GURL registration_request("https://www.example.com/registration");
100   // Testing customized header.
101   scoped_refptr<net::HttpResponseHeaders> response_headers =
102       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
103   response_headers->SetHeader(
104       kRegistrationHeader,
105       "(RS256 ES256);challenge=\"challenge1\";path=\"first\"");
106 
107   std::vector<RegistrationFetcherParam> params =
108       RegistrationFetcherParam::CreateIfValid(registration_request,
109                                               response_headers.get());
110   ASSERT_EQ(params.size(), 1U);
111   const auto& param = params[0];
112   EXPECT_EQ(param.registration_endpoint(),
113             GURL("https://www.example.com/first"));
114   EXPECT_THAT(param.supported_algos(),
115               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
116   EXPECT_EQ(param.challenge(), "challenge1");
117 }
118 
TEST(RegistrationFetcherParamTest,NoSpaces)119 TEST(RegistrationFetcherParamTest, NoSpaces) {
120   const GURL registration_request("https://www.example.com/registration");
121   // Testing customized header.
122   scoped_refptr<net::HttpResponseHeaders> response_headers =
123       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
124   response_headers->SetHeader(
125       kRegistrationHeader,
126       "(RS256 ES256);path=\"startsession\";challenge=\"challenge1\"");
127   std::vector<RegistrationFetcherParam> params =
128       RegistrationFetcherParam::CreateIfValid(registration_request,
129                                               response_headers.get());
130   ASSERT_EQ(params.size(), 1U);
131   const auto& param = params[0];
132   EXPECT_EQ(param.registration_endpoint(),
133             GURL("https://www.example.com/startsession"));
134   EXPECT_THAT(param.supported_algos(),
135               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
136   EXPECT_EQ(param.challenge(), "challenge1");
137 }
138 
TEST(RegistrationFetcherParamTest,TwoRegistrations)139 TEST(RegistrationFetcherParamTest, TwoRegistrations) {
140   const GURL registration_request("https://www.example.com/registration");
141   scoped_refptr<net::HttpResponseHeaders> response_headers =
142       CreateHeaders("/first", "(ES256 RS256)", "c1", "auth1");
143   CreateHeaders("/second", "(ES256)", "challenge2", "auth2", response_headers);
144   std::vector<RegistrationFetcherParam> params =
145       RegistrationFetcherParam::CreateIfValid(registration_request,
146                                               response_headers.get());
147   ASSERT_EQ(params.size(), 2U);
148   const auto& p1 = params[0];
149   EXPECT_EQ(p1.registration_endpoint(), GURL("https://www.example.com/first"));
150   EXPECT_THAT(p1.supported_algos(),
151               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
152   EXPECT_EQ(p1.challenge(), "c1");
153   EXPECT_EQ(p1.authorization(), "auth1");
154 
155   const auto& p2 = params[1];
156   EXPECT_EQ(p2.registration_endpoint(), GURL("https://www.example.com/second"));
157   EXPECT_THAT(p2.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
158   EXPECT_EQ(p2.challenge(), "challenge2");
159   EXPECT_EQ(p2.authorization(), "auth2");
160 }
161 
TEST(RegistrationFetcherParamTest,ValidInvalid)162 TEST(RegistrationFetcherParamTest, ValidInvalid) {
163   const GURL registration_request("https://www.example.com/registration");
164   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
165       "/first", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
166   CreateHeaders("/second", "(es256)", "challenge2", "auth2", response_headers);
167   std::vector<RegistrationFetcherParam> params =
168       RegistrationFetcherParam::CreateIfValid(registration_request,
169                                               response_headers.get());
170   ASSERT_EQ(params.size(), 1U);
171   const auto& p1 = params[0];
172   EXPECT_EQ(p1.registration_endpoint(), GURL("https://www.example.com/first"));
173   EXPECT_THAT(p1.supported_algos(),
174               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
175   EXPECT_EQ(p1.challenge(), "c1");
176   EXPECT_FALSE(p1.authorization());
177 }
178 
TEST(RegistrationFetcherParamTest,AddedInvalidNonsenseCharacters)179 TEST(RegistrationFetcherParamTest, AddedInvalidNonsenseCharacters) {
180   const GURL registration_request("https://www.example.com/registration");
181   // Testing customized header.
182   scoped_refptr<net::HttpResponseHeaders> response_headers =
183       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
184   response_headers->AddHeader(kRegistrationHeader,
185                               "(RS256);path=\"new\";challenge=\"test\";;=;");
186   std::vector<RegistrationFetcherParam> params =
187       RegistrationFetcherParam::CreateIfValid(registration_request,
188                                               response_headers.get());
189   ASSERT_TRUE(params.empty());
190 }
191 
TEST(RegistrationFetcherParamTest,AddedValidNonsenseCharacters)192 TEST(RegistrationFetcherParamTest, AddedValidNonsenseCharacters) {
193   const GURL registration_request("https://www.example.com/registration");
194   // Testing customized header.
195   scoped_refptr<net::HttpResponseHeaders> response_headers =
196       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
197   response_headers->AddHeader(
198       kRegistrationHeader,
199       "(RS256);path=\"new\";challenge=\"test\";nonsense=\";';'\",OTHER");
200   std::vector<RegistrationFetcherParam> params =
201       RegistrationFetcherParam::CreateIfValid(registration_request,
202                                               response_headers.get());
203   ASSERT_EQ(params.size(), 1U);
204   const auto& p1 = params[0];
205   EXPECT_EQ(p1.registration_endpoint(), GURL("https://www.example.com/new"));
206   EXPECT_THAT(p1.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
207   EXPECT_EQ(p1.challenge(), "test");
208 }
209 
TEST(RegistrationFetcherParamTest,AlgAsString)210 TEST(RegistrationFetcherParamTest, AlgAsString) {
211   const GURL registration_request("https://www.example.com/registration");
212   // Testing customized header.
213   scoped_refptr<net::HttpResponseHeaders> response_headers =
214       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
215   response_headers->AddHeader(kRegistrationHeader,
216                               "(\"RS256\");path=\"new\";challenge=\"test\"");
217   std::vector<RegistrationFetcherParam> params =
218       RegistrationFetcherParam::CreateIfValid(registration_request,
219                                               response_headers.get());
220   ASSERT_TRUE(params.empty());
221 }
222 
TEST(RegistrationFetcherParamTest,PathAsToken)223 TEST(RegistrationFetcherParamTest, PathAsToken) {
224   const GURL registration_request("https://www.example.com/registration");
225   // Testing customized header.
226   scoped_refptr<net::HttpResponseHeaders> response_headers =
227       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
228   response_headers->AddHeader(kRegistrationHeader,
229                               "(RS256);path=new;challenge=\"test\"");
230   std::vector<RegistrationFetcherParam> params =
231       RegistrationFetcherParam::CreateIfValid(registration_request,
232                                               response_headers.get());
233   ASSERT_TRUE(params.empty());
234 }
235 
TEST(RegistrationFetcherParamTest,ChallengeAsByteSequence)236 TEST(RegistrationFetcherParamTest, ChallengeAsByteSequence) {
237   const GURL registration_request("https://www.example.com/registration");
238   // Testing customized header.
239   scoped_refptr<net::HttpResponseHeaders> response_headers =
240       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
241   response_headers->AddHeader(kRegistrationHeader,
242                               "(RS256);path=\"new\";challenge=:Y29kZWQ=:");
243   std::vector<RegistrationFetcherParam> params =
244       RegistrationFetcherParam::CreateIfValid(registration_request,
245                                               response_headers.get());
246   ASSERT_TRUE(params.empty());
247 }
248 
TEST(RegistrationFetcherParamTest,ValidInvalidValid)249 TEST(RegistrationFetcherParamTest, ValidInvalidValid) {
250   const GURL registration_request("https://www.example.com/registration");
251   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
252       "/first", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
253   CreateHeaders("/second", "(es256)", "challenge2", "auth2", response_headers);
254   CreateHeaders("/third", "(ES256)", "challenge3", "auth3", response_headers);
255 
256   std::vector<RegistrationFetcherParam> params =
257       RegistrationFetcherParam::CreateIfValid(registration_request,
258                                               response_headers.get());
259   ASSERT_EQ(params.size(), 2U);
260   const auto& p1 = params[0];
261   EXPECT_EQ(p1.registration_endpoint(), GURL("https://www.example.com/first"));
262   EXPECT_THAT(p1.supported_algos(),
263               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
264   EXPECT_EQ(p1.challenge(), "c1");
265   EXPECT_FALSE(p1.authorization());
266 
267   const auto& p2 = params[1];
268   EXPECT_EQ(p2.registration_endpoint(), GURL("https://www.example.com/third"));
269   EXPECT_THAT(p2.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
270   EXPECT_EQ(p2.challenge(), "challenge3");
271   EXPECT_EQ(p2.authorization(), "auth3");
272 }
273 
TEST(RegistrationFetcherParamTest,ThreeRegistrations)274 TEST(RegistrationFetcherParamTest, ThreeRegistrations) {
275   const GURL registration_request("https://www.example.com/registration");
276   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
277       "/startsession", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
278   CreateHeaders("/new", "(ES256)", "coded", "", response_headers);
279   CreateHeaders("/third", "(ES256)", "another", "auth", response_headers);
280 
281   std::vector<RegistrationFetcherParam> params =
282       RegistrationFetcherParam::CreateIfValid(registration_request,
283                                               response_headers.get());
284   ASSERT_EQ(params.size(), 3U);
285   const auto& p1 = params[0];
286   EXPECT_EQ(p1.registration_endpoint(),
287             GURL("https://www.example.com/startsession"));
288   EXPECT_THAT(p1.supported_algos(),
289               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
290   EXPECT_EQ(p1.challenge(), "c1");
291   EXPECT_FALSE(p1.authorization());
292 
293   const auto& p2 = params[1];
294   EXPECT_EQ(p2.registration_endpoint(), GURL("https://www.example.com/new"));
295   EXPECT_THAT(p2.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
296   EXPECT_EQ(p2.challenge(), "coded");
297   EXPECT_EQ(p2.authorization(), "");
298 
299   const auto& p3 = params[2];
300   EXPECT_EQ(p3.registration_endpoint(), GURL("https://www.example.com/third"));
301   EXPECT_THAT(p3.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
302   EXPECT_EQ(p3.challenge(), "another");
303   EXPECT_EQ(p3.authorization(), "auth");
304 }
305 
TEST(RegistrationFetcherParamTest,ThreeRegistrationsList)306 TEST(RegistrationFetcherParamTest, ThreeRegistrationsList) {
307   const GURL registration_request("https://www.example.com/registration");
308   // Testing customized header.
309   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
310       "/startsession", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
311   response_headers->AddHeader(kRegistrationHeader,
312                               "(ES256);path=\"new\";challenge=\"coded\", "
313                               "(ES256);path=\"third\";challenge=\"another\"");
314   std::vector<RegistrationFetcherParam> params =
315       RegistrationFetcherParam::CreateIfValid(registration_request,
316                                               response_headers.get());
317   ASSERT_EQ(params.size(), 3U);
318   const auto& p1 = params[0];
319   EXPECT_EQ(p1.registration_endpoint(),
320             GURL("https://www.example.com/startsession"));
321   EXPECT_THAT(p1.supported_algos(),
322               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
323   EXPECT_EQ(p1.challenge(), "c1");
324 
325   const auto& p2 = params[1];
326   EXPECT_EQ(p2.registration_endpoint(), GURL("https://www.example.com/new"));
327   EXPECT_THAT(p2.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
328   EXPECT_EQ(p2.challenge(), "coded");
329 
330   const auto& p3 = params[2];
331   EXPECT_EQ(p3.registration_endpoint(), GURL("https://www.example.com/third"));
332   EXPECT_THAT(p3.supported_algos(), UnorderedElementsAre(ECDSA_SHA256));
333   EXPECT_EQ(p3.challenge(), "another");
334 }
335 
TEST(RegistrationFetcherParamTest,StartWithSlash)336 TEST(RegistrationFetcherParamTest, StartWithSlash) {
337   const GURL registration_request("https://www.example.com/registration");
338   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
339       "/startsession", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
340   std::vector<RegistrationFetcherParam> params =
341       RegistrationFetcherParam::CreateIfValid(registration_request,
342                                               response_headers.get());
343   ASSERT_EQ(params.size(), 1U);
344   const auto& param = params[0];
345   EXPECT_EQ(param.registration_endpoint(),
346             GURL("https://www.example.com/startsession"));
347   EXPECT_THAT(param.supported_algos(),
348               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
349   EXPECT_EQ(param.challenge(), "c1");
350   EXPECT_FALSE(param.authorization());
351 }
352 
TEST(RegistrationFetcherParamTest,EscapeOnce)353 TEST(RegistrationFetcherParamTest, EscapeOnce) {
354   const GURL registration_request("https://www.example.com/registration");
355   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
356       "/%2561", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
357   std::vector<RegistrationFetcherParam> params =
358       RegistrationFetcherParam::CreateIfValid(registration_request,
359                                               response_headers.get());
360   ASSERT_EQ(params.size(), 1U);
361   const auto& param = params[0];
362   EXPECT_EQ(param.registration_endpoint(), GURL("https://www.example.com/%61"));
363   EXPECT_THAT(param.supported_algos(),
364               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
365   EXPECT_EQ(param.challenge(), "c1");
366   EXPECT_FALSE(param.authorization());
367 }
368 
TEST(RegistrationFetcherParamTest,InvalidUrl)369 TEST(RegistrationFetcherParamTest, InvalidUrl) {
370   const GURL registration_request = GURL("https://[/");
371   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
372       "new", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
373   std::vector<RegistrationFetcherParam> params =
374       RegistrationFetcherParam::CreateIfValid(registration_request,
375                                               response_headers.get());
376   ASSERT_EQ(params.size(), 0U);
377 }
378 
TEST(RegistrationFetcherParamTest,HasUrlEncoded)379 TEST(RegistrationFetcherParamTest, HasUrlEncoded) {
380   const GURL registration_request("https://www.example.com/registration");
381   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
382       "test%2Fstart", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
383   std::vector<RegistrationFetcherParam> params =
384       RegistrationFetcherParam::CreateIfValid(registration_request,
385                                               response_headers.get());
386   ASSERT_EQ(params.size(), 1U);
387   const auto& param = params[0];
388   EXPECT_EQ(param.registration_endpoint(),
389             GURL("https://www.example.com/test/start"));
390   EXPECT_THAT(param.supported_algos(),
391               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
392   EXPECT_EQ(param.challenge(), "c1");
393   EXPECT_FALSE(param.authorization());
394 }
395 
TEST(RegistrationFetcherParamTest,FullUrl)396 TEST(RegistrationFetcherParamTest, FullUrl) {
397   const GURL registration_request("https://www.example.com/registration");
398   scoped_refptr<net::HttpResponseHeaders> response_headers =
399       CreateHeaders("https://accounts.example.com/startsession",
400                     "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
401   std::vector<RegistrationFetcherParam> params =
402       RegistrationFetcherParam::CreateIfValid(registration_request,
403                                               response_headers.get());
404   ASSERT_EQ(params.size(), 1U);
405   const auto& param = params[0];
406   EXPECT_EQ(param.registration_endpoint(),
407             GURL("https://accounts.example.com/startsession"));
408   EXPECT_THAT(param.supported_algos(),
409               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
410   EXPECT_EQ(param.challenge(), "c1");
411   EXPECT_FALSE(param.authorization());
412 }
413 
TEST(RegistrationFetcherParamTest,SwapAlgo)414 TEST(RegistrationFetcherParamTest, SwapAlgo) {
415   const GURL registration_request("https://www.example.com/registration");
416   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
417       "startsession", "(ES256 RS256)", "c1", /*authorization=*/std::nullopt);
418   std::vector<RegistrationFetcherParam> params =
419       RegistrationFetcherParam::CreateIfValid(registration_request,
420                                               response_headers.get());
421   ASSERT_EQ(params.size(), 1U);
422   const auto& param = params[0];
423   EXPECT_EQ(param.registration_endpoint(),
424             GURL("https://www.example.com/startsession"));
425   EXPECT_THAT(param.supported_algos(),
426               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
427   EXPECT_EQ(param.challenge(), "c1");
428   EXPECT_FALSE(param.authorization());
429 }
430 
TEST(RegistrationFetcherParamTest,OneAlgo)431 TEST(RegistrationFetcherParamTest, OneAlgo) {
432   const GURL registration_request("https://www.example.com/registration");
433   scoped_refptr<net::HttpResponseHeaders> response_headers = CreateHeaders(
434       "startsession", "(RS256)", "c1", /*authorization=*/std::nullopt);
435   std::vector<RegistrationFetcherParam> params =
436       RegistrationFetcherParam::CreateIfValid(registration_request,
437                                               response_headers.get());
438   ASSERT_EQ(params.size(), 1U);
439   const auto& param = params[0];
440   EXPECT_EQ(param.registration_endpoint(),
441             GURL("https://www.example.com/startsession"));
442   ASSERT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
443   EXPECT_EQ(param.challenge(), "c1");
444   EXPECT_FALSE(param.authorization());
445 }
446 
TEST(RegistrationFetcherParamTest,InvalidParamIgnored)447 TEST(RegistrationFetcherParamTest, InvalidParamIgnored) {
448   const GURL registration_request("https://www.example.com/registration");
449   scoped_refptr<net::HttpResponseHeaders> response_headers =
450       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
451   response_headers->SetHeader(
452       kRegistrationHeader,
453       "(RS256);path=\"first\";challenge=\"c1\";another=true");
454   std::vector<RegistrationFetcherParam> params =
455       RegistrationFetcherParam::CreateIfValid(registration_request,
456                                               response_headers.get());
457   ASSERT_EQ(params.size(), 1U);
458   const auto& param = params[0];
459   EXPECT_EQ(param.registration_endpoint(),
460             GURL("https://www.example.com/first"));
461   ASSERT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
462   EXPECT_EQ(param.challenge(), "c1");
463   EXPECT_FALSE(param.authorization());
464 }
465 
TEST(RegistrationFetcherParamTest,InvalidInputs)466 TEST(RegistrationFetcherParamTest, InvalidInputs) {
467   struct Input {
468     std::string request_url;
469     std::optional<std::string> path;
470     std::optional<std::string> algos;
471     std::optional<std::string> challenge;
472   };
473 
474   const Input kInvalidInputs[] = {
475       // All invalid
476       {"https://www.example.com/reg", "", "()", ""},
477       // All missing
478       {"https://www.example.com/reg", std::nullopt, std::nullopt, std::nullopt},
479       // All valid different Url
480       {"https://www.example.com/registration",
481        "https://accounts.different.url/startsession", "(RS256)", "c1"},
482       // Empty request Url
483       {"", "start", "(RS256)", "c1"},
484       // Empty algo
485       {"https://www.example.com/reg", "start", "()", "c1"},
486       // Missing algo
487       {"https://www.example.com/reg", "start", std::nullopt, "c1"},
488       // Missing registration
489       {"https://www.example.com/reg", std::nullopt, "(ES256 RS256)", "c1"},
490       // Missing challenge
491       {"https://www.example.com/reg", "start", "(ES256 RS256)", std::nullopt},
492       // Empty challenge
493       {"https://www.example.com/reg", "start", "(ES256 RS256)", ""},
494       // Challenge invalid utf8
495       {"https://www.example.com/reg", "start", "(ES256 RS256)", "ab\xC0\x80"}};
496 
497   for (const auto& input : kInvalidInputs) {
498     const GURL registration_request = GURL(input.request_url);
499     scoped_refptr<net::HttpResponseHeaders> response_headers =
500         CreateHeaders(input.path, input.algos, input.challenge,
501                       /*authorization=*/std::nullopt);
502     SCOPED_TRACE(registration_request.spec() + "; " +
503                  response_headers->raw_headers());
504     std::vector<RegistrationFetcherParam> params =
505         RegistrationFetcherParam::CreateIfValid(registration_request,
506                                                 response_headers.get());
507     EXPECT_TRUE(params.empty());
508   }
509 }
510 
TEST(RegistrationFetcherParamTest,ValidAuthorization)511 TEST(RegistrationFetcherParamTest, ValidAuthorization) {
512   const GURL registration_request("https://www.example.com/registration");
513   scoped_refptr<net::HttpResponseHeaders> response_headers =
514       CreateHeaders("startsession", "(ES256 RS256)", "c1", "authcode");
515   std::vector<RegistrationFetcherParam> params =
516       RegistrationFetcherParam::CreateIfValid(registration_request,
517                                               response_headers.get());
518   ASSERT_EQ(params.size(), 1U);
519   const auto& param = params[0];
520   EXPECT_EQ(param.registration_endpoint(),
521             GURL("https://www.example.com/startsession"));
522   EXPECT_THAT(param.supported_algos(),
523               UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
524   EXPECT_EQ(param.challenge(), "c1");
525   EXPECT_EQ(param.authorization(), "authcode");
526 }
527 
TEST(RegistrationFetcherParamTest,InvalidAuthorizationIgnored)528 TEST(RegistrationFetcherParamTest, InvalidAuthorizationIgnored) {
529   const GURL registration_request("https://www.example.com/registration");
530   // Testing customized header.
531   scoped_refptr<net::HttpResponseHeaders> response_headers =
532       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
533   response_headers->AddHeader(
534       kRegistrationHeader,
535       "(RS256);path=\"startsession\";challenge=\"c1\";authorization=123");
536   std::vector<RegistrationFetcherParam> params =
537       RegistrationFetcherParam::CreateIfValid(registration_request,
538                                               response_headers.get());
539   ASSERT_EQ(params.size(), 1U);
540   const auto& param = params[0];
541   EXPECT_EQ(param.registration_endpoint(),
542             GURL("https://www.example.com/startsession"));
543   EXPECT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
544   EXPECT_EQ(param.challenge(), "c1");
545   EXPECT_FALSE(param.authorization());
546 }
547 
TEST(RegistrationFetcherParamTest,MultipleAuthorizationHeaders)548 TEST(RegistrationFetcherParamTest, MultipleAuthorizationHeaders) {
549   const GURL registration_request("https://www.example.com/registration");
550   // Testing customized header.
551   scoped_refptr<net::HttpResponseHeaders> response_headers =
552       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
553   response_headers->AddHeader(
554       kRegistrationHeader,
555       "(RS256);path=\"startsession\";challenge=\"c1\";"
556       "authorization=\"auth1\";authorization=\"auth2\"");
557   std::vector<RegistrationFetcherParam> params =
558       RegistrationFetcherParam::CreateIfValid(registration_request,
559                                               response_headers.get());
560   ASSERT_EQ(params.size(), 1U);
561   const auto& param = params[0];
562   EXPECT_EQ(param.registration_endpoint(),
563             GURL("https://www.example.com/startsession"));
564   EXPECT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
565   EXPECT_EQ(param.challenge(), "c1");
566   EXPECT_EQ(param.authorization(), "auth2");
567 }
568 
TEST(RegistrationFetcherParamTest,MultipleAuthorizationHeadersWithEmpty)569 TEST(RegistrationFetcherParamTest, MultipleAuthorizationHeadersWithEmpty) {
570   const GURL registration_request("https://www.example.com/registration");
571   // Testing customized header.
572   scoped_refptr<net::HttpResponseHeaders> response_headers =
573       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
574   response_headers->AddHeader(kRegistrationHeader,
575                               "(RS256);path=\"startsession\";challenge=\"c1\";"
576                               "authorization=\"auth1\";authorization=\"\"");
577   std::vector<RegistrationFetcherParam> params =
578       RegistrationFetcherParam::CreateIfValid(registration_request,
579                                               response_headers.get());
580   ASSERT_EQ(params.size(), 1U);
581   const auto& param = params[0];
582   EXPECT_EQ(param.registration_endpoint(),
583             GURL("https://www.example.com/startsession"));
584   EXPECT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
585   EXPECT_EQ(param.challenge(), "c1");
586   EXPECT_EQ(param.authorization(), "");
587 }
588 
TEST(RegistrationFetcherParamTest,EmptyStringAuthorization)589 TEST(RegistrationFetcherParamTest, EmptyStringAuthorization) {
590   const GURL registration_request("https://www.example.com/registration");
591   // Testing customized header.
592   scoped_refptr<net::HttpResponseHeaders> response_headers =
593       HttpResponseHeaders::Builder({1, 1}, "200 OK").Build();
594   response_headers->AddHeader(
595       kRegistrationHeader,
596       "(RS256);path=\"startsession\";challenge=\"c1\";authorization=\"\"");
597   std::vector<RegistrationFetcherParam> params =
598       RegistrationFetcherParam::CreateIfValid(registration_request,
599                                               response_headers.get());
600   ASSERT_EQ(params.size(), 1U);
601   const auto& param = params[0];
602   EXPECT_EQ(param.registration_endpoint(),
603             GURL("https://www.example.com/startsession"));
604   EXPECT_THAT(param.supported_algos(), UnorderedElementsAre(RSA_PKCS1_SHA256));
605   EXPECT_EQ(param.challenge(), "c1");
606   EXPECT_EQ(param.authorization(), "");
607 }
608 
609 }  // namespace
610 
611 }  // namespace net::device_bound_sessions
612