Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: net/http/http_auth_controller_unittest.cc

Issue 1391053002: [net/http auth] Make HttpAuthHandler challenge handling asynchronous. Base URL: https://chromium.googlesource.com/chromium/src.git@auth-handler-init-split
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http/http_auth_controller.cc ('k') | net/http/http_auth_gssapi_posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_auth_controller.h" 5 #include "net/http/http_auth_controller.h"
6 6
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
8 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
9 #include "net/base/test_completion_callback.h" 12 #include "net/base/test_completion_callback.h"
13 #include "net/dns/mock_host_resolver.h"
14 #include "net/http/http_auth.h"
10 #include "net/http/http_auth_cache.h" 15 #include "net/http/http_auth_cache.h"
11 #include "net/http/http_auth_challenge_tokenizer.h" 16 #include "net/http/http_auth_challenge_tokenizer.h"
17 #include "net/http/http_auth_filter.h"
18 #include "net/http/http_auth_handler.h"
19 #include "net/http/http_auth_handler_factory.h"
12 #include "net/http/http_auth_handler_mock.h" 20 #include "net/http/http_auth_handler_mock.h"
13 #include "net/http/http_request_info.h" 21 #include "net/http/http_request_info.h"
14 #include "net/http/http_response_headers.h" 22 #include "net/http/http_response_headers.h"
23 #include "net/http/http_response_info.h"
15 #include "net/http/http_util.h" 24 #include "net/http/http_util.h"
25 #include "net/http/mock_allow_url_security_manager.h"
16 #include "net/log/net_log.h" 26 #include "net/log/net_log.h"
17 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
18 28
29 using ::testing::ValuesIn;
30
19 namespace net { 31 namespace net {
20 32
21 namespace { 33 namespace {
22 34
23 enum HandlerRunMode { 35 enum HandlerRunMode {
24 RUN_HANDLER_SYNC, 36 RUN_HANDLER_SYNC,
25 RUN_HANDLER_ASYNC 37 RUN_HANDLER_ASYNC
26 }; 38 };
27 39
28 enum SchemeState { 40 enum SchemeState {
(...skipping 13 matching lines...) Expand all
42 // Runs an HttpAuthController with a single round mock auth handler 54 // Runs an HttpAuthController with a single round mock auth handler
43 // that returns |handler_rv| on token generation. The handler runs in 55 // that returns |handler_rv| on token generation. The handler runs in
44 // async if |run_mode| is RUN_HANDLER_ASYNC. Upon completion, the 56 // async if |run_mode| is RUN_HANDLER_ASYNC. Upon completion, the
45 // return value of the controller is tested against 57 // return value of the controller is tested against
46 // |expected_controller_rv|. |scheme_state| indicates whether the 58 // |expected_controller_rv|. |scheme_state| indicates whether the
47 // auth scheme used should be disabled after this run. 59 // auth scheme used should be disabled after this run.
48 void RunSingleRoundAuthTest(HandlerRunMode run_mode, 60 void RunSingleRoundAuthTest(HandlerRunMode run_mode,
49 int handler_rv, 61 int handler_rv,
50 int expected_controller_rv, 62 int expected_controller_rv,
51 SchemeState scheme_state) { 63 SchemeState scheme_state) {
64 SCOPED_TRACE(::testing::Message()
65 << "run_mode:" << run_mode << " handler_rv:" << handler_rv
66 << " expected_controller_rv:" << expected_controller_rv
67 << " scheme_state:" << scheme_state);
52 BoundNetLog dummy_log; 68 BoundNetLog dummy_log;
53 HttpAuthCache dummy_auth_cache; 69 HttpAuthCache dummy_auth_cache;
54 70
55 HttpRequestInfo request; 71 HttpRequestInfo request;
56 request.method = "GET"; 72 request.method = "GET";
57 request.url = GURL("http://example.com"); 73 request.url = GURL("http://example.com");
58 74
59 scoped_refptr<HttpResponseHeaders> headers(HeadersFromString( 75 HttpResponseInfo response;
76 response.headers = HeadersFromString(
60 "HTTP/1.1 407\r\n" 77 "HTTP/1.1 407\r\n"
61 "Proxy-Authenticate: MOCK foo\r\n" 78 "Proxy-Authenticate: MOCK foo\r\n"
62 "\r\n")); 79 "\r\n");
63 80
64 HttpAuthHandlerMock::Factory auth_handler_factory; 81 HttpAuthHandlerMock::Factory auth_handler_factory;
65 scoped_ptr<HttpAuthHandlerMock> auth_handler(new HttpAuthHandlerMock()); 82 scoped_ptr<HttpAuthHandlerMock> auth_handler(new HttpAuthHandlerMock());
66 auth_handler->SetGenerateExpectation((run_mode == RUN_HANDLER_ASYNC), 83 auth_handler->SetGenerateExpectation((run_mode == RUN_HANDLER_ASYNC),
67 handler_rv); 84 handler_rv);
68 auth_handler_factory.AddMockHandler(auth_handler.Pass(), 85 auth_handler_factory.AddMockHandler(auth_handler.Pass(),
69 HttpAuthHandlerCreateReason::CHALLENGE); 86 HttpAuthHandlerCreateReason::CHALLENGE);
70 87
71 scoped_refptr<HttpAuthController> controller( 88 scoped_refptr<HttpAuthController> controller(
72 new HttpAuthController(HttpAuth::AUTH_PROXY, 89 new HttpAuthController(HttpAuth::AUTH_PROXY,
73 GURL("http://example.com"), 90 GURL("http://example.com"),
74 &dummy_auth_cache, &auth_handler_factory)); 91 &dummy_auth_cache, &auth_handler_factory));
75 ASSERT_EQ(OK, 92 TestCompletionCallback completion_callback;
76 controller->HandleAuthChallenge(headers, false, false, dummy_log)); 93 int result = controller->HandleAuthChallenge(
94 response, completion_callback.callback(), dummy_log);
95 ASSERT_EQ(OK, completion_callback.GetResult(result));
77 ASSERT_TRUE(controller->HaveAuthHandler()); 96 ASSERT_TRUE(controller->HaveAuthHandler());
97 EXPECT_FALSE(controller->HaveAuth());
78 controller->ResetAuth( 98 controller->ResetAuth(
79 AuthCredentials(base::ASCIIToUTF16("a"), base::ASCIIToUTF16("b"))); 99 AuthCredentials(base::ASCIIToUTF16("a"), base::ASCIIToUTF16("b")));
80 EXPECT_TRUE(controller->HaveAuth()); 100 EXPECT_TRUE(controller->HaveAuth());
81 101
82 TestCompletionCallback callback; 102 TestCompletionCallback callback;
83 EXPECT_EQ((run_mode == RUN_HANDLER_ASYNC)? ERR_IO_PENDING: 103 result = controller->MaybeGenerateAuthToken(&request, callback.callback(),
84 expected_controller_rv, 104 dummy_log);
85 controller->MaybeGenerateAuthToken(&request, callback.callback(),
86 dummy_log));
87 if (run_mode == RUN_HANDLER_ASYNC) 105 if (run_mode == RUN_HANDLER_ASYNC)
88 EXPECT_EQ(expected_controller_rv, callback.WaitForResult()); 106 ASSERT_EQ(ERR_IO_PENDING, result);
107 EXPECT_EQ(expected_controller_rv, callback.GetResult(result));
89 EXPECT_EQ((scheme_state == SCHEME_IS_DISABLED), 108 EXPECT_EQ((scheme_state == SCHEME_IS_DISABLED),
90 controller->IsAuthSchemeDisabled("mock")); 109 controller->IsAuthSchemeDisabled("mock"));
91 } 110 }
92 111
93 } // namespace 112 } // namespace
94 113
95 // If an HttpAuthHandler returns an error code that indicates a 114 // If an HttpAuthHandler returns an error code that indicates a
96 // permanent error, the HttpAuthController should disable the scheme 115 // permanent error, the HttpAuthController should disable the scheme
97 // used and retry the request. 116 // used and retry the request.
98 TEST(HttpAuthControllerTest, PermanentErrors) { 117 TEST(HttpAuthControllerTest, PermanentErrors_Sync) {
99
100 // Run a synchronous handler that returns
101 // ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS. We expect a return value
102 // of OK from the controller so we can retry the request.
103 RunSingleRoundAuthTest(RUN_HANDLER_SYNC, 118 RunSingleRoundAuthTest(RUN_HANDLER_SYNC,
104 ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS, 119 ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS,
105 OK, SCHEME_IS_DISABLED); 120 OK, SCHEME_IS_DISABLED);
121 }
106 122
107 // Now try an async handler that returns 123 // Similar to the above test. Now try an async handler that returns
108 // ERR_MISSING_AUTH_CREDENTIALS. Async and sync handlers invoke 124 // ERR_MISSING_AUTH_CREDENTIALS. Async and sync handlers invoke different code
109 // different code paths in HttpAuthController when generating 125 // paths in HttpAuthController when generating tokens.
110 // tokens. 126 TEST(HttpAuthControllerTest, PermanentErrors_Async) {
111 RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_MISSING_AUTH_CREDENTIALS, OK, 127 RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_MISSING_AUTH_CREDENTIALS, OK,
112 SCHEME_IS_DISABLED); 128 SCHEME_IS_DISABLED);
129 }
113 130
114 // If a non-permanent error is returned by the handler, then the 131 // If a non-permanent error is returned by the handler, then the controller
115 // controller should report it unchanged. 132 // should leave the scheme enabled.
133 TEST(HttpAuthControllerTest, NonPermanentErrors_Sync) {
134 RunSingleRoundAuthTest(RUN_HANDLER_SYNC, ERR_INVALID_AUTH_CREDENTIALS,
135 ERR_INVALID_AUTH_CREDENTIALS, SCHEME_IS_ENABLED);
136 }
137
138 // If a non-permanent error is returned by the handler, then the controller
139 // should leave the scheme enabled.
140 TEST(HttpAuthControllerTest, NonPermanentErrors_Async) {
116 RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_INVALID_AUTH_CREDENTIALS, 141 RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_INVALID_AUTH_CREDENTIALS,
117 ERR_INVALID_AUTH_CREDENTIALS, SCHEME_IS_ENABLED); 142 ERR_INVALID_AUTH_CREDENTIALS, SCHEME_IS_ENABLED);
118 } 143 }
119 144
120 // If an HttpAuthHandler indicates that it doesn't allow explicit 145 // If an HttpAuthHandler indicates that it doesn't allow explicit
121 // credentials, don't prompt for credentials. 146 // credentials, don't prompt for credentials.
122 TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) { 147 TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
123 BoundNetLog dummy_log; 148 BoundNetLog dummy_log;
124 HttpAuthCache dummy_auth_cache; 149 HttpAuthCache dummy_auth_cache;
125 HttpRequestInfo request; 150 HttpRequestInfo request;
126 request.method = "GET"; 151 request.method = "GET";
127 request.url = GURL("http://example.com"); 152 request.url = GURL("http://example.com");
128 153
129 HttpRequestHeaders request_headers; 154 HttpRequestHeaders request_headers;
130 scoped_refptr<HttpResponseHeaders> headers( 155 HttpResponseInfo response;
131 HeadersFromString("HTTP/1.1 401\r\n" 156 response.headers = HeadersFromString(
132 "WWW-Authenticate: Ernie\r\n" 157 "HTTP/1.1 401\r\n"
133 "WWW-Authenticate: Bert\r\n" 158 "WWW-Authenticate: Ernie\r\n"
134 "\r\n")); 159 "WWW-Authenticate: Bert\r\n"
160 "\r\n");
135 161
136 HttpAuthHandlerMock::Factory auth_handler_factory; 162 HttpAuthHandlerMock::Factory auth_handler_factory;
137 163
138 // Handler for the first attempt at authentication. "Ernie" handler accepts 164 // Handler for the first attempt at authentication. "Ernie" handler accepts
139 // the default identity and successfully constructs a token. Handler for the 165 // the default identity and successfully constructs a token. Handler for the
140 scoped_ptr<HttpAuthHandlerMock> auth_handler(new HttpAuthHandlerMock()); 166 scoped_ptr<HttpAuthHandlerMock> auth_handler(new HttpAuthHandlerMock());
141 auth_handler->set_allows_default_credentials(true); 167 auth_handler->set_allows_default_credentials(true);
142 auth_handler->set_allows_explicit_credentials(false); 168 auth_handler->set_allows_explicit_credentials(false);
143 auth_handler->set_expected_auth_scheme("ernie"); 169 auth_handler->set_expected_auth_scheme("ernie");
144 auth_handler_factory.AddMockHandler(auth_handler.Pass(), 170 auth_handler_factory.AddMockHandler(auth_handler.Pass(),
145 HttpAuthHandlerCreateReason::CHALLENGE); 171 HttpAuthHandlerCreateReason::CHALLENGE);
146 172
147 scoped_refptr<HttpAuthController> controller( 173 scoped_refptr<HttpAuthController> controller(
148 new HttpAuthController(HttpAuth::AUTH_SERVER, 174 new HttpAuthController(HttpAuth::AUTH_SERVER,
149 GURL("http://example.com"), 175 GURL("http://example.com"),
150 &dummy_auth_cache, &auth_handler_factory)); 176 &dummy_auth_cache, &auth_handler_factory));
151 ASSERT_EQ(OK, 177 TestCompletionCallback completion_calback;
152 controller->HandleAuthChallenge(headers, false, false, dummy_log)); 178 int rv = controller->HandleAuthChallenge(
179 response, completion_calback.callback(), dummy_log);
180 ASSERT_EQ(OK, completion_calback.GetResult(rv));
153 ASSERT_TRUE(controller->HaveAuthHandler()); 181 ASSERT_TRUE(controller->HaveAuthHandler());
154 controller->ResetAuth(AuthCredentials());
155 EXPECT_TRUE(controller->HaveAuth()); 182 EXPECT_TRUE(controller->HaveAuth());
156 EXPECT_FALSE(auth_handler_factory.HaveAuthHandlers()); 183 EXPECT_FALSE(auth_handler_factory.HaveAuthHandlers());
157 184
158 // Should only succeed if we are using the "Ernie" MockHandler. 185 // Should only succeed if we are using the "Ernie" MockHandler.
159 EXPECT_EQ(OK, controller->MaybeGenerateAuthToken( 186 ASSERT_EQ(OK, controller->MaybeGenerateAuthToken(
160 &request, CompletionCallback(), dummy_log)); 187 &request, completion_calback.callback(), dummy_log));
161 controller->AddAuthorizationHeader(&request_headers); 188 controller->AddAuthorizationHeader(&request_headers);
162 189
163 // Handlers for the second attempt. Neither should be used to generate a 190 // Handlers for the second attempt. Neither should be used to generate a
164 // token. Instead the controller should realize that there are no viable 191 // token. Instead the controller should realize that there are no viable
165 // identities to use with the "Ernie" handler and fail. 192 // identities to use with the "Ernie" handler and fail.
166 auth_handler.reset(new HttpAuthHandlerMock()); 193 auth_handler.reset(new HttpAuthHandlerMock());
167 auth_handler->set_allows_default_credentials(true); 194 auth_handler->set_allows_default_credentials(true);
168 auth_handler->set_allows_explicit_credentials(false); 195 auth_handler->set_allows_explicit_credentials(false);
169 auth_handler->set_expected_auth_scheme("ernie"); 196 auth_handler->set_expected_auth_scheme("ernie");
170 auth_handler_factory.AddMockHandler(auth_handler.Pass(), 197 auth_handler_factory.AddMockHandler(auth_handler.Pass(),
171 HttpAuthHandlerCreateReason::CHALLENGE); 198 HttpAuthHandlerCreateReason::CHALLENGE);
172 199
173 // Fallback handlers for the second attempt. The "Ernie" handler should be 200 // Fallback handlers for the second attempt. The "Ernie" handler should be
174 // discarded due to the disabled scheme, and the "Bert" handler should 201 // discarded due to the disabled scheme, and the "Bert" handler should
175 // successfully be used to generate a token. 202 // successfully be used to generate a token.
176 auth_handler.reset(new HttpAuthHandlerMock()); 203 auth_handler.reset(new HttpAuthHandlerMock());
177 auth_handler->set_allows_default_credentials(false); 204 auth_handler->set_allows_default_credentials(false);
178 auth_handler->set_allows_explicit_credentials(true); 205 auth_handler->set_allows_explicit_credentials(true);
179 auth_handler->set_expected_auth_scheme("bert"); 206 auth_handler->set_expected_auth_scheme("bert");
180 auth_handler_factory.AddMockHandler(auth_handler.Pass(), 207 auth_handler_factory.AddMockHandler(auth_handler.Pass(),
181 HttpAuthHandlerCreateReason::CHALLENGE); 208 HttpAuthHandlerCreateReason::CHALLENGE);
182 209
183 // Once a token is generated, simulate the receipt of a server response 210 // Once a token is generated, simulate the receipt of a server response
184 // indicating that the authentication attempt was rejected. 211 // indicating that the authentication attempt was rejected.
185 ASSERT_EQ(OK, 212 TestCompletionCallback completion_calback_rejected;
186 controller->HandleAuthChallenge(headers, false, false, dummy_log)); 213 rv = controller->HandleAuthChallenge(
214 response, completion_calback_rejected.callback(), dummy_log);
215 ASSERT_EQ(OK, completion_calback_rejected.GetResult(rv));
187 ASSERT_TRUE(controller->HaveAuthHandler()); 216 ASSERT_TRUE(controller->HaveAuthHandler());
217 EXPECT_FALSE(controller->HaveAuth());
188 controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"), 218 controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"),
189 base::string16())); 219 base::string16()));
190 EXPECT_TRUE(controller->HaveAuth()); 220 EXPECT_TRUE(controller->HaveAuth());
191 EXPECT_TRUE(controller->IsAuthSchemeDisabled("ernie")); 221 EXPECT_TRUE(controller->IsAuthSchemeDisabled("ernie"));
192 EXPECT_FALSE(controller->IsAuthSchemeDisabled("bert")); 222 EXPECT_FALSE(controller->IsAuthSchemeDisabled("bert"));
193 223
194 // Should only succeed if we are using the "Bert" MockHandler. 224 // Should only succeed if we are using the "Bert" MockHandler.
195 EXPECT_EQ(OK, controller->MaybeGenerateAuthToken( 225 EXPECT_EQ(OK, controller->MaybeGenerateAuthToken(
196 &request, CompletionCallback(), dummy_log)); 226 &request, completion_calback.callback(), dummy_log));
197 } 227 }
198 228
229 namespace {
230
231 struct ChallengeResponse {
232 const char* const response_headers = nullptr;
233 const char* const authorization_header = nullptr;
234
235 ChallengeResponse(const char* const response_headers,
236 const char* const authorization_header)
237 : response_headers(response_headers),
238 authorization_header(authorization_header) {}
239 };
240
241 struct MockAuthHandler {
242 std::string scheme;
243 int init_rv = OK;
244 int generate_rv = OK;
245
246 MockAuthHandler(const std::string& scheme, int int_rv, int generate_rv)
247 : scheme(scheme), init_rv(int_rv), generate_rv(generate_rv) {}
248 };
249
250 struct ChallengeResponseTestCase {
251 std::vector<ChallengeResponse> rounds;
252 std::vector<MockAuthHandler> handlers;
253 bool run_handler_async = false;
254
255 ChallengeResponseTestCase& WithChallengeResponse(
256 const char* response_headers,
257 const char* authorization_header) {
258 rounds.push_back(ChallengeResponse(response_headers, authorization_header));
259 return *this;
260 }
261
262 ChallengeResponseTestCase& WithHandler(const base::StringPiece& scheme,
263 int init_rv,
264 int generate_rv) {
265 handlers.push_back(
266 MockAuthHandler(scheme.as_string(), init_rv, generate_rv));
267 return *this;
268 }
269 };
270
271 std::vector<ChallengeResponseTestCase> SyncAndAsync(
272 const ChallengeResponseTestCase& test_case) {
273 std::vector<ChallengeResponseTestCase> test_cases;
274 ChallengeResponseTestCase test_case_copy = test_case;
275
276 test_case_copy.run_handler_async = false;
277 test_cases.push_back(test_case_copy);
278
279 test_case_copy.run_handler_async = true;
280 test_cases.push_back(test_case_copy);
281 return test_cases;
282 }
283
284 class HttpAuthControllerTest
285 : public ::testing::TestWithParam<ChallengeResponseTestCase> {};
286
287 } // namespace
288
289 TEST_P(HttpAuthControllerTest, Run) {
290 const ChallengeResponseTestCase& params = GetParam();
291 BoundNetLog dummy_log;
292 HttpAuthCache dummy_auth_cache;
293 GURL url("http://example.com");
294 HttpAuthHandlerMock::Factory auth_factory;
295
296 for (const auto& handler : params.handlers) {
297 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock);
298 mock_handler->set_expected_auth_scheme(handler.scheme);
299 mock_handler->set_expect_multiple_challenges(handler.scheme == "ntlm" ||
300 handler.scheme == "negotiate");
301 mock_handler->SetInitExpectation(params.run_handler_async, handler.init_rv);
302 mock_handler->SetGenerateExpectation(params.run_handler_async,
303 handler.generate_rv);
304 auth_factory.AddMockHandler(mock_handler.Pass(),
305 HttpAuthHandlerCreateReason::CHALLENGE);
306 }
307
308 HttpRequestInfo request_info;
309
310 scoped_refptr<HttpAuthController> auth_controller(new HttpAuthController(
311 HttpAuth::AUTH_SERVER, url, &dummy_auth_cache, &auth_factory));
312 for (const auto& round : params.rounds) {
313 if (!round.response_headers)
314 break;
315 HttpResponseInfo response_info;
316 response_info.headers = HeadersFromString(round.response_headers);
317 TestCompletionCallback callback;
318
319 int result = auth_controller->HandleAuthChallenge(
320 response_info, callback.callback(), dummy_log);
321 EXPECT_EQ(OK, callback.GetResult(result));
322
323 if (!auth_controller->HaveAuthHandler()) {
324 EXPECT_STREQ("", round.authorization_header);
325 continue;
326 }
327
328 if (!auth_controller->HaveAuth()) {
329 auth_controller->ResetAuth(
330 AuthCredentials(base::ASCIIToUTF16("a"), base::ASCIIToUTF16("b")));
331 }
332
333 result = auth_controller->MaybeGenerateAuthToken(
334 &request_info, callback.callback(), dummy_log);
335 EXPECT_EQ(OK, callback.GetResult(result));
336 HttpRequestHeaders headers;
337 auth_controller->AddAuthorizationHeader(&headers);
338 std::string authorization_header;
339 headers.GetHeader(
340 HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER),
341 &authorization_header);
342 EXPECT_STREQ(round.authorization_header, authorization_header.c_str());
343 }
344
345 EXPECT_FALSE(auth_factory.HaveAuthHandlers());
346 }
347
348 // Picks Basic because that's the only supported scheme.
349 INSTANTIATE_TEST_CASE_P(
350 PickSupportedScheme,
351 HttpAuthControllerTest,
352 ValuesIn(
353 SyncAndAsync(ChallengeResponseTestCase()
354 .WithChallengeResponse(
355 "HTTP/1.1 401\n"
356 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
357 "www-authenticate: Basic realm=\"BasicRealm\"\n",
358 "basic auth_token,realm=\"BasicRealm\"")
359 .WithHandler("basic", OK, OK))));
360
361 // No supported schemes.
362 INSTANTIATE_TEST_CASE_P(
363 NoSupportedSchemes,
364 HttpAuthControllerTest,
365 ValuesIn(SyncAndAsync(ChallengeResponseTestCase().WithChallengeResponse(
366 "HTTP/1.1 401\n"
367 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
368 "www-authenticate: Fake realm=\"FooBar\"\n",
369 ""))));
370
371 // Pick Digest over Basic.
372 INSTANTIATE_TEST_CASE_P(
373 DigestOverBasic,
374 HttpAuthControllerTest,
375 ValuesIn(SyncAndAsync(
376 ChallengeResponseTestCase()
377 .WithChallengeResponse(
378 "HTTP/1.1 401\n"
379 "www-authenticate: Basic realm=\"FooBar\"\n"
380 "www-authenticate: Fake realm=\"FooBar\"\n"
381 "www-authenticate: nonce=\"aaaaaaaaaa\"\n"
382 "www-authenticate: Digest realm=\"DigestRealm\", "
383 "nonce=\"aaaaaaaaaa\"\n",
384 "digest auth_token,realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"")
385 .WithHandler("digest", OK, OK))));
386
387 // Handle an empty header correctly.
388 INSTANTIATE_TEST_CASE_P(
389 EmptyHeader,
390 HttpAuthControllerTest,
391 ValuesIn(SyncAndAsync(ChallengeResponseTestCase().WithChallengeResponse(
392 "HTTP/1.1 401\n"
393 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
394 "www-authenticate:\n",
395 ""))));
396
397 // NTLM appears earlier in the list, Negotiate is preferred.
398 INSTANTIATE_TEST_CASE_P(
399 NegotiateOverNTLM,
400 HttpAuthControllerTest,
401 ValuesIn(
402 SyncAndAsync(ChallengeResponseTestCase()
403 .WithChallengeResponse("HTTP/1.1 401\n"
404 "WWW-Authenticate: NTLM\n"
405 "WWW-Authenticate: Negotiate\n",
406 "negotiate auth_token")
407 .WithHandler("negotiate", OK, OK))));
408
409 // Two rounds. Basic isn't connection oriented and will use up a new handler
410 // for the second challenge.
411 INSTANTIATE_TEST_CASE_P(
412 SecondChallengeForBasic,
413 HttpAuthControllerTest,
414 ValuesIn(SyncAndAsync(
415 ChallengeResponseTestCase()
416 .WithChallengeResponse("HTTP/1.1 401\n"
417 "WWW-Authenticate: Basic first_round\n",
418 "basic auth_token,first_round")
419 .WithHandler("basic", OK, OK)
420 .WithChallengeResponse("HTTP/1.1 401\n"
421 "WWW-Authenticate: Basic second_round\n",
422 "basic auth_token,second_round")
423 .WithHandler("basic", OK, OK))));
424
425 // Correctly deal with a missing challenge for the second round.
426 INSTANTIATE_TEST_CASE_P(
427 SecondChallengeIsMissing,
428 HttpAuthControllerTest,
429 ValuesIn(SyncAndAsync(
430 ChallengeResponseTestCase()
431 .WithChallengeResponse("HTTP/1.1 401\n"
432 "WWW-Authenticate: Basic first_round\n",
433 "basic auth_token,first_round")
434 .WithHandler("basic", OK, OK)
435 .WithChallengeResponse("HTTP/1.1 401\n", ""))));
436
437 // Correctly deal with an empty challenge for the second round.
438 INSTANTIATE_TEST_CASE_P(
439 SecondChallengeIsEmpty,
440 HttpAuthControllerTest,
441 ValuesIn(SyncAndAsync(
442 ChallengeResponseTestCase()
443 .WithChallengeResponse("HTTP/1.1 401\n"
444 "WWW-Authenticate: Basic first_round\n",
445 "basic auth_token,first_round")
446 .WithHandler("basic", OK, OK)
447 .WithChallengeResponse("HTTP/1.1 401\n"
448 "WWW-Authenticate:\n",
449 ""))));
450
451 // The second round introduces a preferred scheme.
452 INSTANTIATE_TEST_CASE_P(
453 SecondChallengeHasPreferredScheme,
454 HttpAuthControllerTest,
455 ValuesIn(SyncAndAsync(
456 ChallengeResponseTestCase()
457 .WithChallengeResponse("HTTP/1.1 401\n"
458 "WWW-Authenticate: Basic first_round\n",
459 "basic auth_token,first_round")
460 .WithHandler("basic", OK, OK)
461 .WithChallengeResponse("HTTP/1.1 401\n"
462 "WWW-Authenticate: Basic second_round\n"
463 "WWW-Authenticate: Negotiate\n",
464 "negotiate auth_token")
465 .WithHandler("negotiate", OK, OK))));
466
467 // If there are two challenges, then the auth controller should pick the first
468 // one.
469 INSTANTIATE_TEST_CASE_P(
470 MultipleChallengesForSameScheme,
471 HttpAuthControllerTest,
472 ValuesIn(SyncAndAsync(
473 ChallengeResponseTestCase()
474 .WithChallengeResponse("HTTP/1.1 401\n"
475 "WWW-Authenticate: Basic first_round\n",
476 "basic auth_token,first_round")
477 .WithHandler("basic", OK, OK)
478 .WithChallengeResponse("HTTP/1.1 401\n"
479 "WWW-Authenticate: Basic second_round_1\n"
480 "WWW-Authenticate: Basic second_round_2\n",
481 "basic auth_token,second_round_1")
482 .WithHandler("basic", OK, OK))));
483
484 // As above, but the handler will reject the first challenge of the second
485 // round. The auth controller should use the second challenge instead.
486 INSTANTIATE_TEST_CASE_P(
487 RejectChallengeForTheSameSchemeInSingleResponse,
488 HttpAuthControllerTest,
489 ValuesIn(SyncAndAsync(
490 ChallengeResponseTestCase()
491 .WithChallengeResponse("HTTP/1.1 401\n"
492 "WWW-Authenticate: Basic first_round\n",
493 "basic auth_token,first_round")
494 .WithChallengeResponse("HTTP/1.1 401\n"
495 "WWW-Authenticate: Basic second_round_1\n"
496 "WWW-Authenticate: Basic second_round_2\n",
497 "basic auth_token,second_round_2")
498 .WithHandler("basic", OK, OK)
499 .WithHandler("basic", ERR_INVALID_AUTH_CREDENTIALS, OK)
500 .WithHandler("basic", OK, OK))));
501
502 // Connection based schemes will treat new auth challenges for the same scheme
503 // as acceptance and continuance of the current handshake if there's a
504 // parameter.
505 INSTANTIATE_TEST_CASE_P(
506 MultiRoundAuth_Continuations,
507 HttpAuthControllerTest,
508 ValuesIn(SyncAndAsync(
509 ChallengeResponseTestCase()
510 .WithChallengeResponse("HTTP/1.1 401\n"
511 "WWW-Authenticate: Negotiate\n",
512 "negotiate auth_token")
513 .WithHandler("negotiate", OK, OK)
514 .WithChallengeResponse("HTTP/1.1 401\n"
515 "WWW-Authenticate: Negotiate foo\n",
516 "negotiate continuation,foo"))));
517
518 // As above, but picks the first challenge for the second round.
519 INSTANTIATE_TEST_CASE_P(
520 MultiRoundAuth_ContinuationsWithMultipleChallenges,
521 HttpAuthControllerTest,
522 ValuesIn(SyncAndAsync(
523 ChallengeResponseTestCase()
524 .WithChallengeResponse("HTTP/1.1 401\n"
525 "WWW-Authenticate: Negotiate\n",
526 "negotiate auth_token")
527 .WithHandler("negotiate", OK, OK)
528 .WithChallengeResponse("HTTP/1.1 401\n"
529 "WWW-Authenticate: Negotiate foo\n"
530 "WWW-Authenticate: Negotiate\n",
531 "negotiate continuation,foo"))));
532
533 // As above. The first challenge in the second round counts as a rejection, so
534 // the controller should create a new handler and restart the handshake.
535 INSTANTIATE_TEST_CASE_P(
536 MultiRoundAuth_ContinuationsWithMultipleChallengesAndRejection,
537 HttpAuthControllerTest,
538 ValuesIn(SyncAndAsync(
539 ChallengeResponseTestCase()
540 .WithChallengeResponse("HTTP/1.1 401\n"
541 "WWW-Authenticate: Negotiate\n",
542 "negotiate auth_token")
543 .WithHandler("negotiate", OK, OK)
544 .WithChallengeResponse("HTTP/1.1 401\n"
545 "WWW-Authenticate: Negotiate\n"
546 "WWW-Authenticate: Negotiate continuation\n",
547 "negotiate auth_token")
548 .WithHandler("negotiate", OK, OK))));
549
550 // Multiround authentication with rejection. The rejection comes in the form of
551 // an empty challenge for the same scheme.
552 INSTANTIATE_TEST_CASE_P(
553 MultiRoundAuth_RejectionViaEmptyChallenge,
554 HttpAuthControllerTest,
555 ValuesIn(
556 SyncAndAsync(ChallengeResponseTestCase()
557 .WithChallengeResponse("HTTP/1.1 401\n"
558 "WWW-Authenticate: Negotiate\n",
559 "negotiate auth_token")
560 .WithHandler("negotiate", OK, OK)
561 .WithChallengeResponse("HTTP/1.1 401\n"
562 "WWW-Authenticate: Negotiate\n",
563 "negotiate auth_token")
564 .WithHandler("negotiate", OK, OK)
565 .WithChallengeResponse("HTTP/1.1 401\n"
566 "WWW-Authenticate: Negotiate\n",
567 "negotiate auth_token")
568 .WithHandler("negotiate", OK, OK))));
569
570 // Multiround authentication with rejection. The rejection comes in the form of
571 // a response with no challenge for the original scheme.
572 INSTANTIATE_TEST_CASE_P(
573 MultiRoundAuth_RejectionViaSchemeChange,
574 HttpAuthControllerTest,
575 ValuesIn(
576 SyncAndAsync(ChallengeResponseTestCase()
577 .WithChallengeResponse("HTTP/1.1 401\n"
578 "WWW-Authenticate: Negotiate\n",
579 "negotiate auth_token")
580 .WithHandler("negotiate", OK, OK)
581 .WithChallengeResponse("HTTP/1.1 401\n"
582 "WWW-Authenticate: Basic foo\n",
583 "basic auth_token,foo")
584 .WithHandler("basic", OK, OK))));
585
586 // Dealing with empty and missing second round challenges for connection
587 // oriented schemes.
588 INSTANTIATE_TEST_CASE_P(
589 MultiRoundAuth_EmptySecondChallenge,
590 HttpAuthControllerTest,
591 ValuesIn(
592 SyncAndAsync(ChallengeResponseTestCase()
593 .WithChallengeResponse("HTTP/1.1 401\n"
594 "WWW-Authenticate: Negotiate\n",
595 "negotiate auth_token")
596 .WithHandler("negotiate", OK, OK)
597 .WithChallengeResponse("HTTP/1.1 401\n"
598 "WWW-Authenticate:\n",
599 ""))));
600 INSTANTIATE_TEST_CASE_P(
601 MultiRoundAuth_MissingSecondChallenge,
602 HttpAuthControllerTest,
603 ValuesIn(
604 SyncAndAsync(ChallengeResponseTestCase()
605 .WithChallengeResponse("HTTP/1.1 401\n"
606 "WWW-Authenticate: Negotiate\n",
607 "negotiate auth_token")
608 .WithHandler("negotiate", OK, OK)
609 .WithChallengeResponse("HTTP/1.1 401\n", ""))));
610
611 // Should pick matching challenge even if other challenges are present.
612 INSTANTIATE_TEST_CASE_P(
613 MultiRoundAuth_PicksCorrectChallenge,
614 HttpAuthControllerTest,
615 ValuesIn(SyncAndAsync(
616 ChallengeResponseTestCase()
617 .WithChallengeResponse("HTTP/1.1 401\n"
618 "WWW-Authenticate: Negotiate\n",
619 "negotiate auth_token")
620 .WithHandler("negotiate", OK, OK)
621 .WithChallengeResponse("HTTP/1.1 401\n"
622 "WWW-Authenticate: Basic foo\n"
623 "WWW-Authenticate: Negotiate bar\n",
624 "negotiate continuation,bar"))));
625 INSTANTIATE_TEST_CASE_P(
626 MultiRoundAuth_PicksCorrectChallengeWithPreferredChallenge,
627 HttpAuthControllerTest,
628 ValuesIn(
629 SyncAndAsync(ChallengeResponseTestCase()
630 .WithChallengeResponse("HTTP/1.1 401\n"
631 "WWW-Authenticate: NTLM\n",
632 "ntlm auth_token")
633 .WithHandler("ntlm", OK, OK)
634 .WithChallengeResponse("HTTP/1.1 401\n"
635 "WWW-Authenticate: Negotiate\n"
636 "WWW-Authenticate: NTLM bar\n",
637 "ntlm continuation,bar"))));
638
639 // If an auth handler fails to initialize, the controller should try the next
640 // suitable challenge.
641 INSTANTIATE_TEST_CASE_P(
642 FallThroughInvalidHeaders,
643 HttpAuthControllerTest,
644 ValuesIn(SyncAndAsync(
645 ChallengeResponseTestCase()
646 .WithChallengeResponse("HTTP/1.1 401\n"
647 "WWW-Authenticate: Basic abc;\n"
648 "WWW-Authenticate: Digest abc;\n"
649 "WWW-Authenticate: Basic valid",
650 "basic auth_token,valid")
651 // The first challenge chosen is Digest. But the handler fails.
652 .WithHandler("digest", ERR_INVALID_AUTH_CREDENTIALS, OK)
653 // Next the controller tries the first Basic challenge, which also
654 // fails.
655 .WithHandler("basic", ERR_INVALID_AUTH_CREDENTIALS, OK)
656 // Finally, the second Basic challenge succeeds.
657 .WithHandler("basic", OK, OK))));
658
659 // Identities are used in the correct order.
660 TEST(HttpAuthControllerTest, IdentityPriorityOrder) {}
661
662 // Identities from abstract sources should be available to a new handler if the
663 // server changes authentication scheme or if all identity sources were
664 // exhausted for a handler.
665 TEST(HttpAuthControllerTest, IdentityReuseAcrossHandlers) {}
666
199 } // namespace net 667 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_controller.cc ('k') | net/http/http_auth_gssapi_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698