Skip to content
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

System.Net.Http.WinHttpHandler fallbacks to HTTP/1.1 when using client certificates with HTTP/2 #40794

Closed
jensolsson opened this issue Aug 13, 2020 · 10 comments
Milestone

Comments

@jensolsson
Copy link

jensolsson commented Aug 13, 2020

I am trying to write some code to send a push notification to an iPhone using C# .NET and HttpClient over HTTP2 with client certificate authentication.

Code compiles but always yields a:

HttpRequestException with Message "Error while copying content to a stream."

InnerException IOException Message "The write operation failed, see inner exception."

InnerException WinHttpException Message "{"Error 12152 calling WinHttpWriteData, 'The server returned an invalid or unrecognized response'."}"

I am looking for why the code is failing?

Is it possible to debug/troubleshoot this in some way?

Here is my code

class Program {
    private const string cert = "MIINKwI....<hidden>";
    private const string certpw = "password";
    private const string devicetoken = "921c95b6494828f973512f2327478b0<hidden>";
    private const string bundleid = "se.jensolsson.testapp";

    private static HttpClient client = null;
    static async Task Main(string[] args) {
        try {

            byte[] certificateData = Convert.FromBase64String(cert);
            X509Certificate2 certificate = new X509Certificate2(certificateData, certpw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

            string url = "https://api.push.apple.com:443/3/device/";

            string payload = @"{""aps"":{""alert"":""Test""}}";

            var handler = new WinHttpHandler();
            handler.ClientCertificates.Add(certificate);

            if (client == null)
                client = new HttpClient(handler);

            using (var request = new HttpRequestMessage(HttpMethod.Post, url + devicetoken)) {
                var messageGuid = Guid.NewGuid().ToString();
                request.Version = new Version("2.0");
                request.Content = new StringContent(payload);
                request.Headers.Add("apns-id", messageGuid);
                request.Headers.Add("apns-push-type", "alert");
                request.Headers.Add("apns-priority", "10");
                request.Headers.Add("apns-topic", bundleid);


                using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)) {
                    HttpStatusCode statusCode = response.StatusCode;
                    string reasonPhrase = response.ReasonPhrase;
                    bool success = response.IsSuccessStatusCode;
                }
            }

        }
        catch (ArgumentNullException anu) { }
        catch (InvalidOperationException ioe) { }
        catch (HttpRequestException hre) { }
        catch (TaskCanceledException tce) { }
        catch (Exception e) { }        
    }
}

Investigating further. Tried to connect to an open HTTP2 capable web server. I used https://nghttp2.org/ as an example.

Replaced url line to string url = "https://nghttp2.org/";
replaced request line to using (var request = new HttpRequestMessage(HttpMethod.Get, url)) {.
A very interesting finding is that even though i send a HTTP/2 request and it seem to give a reply, looking at the response object, Version is set to 1.1.

If I also remove the handler.ClientCertificates.Add(certificate); line and retry, looking at the response object, Version is correctly set to 2.0.

So it seem like WinHttpHandler drops HTTP/2 support as soon as a client certificate is added to the handler.

(For completeness I also posted this to SO at https://stackoverflow.com/questions/63381427/sending-http-2-request-to-apple-push-notification-service-using-httpclient-clie There is also a wireshark dump but I dont think it is interesting as it is wrapped in SSL and there is no way for me to decrypt it since it is Apples server.)

Running on Windows 10 .NET 4.8. Latest stable WinHttpHandler. Also tried 5.0 latest preview. Same issue.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Net untriaged New issue has not been triaged by the area owner labels Aug 13, 2020
@ghost
Copy link

ghost commented Aug 13, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

@karelz
Copy link
Member

karelz commented Aug 13, 2020

I think it was fixed in: dotnet/corefx#42888
You need Win10 version which has the support and WinHttpHandler package that has the automatic opt-in feature.

CC @alnikola

@jensolsson
Copy link
Author

jensolsson commented Aug 13, 2020 via email

@jensolsson
Copy link
Author

jensolsson commented Aug 13, 2020

@karelz Now updated to Windows 10, Version 2004, no more updates available
Tested with System.Net.Http.WnHttpHandler v4.7.2 - does not work, same problem
Tested with System.Net.Http.WnHttpHandler v5.0.0-preview.7.20364.11 - does not work, same problem

Is there a special version of WinHttpHandler I need to fetch?

@alnikola
Copy link
Contributor

@jensolsson You need Windows 10 Version 2004 build 19573 or newer. Could you please tell me what is the Window's build number you tested it on?

@jensolsson
Copy link
Author

jensolsson commented Aug 19, 2020 via email

@karelz
Copy link
Member

karelz commented Aug 19, 2020

@jensolsson looks like it is only in Dev channel of Insider builds: https://insider.windows.com/en-us/ (closest announced was 19577 from 2020/3)
Official OS versions: https://en.wikipedia.org/wiki/Windows_10_version_history

@karelz
Copy link
Member

karelz commented Aug 19, 2020

Closing as addressed. If you try it out, let us know how it goes.

@karelz karelz closed this as completed Aug 19, 2020
@karelz karelz added this to the 5.0.0 milestone Aug 19, 2020
@karelz karelz removed the untriaged New issue has not been triaged by the area owner label Aug 19, 2020
@jensolsson
Copy link
Author

@karelz do you know how I can estimate when this feature will be released to the public?
I have a major issue with this. Just got confirmed that Apple will drop support for their old protocol in November so only two months left. I am hoping for a Windows release with these features included before then.

@karelz
Copy link
Member

karelz commented Aug 21, 2020

I don't know what is the timeline on Windows releases sadly. Can you check on their insider program?

@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants