This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split auth and redirect handling back into two separate handlers
- Loading branch information
Geoff Kizer
committed
Feb 20, 2018
1 parent
d4534e7
commit e8a1771
Showing
5 changed files
with
266 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
232 changes: 0 additions & 232 deletions
232
src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticateAndRedirectHandler.cs
This file was deleted.
Oops, something went wrong.
125 changes: 125 additions & 0 deletions
125
src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Diagnostics; | ||
using System.Net.Http.Headers; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace System.Net.Http | ||
{ | ||
internal sealed partial class AuthenticationHandler : HttpMessageHandler | ||
{ | ||
private readonly HttpMessageHandler _innerHandler; | ||
private readonly bool _preAuthenticate; | ||
private readonly ICredentials _credentials; | ||
|
||
public AuthenticationHandler(bool preAuthenticate, ICredentials credentials, HttpMessageHandler innerHandler) | ||
{ | ||
Debug.Assert(innerHandler != null); | ||
Debug.Assert(credentials != null); | ||
|
||
_preAuthenticate = preAuthenticate; | ||
_credentials = credentials; | ||
_innerHandler = innerHandler; | ||
} | ||
|
||
protected internal override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
if (_preAuthenticate) | ||
{ | ||
AuthenticationHelper.TrySetBasicAuthToken(request, _credentials); | ||
} | ||
|
||
HttpResponseMessage response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); | ||
|
||
if (response.StatusCode == HttpStatusCode.Unauthorized) | ||
{ | ||
AuthenticationHeaderValue selectedAuth = GetSupportedAuthScheme(response.Headers.WwwAuthenticate); | ||
if (selectedAuth != null) | ||
{ | ||
switch (selectedAuth.Scheme) | ||
{ | ||
case AuthenticationHelper.Digest: | ||
// Update digest response with new parameter from WWWAuthenticate | ||
var digestResponse = new AuthenticationHelper.DigestResponse(selectedAuth.Parameter); | ||
if (await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false)) | ||
{ | ||
response.Dispose(); | ||
response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); | ||
|
||
// Retry in case of nonce timeout in server. | ||
if (response.StatusCode == HttpStatusCode.Unauthorized) | ||
{ | ||
foreach (AuthenticationHeaderValue ahv in response.Headers.WwwAuthenticate) | ||
{ | ||
if (ahv.Scheme == AuthenticationHelper.Digest) | ||
{ | ||
digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter); | ||
if (AuthenticationHelper.IsServerNonceStale(digestResponse) && | ||
await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false)) | ||
{ | ||
response.Dispose(); | ||
response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
break; | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
|
||
case AuthenticationHelper.Basic: | ||
if (_preAuthenticate) | ||
{ | ||
// We already tried these credentials via preauthentication, so no need to try again | ||
break; | ||
} | ||
|
||
if (AuthenticationHelper.TrySetBasicAuthToken(request, _credentials)) | ||
{ | ||
response.Dispose(); | ||
response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return response; | ||
} | ||
|
||
private static AuthenticationHeaderValue GetSupportedAuthScheme(HttpHeaderValueCollection<AuthenticationHeaderValue> authenticateValues) | ||
{ | ||
AuthenticationHeaderValue basicAuthenticationHeaderValue = null; | ||
|
||
// Only Digest and Basic auth supported, ignore others. | ||
foreach (AuthenticationHeaderValue ahv in authenticateValues) | ||
{ | ||
if (ahv.Scheme == AuthenticationHelper.Digest) | ||
{ | ||
return ahv; | ||
} | ||
else if (ahv.Scheme == AuthenticationHelper.Basic) | ||
{ | ||
basicAuthenticationHeaderValue = ahv; | ||
} | ||
} | ||
|
||
return basicAuthenticationHeaderValue; | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
if (disposing) | ||
{ | ||
_innerHandler.Dispose(); | ||
} | ||
|
||
base.Dispose(disposing); | ||
} | ||
} | ||
} | ||
|
Oops, something went wrong.