private async Task <ICredentials> PromptForCredentialsAsync( CredentialRequestType type, string message, CancellationToken token) { ICredentials promptCredentials = null; if (HttpHandlerResourceV3.PromptForCredentialsAsync != null) { try { // Only one prompt may display at a time. await _credentialPromptLock.WaitAsync(); promptCredentials = await HttpHandlerResourceV3.PromptForCredentialsAsync(_baseUri, type, message, token); } catch (TaskCanceledException) { throw; // pass-thru } catch (OperationCanceledException) { // A valid response for VS dialog when user hits cancel button promptCredentials = null; } finally { _credentialPromptLock.Release(); } } return(promptCredentials); }
public override Task <Tuple <bool, INuGetResource> > TryCreate(SourceRepository source, CancellationToken token) { Debug.Assert(source.PackageSource.IsHttp, "HTTP handler requested for a non-http source."); HttpHandlerResourceV3 curResource = null; if (source.PackageSource.IsHttp) { curResource = CreateResource(source.PackageSource); } return(Task.FromResult(new Tuple <bool, INuGetResource>(curResource != null, curResource))); }
private static HttpHandlerResourceV3 CreateResource(PackageSource packageSource) { var sourceUri = packageSource.SourceUri; var proxy = ProxyCache.Instance.GetProxy(sourceUri); // replace the handler with the proxy aware handler var clientHandler = new HttpClientHandler { Proxy = proxy, AutomaticDecompression = (DecompressionMethods.GZip | DecompressionMethods.Deflate) }; // Setup http client handler client certificates if (packageSource.ClientCertificates != null) { clientHandler.ClientCertificates.AddRange(packageSource.ClientCertificates.ToArray()); } // HTTP handler pipeline can be injected here, around the client handler HttpMessageHandler messageHandler = new ServerWarningLogHandler(clientHandler); if (proxy != null) { messageHandler = new ProxyAuthenticationHandler(clientHandler, HttpHandlerResourceV3.CredentialService?.Value, ProxyCache.Instance); } #if !IS_CORECLR { var innerHandler = messageHandler; messageHandler = new StsAuthenticationHandler(packageSource, TokenStore.Instance) { InnerHandler = messageHandler }; } #endif { var innerHandler = messageHandler; messageHandler = new HttpSourceAuthenticationHandler(packageSource, clientHandler, HttpHandlerResourceV3.CredentialService?.Value) { InnerHandler = innerHandler }; } var resource = new HttpHandlerResourceV3(clientHandler, messageHandler); return(resource); }
private async Task <ICredentials> PromptForCredentials(CancellationToken cancellationToken) { ICredentials promptCredentials = null; if (HttpHandlerResourceV3.PromptForCredentials != null) { try { // Only one prompt may display at a time. await _credentialPromptLock.WaitAsync(); promptCredentials = await HttpHandlerResourceV3.PromptForCredentials(_baseUri, cancellationToken); } finally { _credentialPromptLock.Release(); } } return(promptCredentials); }
private static HttpHandlerResourceV3 CreateResource(PackageSource packageSource) { var uri = packageSource.SourceUri; var proxy = ProxyCache.Instance.GetProxy(uri); // replace the handler with the proxy aware handler var clientHandler = new HttpClientHandler { Proxy = proxy, AutomaticDecompression = (DecompressionMethods.GZip | DecompressionMethods.Deflate) }; // HTTP handler pipeline can be injected here, around the client handler HttpMessageHandler messageHandler = clientHandler; if (proxy != null && HttpHandlerResourceV3.CredentialSerivce != null) { messageHandler = new ProxyCredentialHandler(clientHandler, HttpHandlerResourceV3.CredentialSerivce, ProxyCache.Instance); } var resource = new HttpHandlerResourceV3(clientHandler, messageHandler); return(resource); }
private async Task <HttpResponseMessage> SendWithCredentialSupportAsync( Func <HttpRequestMessage> requestFactory, HttpCompletionOption completionOption, ILogger log, CancellationToken cancellationToken) { HttpResponseMessage response = null; ICredentials promptCredentials = null; // Create the http client on the first call if (_httpClient == null) { await _httpClientLock.WaitAsync(); try { // Double check if (_httpClient == null) { await UpdateHttpClient(); } } finally { _httpClientLock.Release(); } } // Update the request for STS Func <HttpRequestMessage> requestWithStsFactory = () => { var request = requestFactory(); STSAuthHelper.PrepareSTSRequest(_baseUri, CredentialStore.Instance, request); return(request); }; // Authorizing may take multiple attempts while (true) { // Clean up any previous responses if (response != null) { response.Dispose(); } // store the auth state before sending the request var beforeLockId = _lastAuthId; // Read the response headers before reading the entire stream to avoid timeouts from large packages. response = await _retryHandler.SendAsync( _httpClient, requestWithStsFactory, completionOption, log, cancellationToken); if (response.StatusCode == HttpStatusCode.Unauthorized) { try { // Only one request may prompt and attempt to auth at a time await _httpClientLock.WaitAsync(); // Auth may have happened on another thread, if so just continue if (beforeLockId != _lastAuthId) { continue; } // Give up after 3 tries. _authRetries++; if (_authRetries > 3) { return(response); } // Windows auth if (STSAuthHelper.TryRetrieveSTSToken(_baseUri, CredentialStore.Instance, response)) { // Auth token found, create a new message handler and retry. await UpdateHttpClient(); continue; } // Prompt the user promptCredentials = await PromptForCredentials(cancellationToken); if (promptCredentials != null) { // The user entered credentials, create a new message handler that includes // these and retry. await UpdateHttpClient(promptCredentials); continue; } } finally { _httpClientLock.Release(); } } if (promptCredentials != null && HttpHandlerResourceV3.CredentialsSuccessfullyUsed != null) { HttpHandlerResourceV3.CredentialsSuccessfullyUsed(_baseUri, promptCredentials); } return(response); } }
private async Task <HttpResponseMessage> SendWithCredentialSupportAsync( Func <HttpRequestMessage> requestFactory, ILogger log, CancellationToken cancellationToken) { HttpResponseMessage response = null; ICredentials promptCredentials = null; // Create the http client on the first call if (_httpClient == null) { await _httpClientLock.WaitAsync(); try { // Double check if (_httpClient == null) { await UpdateHttpClientAsync(); } } finally { _httpClientLock.Release(); } } // Update the request for STS Func <HttpRequestMessage> requestWithStsFactory = () => { var request = requestFactory(); STSAuthHelper.PrepareSTSRequest(_baseUri, CredentialStore.Instance, request); return(request); }; // Authorizing may take multiple attempts while (true) { // Clean up any previous responses if (response != null) { response.Dispose(); } // store the auth state before sending the request var beforeLockId = _lastAuthId; // Read the response headers before reading the entire stream to avoid timeouts from large packages. response = await RetryHandler.SendAsync( _httpClient, requestWithStsFactory, HttpCompletionOption.ResponseHeadersRead, log, cancellationToken); if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden) { try { // Only one request may prompt and attempt to auth at a time await _httpClientLock.WaitAsync(); // Auth may have happened on another thread, if so just continue if (beforeLockId != _lastAuthId) { continue; } var authState = GetAuthenticationState(); authState.Increment(); if (authState.IsBlocked) { return(response); } // Windows auth if (response.StatusCode == HttpStatusCode.Unauthorized && STSAuthHelper.TryRetrieveSTSToken(_baseUri, CredentialStore.Instance, response)) { // Auth token found, create a new message handler and retry. await UpdateHttpClientAsync(); continue; } // Prompt the user CredentialRequestType type; string message; if (response.StatusCode == HttpStatusCode.Unauthorized) { type = CredentialRequestType.Unauthorized; message = string.Format( CultureInfo.CurrentCulture, Strings.Http_CredentialsForUnauthorized, _packageSource.Source); } else { type = CredentialRequestType.Forbidden; message = string.Format( CultureInfo.CurrentCulture, Strings.Http_CredentialsForForbidden, _packageSource.Source); } promptCredentials = await PromptForCredentialsAsync( type, message, cancellationToken); if (promptCredentials != null) { // The user entered credentials, create a new message handler that includes // these and retry. await UpdateHttpClientAsync(promptCredentials); continue; } // null means cancelled by user // block subsequent attempts to annoy user with prompts authState.IsBlocked = true; return(response); } finally { _httpClientLock.Release(); } } if (promptCredentials != null && HttpHandlerResourceV3.CredentialsSuccessfullyUsed != null) { HttpHandlerResourceV3.CredentialsSuccessfullyUsed(_baseUri, promptCredentials); } return(response); } }