Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit e6ef080

Browse files
committed
Merge pull request #2463 from davidsh/proxyauthfix
Fix proxy authentication handling during redirects
2 parents c00a2f6 + 826d302 commit e6ef080

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,17 @@ private static void WinHttpStatusCallback(
717717
}
718718

719719
state.RequestMessage.RequestUri = redirectUri;
720+
721+
// Redirection to a new uri may require a new connection through a potentially different proxy.
722+
// If so, we will need to respond to additional 407 proxy auth demands and re-attach any
723+
// proxy credentials. The ProcessResponse() method looks at the state.LastStatusCode
724+
// before attaching proxy credentials and marking the HTTP request to be re-submitted.
725+
// So we need to reset the LastStatusCode remembered. Otherwise, it will see additional 407
726+
// responses as an indication that proxy auth failed and won't retry the HTTP request.
727+
if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
728+
{
729+
state.LastStatusCode = 0;
730+
}
720731

721732
// For security reasons, we drop the server credential if it is a
722733
// NetworkCredential. But we allow credentials in a CredentialCache
@@ -1147,14 +1158,13 @@ private async void StartRequest(object obj)
11471158

11481159
uint proxyAuthScheme = 0;
11491160
uint serverAuthScheme = 0;
1150-
HttpStatusCode lastStatusCode = 0;
11511161
bool retryRequest = false;
11521162

11531163
do
11541164
{
11551165
state.CancellationToken.ThrowIfCancellationRequested();
11561166

1157-
PreAuthenticateRequest(state, requestHandle, proxyAuthScheme, ref lastStatusCode);
1167+
PreAuthenticateRequest(state, requestHandle, proxyAuthScheme);
11581168

11591169
// Send a request.
11601170
if (!Interop.WinHttp.WinHttpSendRequest(
@@ -1211,7 +1221,6 @@ await state.RequestMessage.Content.CopyToAsync(
12111221
requestHandle,
12121222
ref proxyAuthScheme,
12131223
ref serverAuthScheme,
1214-
ref lastStatusCode,
12151224
out retryRequest);
12161225
}
12171226
} while (retryRequest);
@@ -1276,7 +1285,6 @@ private void ProcessResponse(
12761285
SafeWinHttpHandle requestHandle,
12771286
ref uint proxyAuthScheme,
12781287
ref uint serverAuthScheme,
1279-
ref HttpStatusCode lastStatusCode,
12801288
out bool retryRequest)
12811289
{
12821290
retryRequest = false;
@@ -1293,14 +1301,14 @@ private void ProcessResponse(
12931301
switch (statusCode)
12941302
{
12951303
case HttpStatusCode.Unauthorized:
1296-
if (state.ServerCredentials == null || lastStatusCode == HttpStatusCode.Unauthorized)
1304+
if (state.ServerCredentials == null || state.LastStatusCode == HttpStatusCode.Unauthorized)
12971305
{
12981306
// Either we don't have server credentials or we already tried
12991307
// to set the credentials and it failed before.
13001308
// So we will let the 401 be the final status code returned.
13011309
break;
13021310
}
1303-
lastStatusCode = statusCode;
1311+
state.LastStatusCode = statusCode;
13041312

13051313
// Determine authorization scheme to use. We ignore the firstScheme
13061314
// parameter which is included in the supportedSchemes flags already.
@@ -1337,12 +1345,12 @@ private void ProcessResponse(
13371345
break;
13381346

13391347
case HttpStatusCode.ProxyAuthenticationRequired:
1340-
if (lastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
1348+
if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
13411349
{
13421350
// We tried already to set the credentials.
13431351
break;
13441352
}
1345-
lastStatusCode = statusCode;
1353+
state.LastStatusCode = statusCode;
13461354

13471355
// Determine authorization scheme to use. We ignore the firstScheme
13481356
// parameter which is included in the supportedSchemes flags already.
@@ -1381,8 +1389,7 @@ private void ProcessResponse(
13811389
private void PreAuthenticateRequest(
13821390
RequestState state,
13831391
SafeWinHttpHandle requestHandle,
1384-
uint proxyAuthScheme,
1385-
ref HttpStatusCode lastStatusCode)
1392+
uint proxyAuthScheme)
13861393
{
13871394
// Set proxy credentials if we have them.
13881395
// If a proxy authentication challenge was responded to, reset
@@ -1416,7 +1423,7 @@ private void PreAuthenticateRequest(
14161423
state.RequestMessage.RequestUri,
14171424
authScheme,
14181425
Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);
1419-
lastStatusCode = HttpStatusCode.Unauthorized; // Remember we already set the creds.
1426+
state.LastStatusCode = HttpStatusCode.Unauthorized; // Remember we already set the creds.
14201427
}
14211428
}
14221429
}
@@ -2151,6 +2158,8 @@ public Func<
21512158
public IWebProxy Proxy { get; set; }
21522159

21532160
public ICredentials ServerCredentials { get; set; }
2161+
2162+
public HttpStatusCode LastStatusCode { get; set; }
21542163
}
21552164
}
21562165
}

0 commit comments

Comments
 (0)