title: .NET Core 2.1 Apple Push Notifications
body: <p>I have to send push notifications to specific iOS devices with my .Net Core WebAPI that will be executed on a Windows 2008 Server R2. The server itself should not be the problem because it is working with a node.js library. But I want it to work with an WepAPI in ASP .Net Core 2.1 which is self hosted with the inbuilt Kestrel Server. Maybe you've got an idea how to solve this problem.</p>
  
  <p>My Code: </p>
  
  <pre><code>// This will encode the jason web token apns needs for the authorization
  // get the base64 private key of the .p8 file from apple
  string p8File = System.IO.File.ReadAllText(Settings.Apn.PrivateKey);
  p8File = p8File.Replace("-----BEGIN PRIVATE KEY-----", string.Empty);
  p8File = p8File.Replace("-----END PRIVATE KEY-----", string.Empty);
  p8File = p8File.Replace(" ", string.Empty);
  
  byte[] keyData = Convert.FromBase64String(p8File);
  ECDsa key = new ECDsaCng(CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob));
  
  ECDsaSecurityKey securityKey = new ECDsaSecurityKey(key) { KeyId = Settings.Apn.KeyId };
  SigningCredentials credentials = new SigningCredentials(securityKey, "ES256");
  
  SecurityTokenDescriptor descriptor =
      new SecurityTokenDescriptor
          {
              IssuedAt = DateTime.Now,
              Issuer = Settings.Apn.TeamId,
              SigningCredentials = credentials
          };
  
  JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
  string encodedToken = jwtHandler.CreateEncodedJwt(descriptor);
  this.log?.LogInformation($"Created JWT: {encodedToken}");
  
  // The hostname is: https://api.development.push.apple.com:443
  HttpClient client = new HttpClient { BaseAddress = new Uri(Settings.Apn.Hostname) };
  client.DefaultRequestHeaders.Clear();
  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  this.log?.LogInformation("Initialized new HttpClient.");
  
  // payload content for the apns
  JObject payloadData = new JObject
                            {
                                new JProperty("alert", data.Message),
                                new JProperty("badge", 2),
                                new JProperty("sound", "default")
                            };
  JObject payload = new JObject
                         {
                             new JProperty("aps", payloadData)
                         };
  this.log?.LogInformation($"Setup payload: {payload}");
  
  // HttpRequestMessage that should be send
  HttpRequestMessage request = new HttpRequestMessage(
                                   HttpMethod.Post,
                                   $"{Settings.Apn.Hostname}/3/device/{data.DeviceId}")
                                   {
                                       Content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json")
                                   };
  this.log?.LogInformation("Setup HttpRequestMessage.");
  
  // Setup the header
  request.Headers.Add("Authorization", $"Bearer {encodedToken}");
  request.Headers.Add("apns-id", Guid.NewGuid().ToString());
  request.Headers.Add("apns-expiration", DateTime.Now.AddDays(1).ToString(CultureInfo.InvariantCulture));
  request.Headers.Add("apns-priority", "10");
  request.Headers.Add("apns-topic", "de.gefasoft-engineering.FabChat");
  
  // Debug logging
  this.log.LogDebug(request.ToString());
  this.log.LogDebug(await request.Content.ReadAsStringAsync());
  this.log.LogDebug(request.RequestUri.Host + request.RequestUri.Port);
  
  // Send request
  var result = await client.SendAsync(request);
  this.log?.LogInformation("Sent request.");
  this.log?.LogInformation(await result.Content.ReadAsStringAsync());
  </code></pre>
  
  <p>I always get following Exception thrown: </p>
  
  <blockquote>
    <p>System.Net.Http.HttpRequestException: The SSL connection could not be
    established, see inner exception. --->
    System.Security.Authentication.AuthenticationException: Authentication
    failed, see inner exception. --->
    System.ComponentModel.Win32Exception: The message received was
    unexpected or badly formatted    --- End of inner exception stack
    trace ---</p>
  </blockquote>