0

We are trying to connect to APNS via .NET project (Framework 4.0).

We know JWT mechanism wont work due to HTTP/2 requirement.

We are trying to achieve this via TLS certificated based authentication, as below:

No erros/exception. Code works but no notification received on iPhone.

int port = 443;;
var payload = JsonHelper.Serialize (notification);
String certificatePath = "apns.pem"; //Not working for .p12/pfx
X509Certificate2 clientCertificate = new X509Certificate2 (System.IO.File.ReadAllBytes (certificatePath), "password");
X509Certificate2Collection certificatesCollection = new X509Certificate2Collection (clientCertificate);

TcpClient client = new TcpClient ("Production", port);
SslStream sslStream = new SslStream (client.GetStream (), false, new RemoteCertificateValidationCallback (ValidateServerCertificate), null);

try {
  sslStream.AuthenticateAsClient ("api.push.apple.com", certificatesCollection, (SslProtocols)3072, false);
  MemoryStream memoryStream = new MemoryStream ();
  BinaryWriter writer = new BinaryWriter (memoryStream);
  writer.Write ((byte)0);
  writer.Write ((byte)0);
  writer.Write ((byte)32);

  writer.Write (HexStringToByteArray (deviceToken.ToUpper ()));
  writer.Write ((byte)0);
  writer.Write ((byte)payload.Length);
  byte [] b1 = System.Text.Encoding.UTF8.GetBytes (payload);
  writer.Write (b1);
  writer.Flush ();
  byte [] array = memoryStream.ToArray ();
  sslStream.Write (array);

  sslStream.Flush ();
  client.Close ();
vITs
  • 1,651
  • 12
  • 30
  • ASP.NET 4.0 is 11 years old and went out of support *several* years ago. That's the version *before* `async/await` were introduced and won't be found in any supported Windows version - all supported Windows versions have .NET Framework 4.6 at least – Panagiotis Kanavos Nov 15 '21 at 16:06
  • `No erros/exception. Code works` how do you know that? Your code writes some bytes to a stream but never checks for a response. It tries to do that using a proprietary .NET binary format that even .NET doesn't use any more - `BinaryWriter` isn't needed to write bytes to a stream. It's used to write primitive types using the insecure BinaryFormatter class. Only another .NET application using BinaryFormatter or BinaryReader could read this – Panagiotis Kanavos Nov 15 '21 at 16:09
  • 1
    Besides, [.NET Framework 4 never supported TLS1.2](https://stackoverflow.com/questions/33761919/tls-1-2-in-net-framework-4-0) and no cloud service accepts anything less these days. Unless you actually run this code on a .NET Framework 4.5 runtime and forced your code to use TLS1.2, Apple's servers will reject the connection. You should really, really target a fresh runtime and use HTTPS, TLS1.2 and HTTP/2 properly instead of trying to hack it – Panagiotis Kanavos Nov 15 '21 at 16:12
  • Thanks @PanagiotisKanavos for quick reply. By code works, I mean call to AuthenticateAsClient has no errors. If I change certificate I get error immediately. I know its legacy, still wanted to check if we have workarounds. – vITs Nov 15 '21 at 16:14
  • The workaround is to upgrade to a supported .NET Framework version. Your code is running on a newer runtime anyway, no matter what your project assumes. There's simply no supported Windows version with just .NET 4.0. All 4.x runtimes are binary replacements which means that if, for whatever reason, a newer version was installed it would replace the older one. Even if you target Windows 2008 R2, the actual runtime was probably upgraded through Windows Update years ago – Panagiotis Kanavos Nov 15 '21 at 16:16
  • The current supported version is 4.5.2 but even that will go out of support in just a few months. The oldest supported version will be 4.6.2. There's no reason to use that instead of the latest version though. You're already using an unsupported .NET version trying hacks to make it work in a way that's simply not supported. It would take *less* work to switch to 4.7 or 4.8 than try to get the hack to work – Panagiotis Kanavos Nov 15 '21 at 16:18
  • @PanagiotisKanavos Received response of above request contains, "HTTP/2 client preface string missing or corrupt." – vITs Nov 16 '21 at 06:26
  • 1
    The service demands HTTP/2. That's a completely different protocol, not just an encrypted HTTP 1.1 stream. You'll have to either implement the entire protocol yourself, find a library that does, or rewrite the application to .NET Core which already supports HTTP/2 and even HTTP/3 (experimentally). – Panagiotis Kanavos Nov 16 '21 at 07:24
  • For example, [dotAPNS](https://github.com/alexalok/dotAPNS) is a library that sends using APNS *on .NET Framework 4.6 and later*. It uses the System.Net.Http.HttpCliient to do this. In .NET Core, the library is available out of the box. In .NET Framework it's available through the System.Net.Http package. – Panagiotis Kanavos Nov 16 '21 at 07:29
  • Yeah, we finally concluded using fcm – vITs Nov 17 '21 at 16:12

0 Answers0