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

Side by Side Diff: net/http/http_auth_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_handler_unittest.cc ('k') | net/http/http_network_transaction.h » ('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 <set>
6 #include <string> 5 #include <string>
7 6
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "net/base/net_errors.h"
12 #include "net/dns/mock_host_resolver.h"
13 #include "net/http/http_auth.h" 7 #include "net/http/http_auth.h"
14 #include "net/http/http_auth_challenge_tokenizer.h"
15 #include "net/http/http_auth_filter.h"
16 #include "net/http/http_auth_handler.h"
17 #include "net/http/http_auth_handler_factory.h"
18 #include "net/http/http_auth_handler_mock.h"
19 #include "net/http/http_auth_scheme_set.h"
20 #include "net/http/http_response_headers.h"
21 #include "net/http/http_util.h"
22 #include "net/http/mock_allow_url_security_manager.h"
23 #include "testing/gtest/include/gtest/gtest.h" 8 #include "testing/gtest/include/gtest/gtest.h"
24 9
25 namespace net { 10 namespace net {
26 11
27 namespace {
28
29 HttpAuthHandlerMock* CreateMockHandler(bool expect_multiple_challenges) {
30 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
31 auth_handler->set_expect_multiple_challenges(expect_multiple_challenges);
32 std::string challenge_text = "Mock";
33 HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
34 challenge_text.end());
35 GURL origin("www.example.com");
36 EXPECT_EQ(OK, auth_handler->HandleInitialChallenge(
37 challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog()));
38 return auth_handler;
39 }
40
41 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) {
42 return new HttpResponseHeaders(
43 HttpUtil::AssembleRawHeaders(response.c_str(), response.length()));
44 }
45
46 HttpAuth::AuthorizationResult HandleChallengeResponse(
47 bool expect_multiple_challenges,
48 const std::string& headers_text,
49 std::string* challenge_used) {
50 scoped_ptr<HttpAuthHandlerMock> mock_handler(
51 CreateMockHandler(expect_multiple_challenges));
52 HttpAuthSchemeSet disabled_schemes;
53 scoped_refptr<HttpResponseHeaders> headers(
54 HeadersFromResponseText(headers_text));
55 return HttpAuth::HandleChallengeResponse(mock_handler.get(), headers.get(),
56 HttpAuth::AUTH_SERVER,
57 disabled_schemes, challenge_used);
58 }
59
60 } // namespace
61
62 TEST(HttpAuthTest, ChooseBestChallenge) {
63 static const struct {
64 const char* headers;
65 const char* challenge_scheme;
66 const char* challenge_realm;
67 } tests[] = {
68 {
69 // Basic is the only challenge type, pick it.
70 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
71 "www-authenticate: Basic realm=\"BasicRealm\"\n",
72
73 "basic", "BasicRealm",
74 },
75 {
76 // Fake is the only challenge type, but it is unsupported.
77 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
78 "www-authenticate: Fake realm=\"FooBar\"\n",
79
80 nullptr, "",
81 },
82 {
83 // Pick Digest over Basic.
84 "www-authenticate: Basic realm=\"FooBar\"\n"
85 "www-authenticate: Fake realm=\"FooBar\"\n"
86 "www-authenticate: nonce=\"aaaaaaaaaa\"\n"
87 "www-authenticate: Digest realm=\"DigestRealm\", "
88 "nonce=\"aaaaaaaaaa\"\n",
89
90 "digest", "DigestRealm",
91 },
92 {
93 // Handle an empty header correctly.
94 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
95 "www-authenticate:\n",
96
97 nullptr, "",
98 },
99 {
100 // NTLM appears earlier in the list, but HttAuth should pick
101 // Negotiate.
102 "WWW-Authenticate: NTLM\n"
103 "WWW-Authenticate: Negotiate\n",
104
105 #if defined(USE_KERBEROS) && !defined(OS_ANDROID)
106 // Choose Negotiate over NTLM on all platforms.
107 // TODO(ahendrickson): This may be flaky on Linux and OSX as it
108 // relies on being able to load one of the known .so files
109 // for gssapi.
110 "negotiate",
111 #else
112 // On systems that don't use Kerberos fall back to NTLM.
113 "ntlm",
114 #endif // defined(USE_KERBEROS)
115 "",
116 }};
117 GURL origin("http://www.example.com");
118 HttpAuthSchemeSet disabled_schemes;
119 MockAllowURLSecurityManager url_security_manager;
120 scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
121 scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
122 HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
123 http_auth_handler_factory->SetURLSecurityManager(
124 "negotiate", &url_security_manager);
125
126 for (size_t i = 0; i < arraysize(tests); ++i) {
127 // Make a HttpResponseHeaders object.
128 std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n");
129 headers_with_status_line += tests[i].headers;
130 scoped_refptr<HttpResponseHeaders> headers(
131 HeadersFromResponseText(headers_with_status_line));
132
133 scoped_ptr<HttpAuthHandler> handler;
134 HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(),
135 headers.get(),
136 HttpAuth::AUTH_SERVER,
137 origin,
138 disabled_schemes,
139 BoundNetLog(),
140 &handler);
141
142 if (handler.get()) {
143 EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme());
144 EXPECT_STREQ(tests[i].challenge_realm, handler->realm().c_str());
145 } else {
146 EXPECT_EQ(nullptr, tests[i].challenge_scheme);
147 EXPECT_STREQ("", tests[i].challenge_realm);
148 }
149 }
150 }
151
152 TEST(HttpAuthTest, HandleChallengeResponse) {
153 std::string challenge_used;
154 const char* const kMockChallenge =
155 "HTTP/1.1 401 Unauthorized\n"
156 "WWW-Authenticate: Mock token_here\n";
157 const char* const kBasicChallenge =
158 "HTTP/1.1 401 Unauthorized\n"
159 "WWW-Authenticate: Basic realm=\"happy\"\n";
160 const char* const kMissingChallenge =
161 "HTTP/1.1 401 Unauthorized\n";
162 const char* const kEmptyChallenge =
163 "HTTP/1.1 401 Unauthorized\n"
164 "WWW-Authenticate: \n";
165 const char* const kBasicAndMockChallenges =
166 "HTTP/1.1 401 Unauthorized\n"
167 "WWW-Authenticate: Basic realm=\"happy\"\n"
168 "WWW-Authenticate: Mock token_here\n";
169 const char* const kTwoMockChallenges =
170 "HTTP/1.1 401 Unauthorized\n"
171 "WWW-Authenticate: Mock token_a\n"
172 "WWW-Authenticate: Mock token_b\n";
173
174 // Request based schemes should treat any new challenges as rejections of the
175 // previous authentication attempt. (There is a slight exception for digest
176 // authentication and the stale parameter, but that is covered in the
177 // http_auth_handler_digest_unittests).
178 EXPECT_EQ(
179 HttpAuth::AUTHORIZATION_RESULT_REJECT,
180 HandleChallengeResponse(false, kMockChallenge, &challenge_used));
181 EXPECT_EQ("Mock token_here", challenge_used);
182
183 EXPECT_EQ(
184 HttpAuth::AUTHORIZATION_RESULT_REJECT,
185 HandleChallengeResponse(false, kBasicChallenge, &challenge_used));
186 EXPECT_EQ("", challenge_used);
187
188 EXPECT_EQ(
189 HttpAuth::AUTHORIZATION_RESULT_REJECT,
190 HandleChallengeResponse(false, kMissingChallenge, &challenge_used));
191 EXPECT_EQ("", challenge_used);
192
193 EXPECT_EQ(
194 HttpAuth::AUTHORIZATION_RESULT_REJECT,
195 HandleChallengeResponse(false, kEmptyChallenge, &challenge_used));
196 EXPECT_EQ("", challenge_used);
197
198 EXPECT_EQ(
199 HttpAuth::AUTHORIZATION_RESULT_REJECT,
200 HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used));
201 EXPECT_EQ("Mock token_here", challenge_used);
202
203 EXPECT_EQ(
204 HttpAuth::AUTHORIZATION_RESULT_REJECT,
205 HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used));
206 EXPECT_EQ("Mock token_a", challenge_used);
207
208 // Connection based schemes will treat new auth challenges for the same scheme
209 // as acceptance (and continuance) of the current approach. If there are
210 // no auth challenges for the same scheme, the response will be treated as
211 // a rejection.
212 EXPECT_EQ(
213 HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
214 HandleChallengeResponse(true, kMockChallenge, &challenge_used));
215 EXPECT_EQ("Mock token_here", challenge_used);
216
217 EXPECT_EQ(
218 HttpAuth::AUTHORIZATION_RESULT_REJECT,
219 HandleChallengeResponse(true, kBasicChallenge, &challenge_used));
220 EXPECT_EQ("", challenge_used);
221
222 EXPECT_EQ(
223 HttpAuth::AUTHORIZATION_RESULT_REJECT,
224 HandleChallengeResponse(true, kMissingChallenge, &challenge_used));
225 EXPECT_EQ("", challenge_used);
226
227 EXPECT_EQ(
228 HttpAuth::AUTHORIZATION_RESULT_REJECT,
229 HandleChallengeResponse(true, kEmptyChallenge, &challenge_used));
230 EXPECT_EQ("", challenge_used);
231
232 EXPECT_EQ(
233 HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
234 HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used));
235 EXPECT_EQ("Mock token_here", challenge_used);
236
237 EXPECT_EQ(
238 HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
239 HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used));
240 EXPECT_EQ("Mock token_a", challenge_used);
241 }
242
243 TEST(HttpAuthTest, GetChallengeHeaderName) { 12 TEST(HttpAuthTest, GetChallengeHeaderName) {
244 std::string name; 13 std::string name;
245 14
246 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER); 15 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER);
247 EXPECT_STREQ("WWW-Authenticate", name.c_str()); 16 EXPECT_STREQ("WWW-Authenticate", name.c_str());
248 17
249 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY); 18 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY);
250 EXPECT_STREQ("Proxy-Authenticate", name.c_str()); 19 EXPECT_STREQ("Proxy-Authenticate", name.c_str());
251 } 20 }
252 21
253 TEST(HttpAuthTest, GetAuthorizationHeaderName) { 22 TEST(HttpAuthTest, GetAuthorizationHeaderName) {
254 std::string name; 23 std::string name;
255 24
256 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER); 25 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER);
257 EXPECT_STREQ("Authorization", name.c_str()); 26 EXPECT_STREQ("Authorization", name.c_str());
258 27
259 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY); 28 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY);
260 EXPECT_STREQ("Proxy-Authorization", name.c_str()); 29 EXPECT_STREQ("Proxy-Authorization", name.c_str());
261 } 30 }
262 31
263 } // namespace net 32 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_unittest.cc ('k') | net/http/http_network_transaction.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698