private async Task <HttpResponseMessage> SendWithProxyAsync( Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken) { if (proxyUri.Scheme != UriScheme.Http) { throw new InvalidOperationException(SR.net_http_invalid_proxy_scheme); } if (!HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme)) { // TODO #23136: Implement SSL tunneling through proxy throw new NotImplementedException("no support for SSL tunneling through proxy"); } HttpConnection connection = await GetOrCreateConnection(request, proxyUri, cancellationToken).ConfigureAwait(false); HttpResponseMessage response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); // Handle proxy authentication if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate) { // We only support Basic auth, ignore others if (h.Scheme == AuthenticationHelper.Basic) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic); if (credential != null) { response.Dispose(); request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic, AuthenticationHelper.GetBasicTokenForCredential(credential)); connection = await GetOrCreateConnection(request, proxyUri, cancellationToken).ConfigureAwait(false); response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } else if (h.Scheme == AuthenticationHelper.Digest) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest); if (credential != null) { // Update digest response with new parameter from Proxy-Authenticate AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter); if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).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.ProxyAuthenticate) { if (ahv.Scheme == AuthenticationHelper.Digest) { digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter); if (AuthenticationHelper.IsServerNonceStale(digestResponse) && await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } } break; } } } } return(response); }
protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { HttpResponseMessage response; uint redirectCount = 0; while (true) { // Just as with WinHttpHandler and CurlHandler, for security reasons, we drop the server credential if it is // anything other than a CredentialCache on redirection. We allow credentials in a CredentialCache since they // are specifically tied to URIs. ICredentials currentCredential = redirectCount > 0 ? _credentials as CredentialCache : _credentials; if (currentCredential != null && _preAuthenticate) { // Try using previous digest response WWWAuthenticate header if (_digestResponse != null) { await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false); } else { AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential); } } response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); if (currentCredential != null && !_preAuthenticate && 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 _digestResponse = new AuthenticationHelper.DigestResponse(selectedAuth.Parameter); if (await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, _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, currentCredential, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } } break; case AuthenticationHelper.Basic: if (AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } if (!RequestNeedsRedirect(response)) { break; } // Clear the authorization header, if the request requires redirect. request.Headers.Authorization = null; Uri location = response.Headers.Location; if (location == null) { // No location header. Nothing to redirect to. break; } if (!location.IsAbsoluteUri) { location = new Uri(request.RequestUri, location); } // Disallow automatic redirection from secure to non-secure schemes bool allowed = (HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedScheme(location.Scheme)) || (HttpUtilities.IsSupportedSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedSecureScheme(location.Scheme)); if (!allowed) { break; } redirectCount++; if (redirectCount > _maxAutomaticRedirections) { throw new HttpRequestException(SR.net_http_max_redirects); } // Set up for the automatic redirect request.RequestUri = location; if (RequestRequiresForceGet(response.StatusCode, request.Method)) { request.Method = HttpMethod.Get; request.Content = null; } // Do the redirect. response.Dispose(); } return(response); }
protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (_preAuthenticate) { // Try using previous digest response WWWAuthenticate header if (_digestResponse != null) { await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false); } else { AuthenticationHelper.TrySetBasicAuthToken(request, _credentials); } } HttpResponseMessage response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); // In case of redirection, ensure _credentials as CredentialCache if (AutoRedirectHandler.RequestNeedsRedirect(response)) { // Just as with WinHttpHandler and CurlHandler, for security reasons, we drop the server credential if it is // anything other than a CredentialCache. We allow credentials in a CredentialCache since they // are specifically tied to URIs. _credentials = _credentials as CredentialCache; } else if (_credentials != null && !_preAuthenticate && response.StatusCode == HttpStatusCode.Unauthorized) { HttpHeaderValueCollection <AuthenticationHeaderValue> authenticateValues = response.Headers.WwwAuthenticate; foreach (AuthenticationHeaderValue h in authenticateValues) { // We only support Basic and digest auth, ignore others if (h.Scheme == AuthenticationHelper.Basic) { if (AuthenticationHelper.TrySetBasicAuthToken(request, _credentials)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); break; } } else if (h.Scheme == AuthenticationHelper.Digest) { // Update digest response with new parameter from WWWAuthenticate _digestResponse = new AuthenticationHelper.DigestResponse(h.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; } } } } return(response); }
private async Task <HttpResponseMessage> SendWithProxyAsync( Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken) { if (proxyUri.Scheme != UriScheme.Http) { throw new NotSupportedException(SR.net_http_invalid_proxy_scheme); } HttpResponseMessage response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); // Handle proxy authentication if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate) { if (h.Scheme == AuthenticationHelper.Basic) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic); if (credential != null) { // TODO #23156: Drain response before disposing. response.Dispose(); request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic, AuthenticationHelper.GetBasicTokenForCredential(credential)); response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); } break; } else if (h.Scheme == AuthenticationHelper.Digest) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest); if (credential != null) { // Update digest response with new parameter from Proxy-Authenticate AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter); if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { // TODO #23156: Drain response before disposing. response.Dispose(); response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); // Retry in case of nonce timeout in server. if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue ahv in response.Headers.ProxyAuthenticate) { if (ahv.Scheme == AuthenticationHelper.Digest) { digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter); if (AuthenticationHelper.IsServerNonceStale(digestResponse) && await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } } break; } } } } return(response); }
protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (_preAuthenticate) { // Try using previous digest response WWWAuthenticate header if (_digestResponse != null) { await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false); } else { AuthenticationHelper.TrySetBasicAuthToken(request, _credentials); } } HttpResponseMessage response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); if (!_preAuthenticate && response.StatusCode == HttpStatusCode.Unauthorized) { HttpHeaderValueCollection <AuthenticationHeaderValue> authenticateValues = response.Headers.WwwAuthenticate; foreach (AuthenticationHeaderValue h in authenticateValues) { // We only support Basic and digest auth, ignore others if (h.Scheme == AuthenticationHelper.Basic) { if (AuthenticationHelper.TrySetBasicAuthToken(request, _credentials)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); break; } } else if (h.Scheme == AuthenticationHelper.Digest) { // Update digest response with new parameter from WWWAuthenticate _digestResponse = new AuthenticationHelper.DigestResponse(h.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; } } } } return(response); }
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); }