New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom validation of server SSL Certificate to HttpClient API #4476

Closed
SidharthNabar opened this Issue Nov 12, 2015 · 25 comments

Comments

Projects
None yet
8 participants
@SidharthNabar

SidharthNabar commented Nov 12, 2015

This issue tracks the addition of new functionality to the HttpClient API. In order to implement certificate pinning and self-signed SSL certificate scenarios, developers need access to the SSL cert presented by the server, and the ability to do their own validation and then accept/reject the connection accordingly.

Today, this ability is provided in .NET Framework by ServicePointManager.ServerCertificateValidationCallback and in ASP.NET 5 by WinHttpHandler.ServerCertificateValidationCallback. However, ServicePointManager is not in .NET Core, and WinHttpHandler is not available x-plat and on all app models. Hence, there is a need to add this API to the top-level HttpClient or HttpClientHandler types.

If you have specific requirements around this scenario, please enter those here - we will track this issue in our backlog.

@SidharthNabar

This comment has been minimized.

Show comment
Hide comment

SidharthNabar commented Nov 12, 2015

@ericstj

This comment has been minimized.

Show comment
Hide comment
@ericstj

ericstj Nov 12, 2015

Member

Consider where you want this API change to go. If you want it to reach existing releases or desktop it will need to be on a new type / extension.

Member

ericstj commented Nov 12, 2015

Consider where you want this API change to go. If you want it to reach existing releases or desktop it will need to be on a new type / extension.

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh Nov 12, 2015

Member

We want it to be new properties on HttpClientHandler class.

The problem is that there is no such thing as "extension properties". There is only "extension methods".

Member

davidsh commented Nov 12, 2015

We want it to be new properties on HttpClientHandler class.

The problem is that there is no such thing as "extension properties". There is only "extension methods".

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 13, 2015

Member

The WinHttpHandler.ServerCertificateValidationCallback isn't compatible with the System.Net.Security.RemoteCertificationValidationCallback delegate..
System.Net.Security.RemoteCertificateValidationCallback delegate:

    public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors);

System.Net.Http.WinHttpHandler.ServerCertificateValidationCallback definition:

  public Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> ServerCertificateValidationCallback {  get; set;  }

As you can see, the sender is more strongly typed for WinHttpHandler, and uses X509Certificate2 vs X509Certificate. Can this be fixed before RTM to be more consistent?

Member

mconnew commented Nov 13, 2015

The WinHttpHandler.ServerCertificateValidationCallback isn't compatible with the System.Net.Security.RemoteCertificationValidationCallback delegate..
System.Net.Security.RemoteCertificateValidationCallback delegate:

    public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors);

System.Net.Http.WinHttpHandler.ServerCertificateValidationCallback definition:

  public Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> ServerCertificateValidationCallback {  get; set;  }

As you can see, the sender is more strongly typed for WinHttpHandler, and uses X509Certificate2 vs X509Certificate. Can this be fixed before RTM to be more consistent?

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh Nov 13, 2015

Member

/cc: @ericstj @weshaggard @stephentoub

@mconnew We do not plan to "fix" this. It is by-design.

The API review that we did for WinHttpHandler was very explicit about this point. We are not supporting the RemoteCertificateValidationCallback named delegate type. It will not appear in CoreFx.

Instead, we were explicitly told to only use Func style definitions moving forward. And we also used that as a reason to use X509Certificate2 instead of X509Certificate.

Member

davidsh commented Nov 13, 2015

/cc: @ericstj @weshaggard @stephentoub

@mconnew We do not plan to "fix" this. It is by-design.

The API review that we did for WinHttpHandler was very explicit about this point. We are not supporting the RemoteCertificateValidationCallback named delegate type. It will not appear in CoreFx.

Instead, we were explicitly told to only use Func style definitions moving forward. And we also used that as a reason to use X509Certificate2 instead of X509Certificate.

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh
Member

davidsh commented Nov 13, 2015

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 13, 2015

Member

@davidsh, it is currently in the System.Net.Security contract. It can be seen here.

Member

mconnew commented Nov 13, 2015

@davidsh, it is currently in the System.Net.Security contract. It can be seen here.

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh Nov 13, 2015

Member

Hmmm...ok in that case, we should re-consider the System.Net.Security contract to change that to Func<T> as well and change X509Certifcate to X509Certificate2

@SidharthNabar Can you drive this as part of the full-up API review for System.Net.*

Member

davidsh commented Nov 13, 2015

Hmmm...ok in that case, we should re-consider the System.Net.Security contract to change that to Func<T> as well and change X509Certifcate to X509Certificate2

@SidharthNabar Can you drive this as part of the full-up API review for System.Net.*

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh
Member

davidsh commented Nov 13, 2015

@SidharthNabar

This comment has been minimized.

Show comment
Hide comment
@SidharthNabar

SidharthNabar Nov 13, 2015

Agreed. The RemoteCertificateValidationCallback type needs to be updated in System.Net.Security as well.

SidharthNabar commented Nov 13, 2015

Agreed. The RemoteCertificateValidationCallback type needs to be updated in System.Net.Security as well.

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 13, 2015

Member

Previously in HttpWebRequest, the callback validator would be set via the static property ServicePointManager.ServerCertificateValidationCallbackobject. If you wanted to chain on to an existing validator, you could store the previous value in a static field of your own and then have your own validator call the previous validator. Something like this:

static RemoteCertificateValidationCallback chainedServerCertValidationCallback = null;

static void SetCertificateValidator()
{
    chainedServerCertValidationCallback = ServicePointManager.ServerCertificateValidationCallback;
    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidateServerCertificate);
}

static  bool OnValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool valid = // Do validation
    if(valid)
    {
        if (chainedServerCertValidationCallback == null)
        {
            return (sslPolicyErrors == SslPolicyErrors.None);
        }
        else
        {
            return chainedServerCertValidationCallback(sender, certificate, chain, sslPolicyErrors);
        }
    }
    return false;
}

Now that it is being set at the HttpMessageHandler level, there could be many different previous validators on different instances of the handler. This makes chaining validators difficult as either a closure delegate is needed to be instantiated, or an entire class needs to be instantiated with the previous validator enclosed as an instance method. Here is an example of how it would look.

static void SetServerCertificateValidationCallback(WinHttpHandler handler)
{
    winHttpHandler.ServerCertificateValidationCallback = ChainValidator(winHttpHandler.ServerCertificateValidationCallback);
}

static Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> ChainValidator(Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> previousValidator)
{
    if (previousValidator == null)
    {
        return OnValidateServerCertificate;
    }

    Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> chained =
        (request, certificate, chain, sslPolicyErrors) =>
    {
        bool valid = OnValidateServerCertificate(request, certificate, chain, sslPolicyErrors);
        if (valid)
        {
            return previousValidator(request, certificate, chain, sslPolicyErrors);
        }
        return false;
    };

    return chained;
}

static bool OnValidateServerCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool valid = // Do validation
    if(valid)
    {
        return (sslPolicyErrors == SslPolicyErrors.None);
    }

    return false;
}

The new way of doing it is a later more work to achieve the same thing. I would request that the new api have some simple mechanism for chaining callbacks. E.g. multicast delegates or an event.

Member

mconnew commented Nov 13, 2015

Previously in HttpWebRequest, the callback validator would be set via the static property ServicePointManager.ServerCertificateValidationCallbackobject. If you wanted to chain on to an existing validator, you could store the previous value in a static field of your own and then have your own validator call the previous validator. Something like this:

static RemoteCertificateValidationCallback chainedServerCertValidationCallback = null;

static void SetCertificateValidator()
{
    chainedServerCertValidationCallback = ServicePointManager.ServerCertificateValidationCallback;
    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidateServerCertificate);
}

static  bool OnValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool valid = // Do validation
    if(valid)
    {
        if (chainedServerCertValidationCallback == null)
        {
            return (sslPolicyErrors == SslPolicyErrors.None);
        }
        else
        {
            return chainedServerCertValidationCallback(sender, certificate, chain, sslPolicyErrors);
        }
    }
    return false;
}

Now that it is being set at the HttpMessageHandler level, there could be many different previous validators on different instances of the handler. This makes chaining validators difficult as either a closure delegate is needed to be instantiated, or an entire class needs to be instantiated with the previous validator enclosed as an instance method. Here is an example of how it would look.

static void SetServerCertificateValidationCallback(WinHttpHandler handler)
{
    winHttpHandler.ServerCertificateValidationCallback = ChainValidator(winHttpHandler.ServerCertificateValidationCallback);
}

static Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> ChainValidator(Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> previousValidator)
{
    if (previousValidator == null)
    {
        return OnValidateServerCertificate;
    }

    Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> chained =
        (request, certificate, chain, sslPolicyErrors) =>
    {
        bool valid = OnValidateServerCertificate(request, certificate, chain, sslPolicyErrors);
        if (valid)
        {
            return previousValidator(request, certificate, chain, sslPolicyErrors);
        }
        return false;
    };

    return chained;
}

static bool OnValidateServerCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool valid = // Do validation
    if(valid)
    {
        return (sslPolicyErrors == SslPolicyErrors.None);
    }

    return false;
}

The new way of doing it is a later more work to achieve the same thing. I would request that the new api have some simple mechanism for chaining callbacks. E.g. multicast delegates or an event.

@SidharthNabar

This comment has been minimized.

Show comment
Hide comment
@SidharthNabar

SidharthNabar Nov 19, 2015

@mconnew - That's a great input. We should definitely consider the scenario of multiple validators handling the validation. For an event based design however, how do you propose we merge all the results? e.g. If three event handlers subscribe to the event, what would be the mechanism to combine the return values of those three?

Also, can you describe a scenario for chained validation callbacks. Typically, the expectation is that the caller of SendRequestAsync owns the decision of whether or not to trust the server certificate. And that caller would be the only one wiring up the validation callback.

SidharthNabar commented Nov 19, 2015

@mconnew - That's a great input. We should definitely consider the scenario of multiple validators handling the validation. For an event based design however, how do you propose we merge all the results? e.g. If three event handlers subscribe to the event, what would be the mechanism to combine the return values of those three?

Also, can you describe a scenario for chained validation callbacks. Typically, the expectation is that the caller of SendRequestAsync owns the decision of whether or not to trust the server certificate. And that caller would be the only one wiring up the validation callback.

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 20, 2015

Member

Two possible approaches I can see. If staying with a delegate that returns a Boolean, then I would expect it to fail validation if any validator returns false. My reasoning is that a validator isn't really saying that a certificate is good, it's saying that it hasn't failed any code based validation rules. Having multiple validators is basically adding multiple code based validation rules and for a certificate to be valid, then it needs to pass all rules so you AND the results.
If you switch to an actual event, then you could have an EventArgs class which typically has a handled property to short circuit any more validators running. But I don't think that's quite appropriate as it's not notifying an event for the handler to do something with, it's asking for a response and a decision. Because of this I prefer the first approach I suggested.

Member

mconnew commented Nov 20, 2015

Two possible approaches I can see. If staying with a delegate that returns a Boolean, then I would expect it to fail validation if any validator returns false. My reasoning is that a validator isn't really saying that a certificate is good, it's saying that it hasn't failed any code based validation rules. Having multiple validators is basically adding multiple code based validation rules and for a certificate to be valid, then it needs to pass all rules so you AND the results.
If you switch to an actual event, then you could have an EventArgs class which typically has a handled property to short circuit any more validators running. But I don't think that's quite appropriate as it's not notifying an event for the handler to do something with, it's asking for a response and a decision. Because of this I prefer the first approach I suggested.

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 23, 2015

Member

I forgot to address your second point. First, there's no guarantee that the code that generates the HttpRequestMessage/causes a request to be initiated is owned by the same codebase as creates the HttpClient with it's handler. You could have an api where the request is passed to some class which does the actual call, or might pass back the HttpClient.
I'll give you the example for WCF's use case of needing multiple validators. We allow developers to specify a specific certificate that a web server will be using. We have a registration mechanism and validation callback method which maps a request to the expected server certificate. In our callback, we verify that the Server Certificate provided on our API matches the certificate that was received from the server. As the same HttpClient/HttpClientHandler can be used for multiple remote endpoints, we need to have this global callback registered. If a customer then provides their own validation callback (WCF's own extensibility point), then we need to chain that one on too.

Member

mconnew commented Nov 23, 2015

I forgot to address your second point. First, there's no guarantee that the code that generates the HttpRequestMessage/causes a request to be initiated is owned by the same codebase as creates the HttpClient with it's handler. You could have an api where the request is passed to some class which does the actual call, or might pass back the HttpClient.
I'll give you the example for WCF's use case of needing multiple validators. We allow developers to specify a specific certificate that a web server will be using. We have a registration mechanism and validation callback method which maps a request to the expected server certificate. In our callback, we verify that the Server Certificate provided on our API matches the certificate that was received from the server. As the same HttpClient/HttpClientHandler can be used for multiple remote endpoints, we need to have this global callback registered. If a customer then provides their own validation callback (WCF's own extensibility point), then we need to chain that one on too.

@sharwell

This comment has been minimized.

Show comment
Hide comment
@sharwell

sharwell Nov 24, 2015

Member

ServicePointManager.ServerCertificateValidationCallback does not provide a way to customize certificate validation. In one of the Visual Studio extensions I work on, we want to provide very specific customized handling for self-signed certificates in order to operate properly with other (command line) tools. It is not acceptable for us to change the behavior of other HTTP operations in Visual Studio to support our scenario, so for all practical purposes ServerCertificateValidationCallback is equivalent to not existing.

The solution used for supporting customized certificate validation for System.Net.Http MUST NOT be a static property or method.

That said, we could work with pretty much any solution that restricts the operation to HTTP requests initiated by our code. As an example of the impact of this, our code does not support self-signed certificates in Visual Studio 2005 or 2008, and only supports self-signed certificates in Visual Studio 2010 when .NET 4.5 is installed on the system (via light-up/reflection). For Visual Studio 2012+, it is straightforward to customize certificate handling.

Member

sharwell commented Nov 24, 2015

ServicePointManager.ServerCertificateValidationCallback does not provide a way to customize certificate validation. In one of the Visual Studio extensions I work on, we want to provide very specific customized handling for self-signed certificates in order to operate properly with other (command line) tools. It is not acceptable for us to change the behavior of other HTTP operations in Visual Studio to support our scenario, so for all practical purposes ServerCertificateValidationCallback is equivalent to not existing.

The solution used for supporting customized certificate validation for System.Net.Http MUST NOT be a static property or method.

That said, we could work with pretty much any solution that restricts the operation to HTTP requests initiated by our code. As an example of the impact of this, our code does not support self-signed certificates in Visual Studio 2005 or 2008, and only supports self-signed certificates in Visual Studio 2010 when .NET 4.5 is installed on the system (via light-up/reflection). For Visual Studio 2012+, it is straightforward to customize certificate handling.

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 24, 2015

Member

@sharwell, the current desktop design with ServicePointManager.ServerCertificateValidationCallback can be used in a way to effectively install a validator which only validates for your own requests. Take a look at how WCF does it on Desktop .Net. Basically we have a static dictionary where we store the HttpWebRequest as the key, and whatever information you need as the value. We add the HttpWebRequest to this dictionary before we make the call, and then remove it again after we're done. In our case the dictionary value is the expected certificate thumbprint. On initialization, we copy the reference to the current validator and then install our own. Then when our validator runs we check to see if the specific request is in the dictionary, and if it is, we run out validation code using the value that was stored. If our validation passes, we call the previously installed validator in a chain. If our validation code fails, then we return false.

Member

mconnew commented Nov 24, 2015

@sharwell, the current desktop design with ServicePointManager.ServerCertificateValidationCallback can be used in a way to effectively install a validator which only validates for your own requests. Take a look at how WCF does it on Desktop .Net. Basically we have a static dictionary where we store the HttpWebRequest as the key, and whatever information you need as the value. We add the HttpWebRequest to this dictionary before we make the call, and then remove it again after we're done. In our case the dictionary value is the expected certificate thumbprint. On initialization, we copy the reference to the current validator and then install our own. Then when our validator runs we check to see if the specific request is in the dictionary, and if it is, we run out validation code using the value that was stored. If our validation passes, we call the previously installed validator in a chain. If our validation code fails, then we return false.

@sharwell

This comment has been minimized.

Show comment
Hide comment
@sharwell

sharwell Nov 24, 2015

Member

@mconnew From everything I could tell, that strategy does not appear to be thread safe. It's unclear how it could be leveraged without introducing race conditions in the application.

Member

sharwell commented Nov 24, 2015

@mconnew From everything I could tell, that strategy does not appear to be thread safe. It's unclear how it could be leveraged without introducing race conditions in the application.

@mconnew

This comment has been minimized.

Show comment
Hide comment
@mconnew

mconnew Nov 24, 2015

Member

@sharwell, we use that strategy in WCF on desktop and have extensive stress tests which run sometimes for weeks at a time to find issues like race conditions and we haven't had an issue. The only risk is on setting the initial callback at the same time as someone else's library code does the same. While WCF doesn't do this, if this is a concern I believe this could be done safely using a set and check loop. E.g. read old the value, set the new value, read the new value and verify it is what you expect. If it isn't, rinse and repeat. Use Thread.MemoryBarrier() between the set and read to deal with multi core cache coherency issues. But that's an initial setup race condition issue and the reality is most systems don't initialize multiple components simultaneously because you can't trust that two different code bases (e.g. VS installers) won't stomp on each other during initialization. I'm guessing about VS, but I suspect they loop through extensions doing the initialization. Event if they don't, you can protect against that as I suggested. You will have no thread safety or race issues once set up.

Member

mconnew commented Nov 24, 2015

@sharwell, we use that strategy in WCF on desktop and have extensive stress tests which run sometimes for weeks at a time to find issues like race conditions and we haven't had an issue. The only risk is on setting the initial callback at the same time as someone else's library code does the same. While WCF doesn't do this, if this is a concern I believe this could be done safely using a set and check loop. E.g. read old the value, set the new value, read the new value and verify it is what you expect. If it isn't, rinse and repeat. Use Thread.MemoryBarrier() between the set and read to deal with multi core cache coherency issues. But that's an initial setup race condition issue and the reality is most systems don't initialize multiple components simultaneously because you can't trust that two different code bases (e.g. VS installers) won't stomp on each other during initialization. I'm guessing about VS, but I suspect they loop through extensions doing the initialization. Event if they don't, you can protect against that as I suggested. You will have no thread safety or race issues once set up.

@sharwell

This comment has been minimized.

Show comment
Hide comment
@sharwell

sharwell Nov 25, 2015

Member

@mconnew Thanks for the info. 😄 I'm going to try to make use of it in our next release.

That said, I still think if we're creating a new API to support this functionality in a cross-platform manner for System.Net.Http, it would be beneficial to everyone to implement it as instance properties instead of static ones.

Member

sharwell commented Nov 25, 2015

@mconnew Thanks for the info. 😄 I'm going to try to make use of it in our next release.

That said, I still think if we're creating a new API to support this functionality in a cross-platform manner for System.Net.Http, it would be beneficial to everyone to implement it as instance properties instead of static ones.

@johnjelinek

This comment has been minimized.

Show comment
Hide comment
@johnjelinek

johnjelinek commented Jan 12, 2016

👍

@davidsh davidsh assigned davidsh and unassigned SidharthNabar Apr 9, 2016

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh Apr 9, 2016

Member

Will be part of #7623

Member

davidsh commented Apr 9, 2016

Will be part of #7623

@stephentoub stephentoub modified the milestones: 1.1.0, 1.0.0-rtm Apr 30, 2016

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh May 9, 2016

Member

Closing this issue since it is part of #7623.

Member

davidsh commented May 9, 2016

Closing this issue since it is part of #7623.

@davidsh davidsh closed this May 9, 2016

@guardrex

This comment has been minimized.

Show comment
Hide comment
@guardrex

guardrex Jun 15, 2016

@davidsh @mconnew

I'm looking at @mconnew's 2nd code sample in #4476 (comment). My scenario is that I have self-signed certs on Linux machines that use a simple HTTPServer from http.server with an SSL-wrapped socket. I just need to make secure requests to those machines along the lines of ...

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Add("header", "value");
    HttpResponseMessage response = await client.GetAsync(requestUri);
    if (response.IsSuccessStatusCode)
    {
        ...
    }
}

In .NET 4.x days, I used to use ServicePointManager.ServerCertificateValidationCallback to validate the self-signed certs so that such requests wouldn't choke. Now, I'm wondering with my Core CLR app if I can use @mconnew's 2nd code sample along the lines of ...

WinHttpHandler handler = new WinHttpHandler();
SetServerCertificateValidationCallback(handler);
using (var client = new HttpClient(handler))
{
    ...
}

Is that the correct approach for my scenario?

guardrex commented Jun 15, 2016

@davidsh @mconnew

I'm looking at @mconnew's 2nd code sample in #4476 (comment). My scenario is that I have self-signed certs on Linux machines that use a simple HTTPServer from http.server with an SSL-wrapped socket. I just need to make secure requests to those machines along the lines of ...

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Add("header", "value");
    HttpResponseMessage response = await client.GetAsync(requestUri);
    if (response.IsSuccessStatusCode)
    {
        ...
    }
}

In .NET 4.x days, I used to use ServicePointManager.ServerCertificateValidationCallback to validate the self-signed certs so that such requests wouldn't choke. Now, I'm wondering with my Core CLR app if I can use @mconnew's 2nd code sample along the lines of ...

WinHttpHandler handler = new WinHttpHandler();
SetServerCertificateValidationCallback(handler);
using (var client = new HttpClient(handler))
{
    ...
}

Is that the correct approach for my scenario?

@davidsh

This comment has been minimized.

Show comment
Hide comment
@davidsh

davidsh Jun 15, 2016

Member

Generally speaking, yes, that pattern should work.

Also, we revised the System.Net.Http contract (4.1 revision) to have more properties and have the ServerCertificateCustomValidationCallback property as well. So, it is not necessary to use WinHttpHandler directly. You can use HttpClientHandler (which is cross-platform) to get custom server certificate validation logic.

Member

davidsh commented Jun 15, 2016

Generally speaking, yes, that pattern should work.

Also, we revised the System.Net.Http contract (4.1 revision) to have more properties and have the ServerCertificateCustomValidationCallback property as well. So, it is not necessary to use WinHttpHandler directly. You can use HttpClientHandler (which is cross-platform) to get custom server certificate validation logic.

@guardrex

This comment has been minimized.

Show comment
Hide comment
@guardrex

guardrex Jun 15, 2016

This app is stuck a little bit on rc2-final because the WindowsAzure.Storage folks lag behind nightly. They go release-to-release, so I feel more comfortable using their bits with rc2-final.

Since @mconnew's pattern looks good for now, I'll try getting that to work in this app, then switch over to System.Net.Http/4.1.0-* at RTM after they release a RTM storage lib.

Thanks @davidsh ... It's all coming together now.

Cheers to @mconnew ... 🍻 ... saved me significant time by posting that code sample.

guardrex commented Jun 15, 2016

This app is stuck a little bit on rc2-final because the WindowsAzure.Storage folks lag behind nightly. They go release-to-release, so I feel more comfortable using their bits with rc2-final.

Since @mconnew's pattern looks good for now, I'll try getting that to work in this app, then switch over to System.Net.Http/4.1.0-* at RTM after they release a RTM storage lib.

Thanks @davidsh ... It's all coming together now.

Cheers to @mconnew ... 🍻 ... saved me significant time by posting that code sample.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment