Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

WinHttpHandler: Check available credentials when choosing authentication scheme #28105

Merged
merged 5 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void CheckResponseForAuthentication(
// But we can validate with assert.
Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);

serverAuthScheme = ChooseAuthScheme(supportedSchemes);
serverAuthScheme = ChooseAuthScheme(supportedSchemes, state.RequestMessage.RequestUri, state.ServerCredentials);
if (serverAuthScheme != 0)
{
if (SetWinHttpCredential(
Expand Down Expand Up @@ -155,7 +155,7 @@ public void CheckResponseForAuthentication(
// But we can validate with assert.
Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);

proxyAuthScheme = ChooseAuthScheme(supportedSchemes);
proxyAuthScheme = ChooseAuthScheme(supportedSchemes, state.Proxy.GetProxy(state.RequestMessage.RequestUri), proxyCreds);
state.RetryRequest = true;
break;

Expand Down Expand Up @@ -371,11 +371,16 @@ private bool SetWinHttpCredential(
return true;
}

private static uint ChooseAuthScheme(uint supportedSchemes)
private static uint ChooseAuthScheme(uint supportedSchemes, Uri uri, ICredentials credentials)
{
if (credentials == null)
{
return 0;
}

foreach (uint authScheme in s_authSchemePriorityOrder)
{
if ((supportedSchemes & authScheme) != 0)
if ((supportedSchemes & authScheme) != 0 && credentials.GetCredential(uri, s_authSchemeStringMapping[authScheme]) != null)
{
return authScheme;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public abstract class HttpClientHandler_Authentication_Test : HttpClientTestBase

private static readonly NetworkCredential s_credentials = new NetworkCredential(Username, Password, Domain);

private static readonly Func<HttpClientHandler, Uri, HttpStatusCode, NetworkCredential, Task> s_createAndValidateRequest = async (handler, url, expectedStatusCode, credentials) =>
private static readonly Func<HttpClientHandler, Uri, HttpStatusCode, ICredentials, Task> s_createAndValidateRequest = async (handler, url, expectedStatusCode, credentials) =>
{
handler.Credentials = credentials;

Expand Down Expand Up @@ -90,6 +90,31 @@ await LoopbackServer.CreateServerAsync(async (server, url) =>
}, options);
}

[Theory]
[InlineData("WWW-Authenticate: Basic realm=\"hello\"\r\nWWW-Authenticate: Negotiate\r\nx-identifier: Test\r\n", "Basic")]
[InlineData("WWW-Authenticate: Basic realm=\"hello\"\r\nWWW-Authenticate: Digest realm=\"hello\", nonce=\"hello\", algorithm=MD5\r\nWWW-Authenticate: Negotiate\r\nx-identifier: Test\r\n", "Digest")]
public async Task HttpClientHandler_MultipleAuthenticateHeaders_PicksSupported(string authenticateHeader, string supportedAuth)
{
if (IsCurlHandler && authenticateHeader.Contains("Digest"))
{
// TODO: #28065: Fix failing authentication test cases on different httpclienthandlers.
return;
}

var options = new LoopbackServer.Options { Domain = Domain, Username = Username, Password = Password };
await LoopbackServer.CreateServerAsync(async (server, url) =>
{
HttpClientHandler handler = CreateHttpClientHandler();

var credentials = new CredentialCache();
credentials.Add(url, supportedAuth, new NetworkCredential(Username, Password, Domain));
handler.UseDefaultCredentials = false;

Task serverTask = server.AcceptConnectionPerformAuthenticationAndCloseAsync(authenticateHeader);
await TestHelper.WhenAllCompletedOrAnyFailed(s_createAndValidateRequest(handler, url, HttpStatusCode.OK, credentials), serverTask);
}, options);
}

[Theory]
[InlineData("WWW-Authenticate: Basic realm=\"hello\"\r\n")]
[InlineData("WWW-Authenticate: Digest realm=\"hello\", nonce=\"testnonce\"\r\n")]
Expand Down