Beispiel #1
0
        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);
        }
Beispiel #2
0
        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)));
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #7
0
        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);
            }
        }