Integrate Apple Push Notification Service

(Apple Push Notification Service APNs) is a critical component for delivering timely and relevant updates to users on Apple devices. Whether it's a message, alert, or app update, APNs ensures your iOS, macOS, watchOS, and tvOS applications remain engaging and responsive. This post walks, we'll walk through integrating APNs into a C# backend to send push notifications to Apple devices.

Integrate Apple Push Notification Service

Getting Started

Apple Push Notification Service is a robust platform provided by Apple that enables third-party applications to send notifications to iOS, macOS, tvOS, and watchOS devices. While APNs integration is commonly discussed for Swift or Objective-C, server-side notification sending (often written in C# for backend APIs) is equally critical.

Integrating APNs in a C# application (typically a backend service or server app) involves sending push notifications to iOS devices using HTTP/2 and JWT-based authentication (with your Apple-provided key).

Steps Overview:

  1. Create your Apple Push Notification Key (APNs Auth Key) in Apple Developer Account.
  2. Prepare your credentials: Key ID, Team ID, Bundle ID, and .p8 private key file.
  3. Use a C# HTTP/2 client (e.g., HttpClient + SocketsHttpHandler with HttpRequestMessage) to send POST requests to Apple servers.
  4. Generate a JWT token signed with your .p8 key.
  5. Send push notifications using that token in the Authorization header.

Prerequisites

Before you start coding:
  1. An Apple Developer Account
  2. Create an APNs Key: https://developer.apple.com/account/resources/authkeys/list
    • Download the .p8 file
    • Note the: Key ID (e.g. ABCD1234XY), Team ID (e.g. X9Q8L99W8T),Bundle ID of your app (e.g. com.example.myapp)

Install Required NuGet Packages

Install these packages, to know more how to install NuGet packages visit my another post "Installing NuGet Packages: A Beginner's Guide":
dotnet add package System.IdentityModel.Tokens.Jwt
dotnet add package Microsoft.IdentityModel.Tokens

Code: Sending a Push Notification via APNs

 using System;  
 using System.IO;  
 using System.Net.Http;  
 using System.Net.Http.Headers;  
 using System.Security.Cryptography;  
 using System.Text;  
 using System.Threading.Tasks;  
 using Microsoft.IdentityModel.Tokens;  
 using System.IdentityModel.Tokens.Jwt;  
 public class ApnsPushService  
 {  
   private readonly string _p8FilePath = "AuthKey_XXXXXX.p8"; // Path to your .p8 key  
   private readonly string _keyId = "YOUR_KEY_ID";  
   private readonly string _teamId = "YOUR_TEAM_ID";  
   private readonly string _bundleId = "com.example.myapp";  
   private readonly string _deviceToken = "DEVICE_TOKEN_HERE"; // 64-char token from device  
   private readonly string _apnsHost = "https://api.push.apple.com";  
   private string GenerateJwtToken()  
   {  
     var privateKey = File.ReadAllText(_p8FilePath);  
     var ecdsa = ECDsa.Create();  
     ecdsa.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey  
       .Replace("-----BEGIN PRIVATE KEY-----", "")  
       .Replace("-----END PRIVATE KEY-----", "")  
       .Replace("\n", "").Trim()), out _);  
     var securityKey = new ECDsaSecurityKey(ecdsa) { KeyId = _keyId };  
     var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.EcdsaSha256);  
     var header = new JwtHeader(credentials)  
     {  
       { "kid", _keyId }  
     };  
     var payload = new JwtPayload(_teamId, null, null, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(20));  
     var token = new JwtSecurityToken(header, payload);  
     return new JwtSecurityTokenHandler().WriteToken(token);  
   }  
   public async Task SendPushNotificationAsync()  
   {  
     var jwtToken = GenerateJwtToken();  
     var payload = new  
     {  
       aps = new  
       {  
         alert = new  
         {  
           title = "Hello",  
           body = "This is a push notification from C#"  
         },  
         sound = "default"  
       }  
     };  
     var jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload);  
     var request = new HttpRequestMessage(HttpMethod.Post, $"{_apnsHost}/3/device/{_deviceToken}")  
     {  
       Version = new Version(2, 0),  
       Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")  
     };  
     request.Headers.Authorization = new AuthenticationHeaderValue("bearer", jwtToken);  
     request.Headers.TryAddWithoutValidation("apns-topic", _bundleId);  
     var handler = new SocketsHttpHandler  
     {  
       PooledConnectionLifetime = TimeSpan.FromMinutes(5),  
       EnableMultipleHttp2Connections = true  
     };  
     using var client = new HttpClient(handler);  
     client.DefaultRequestVersion = new Version(2, 0);  
     var response = await client.SendAsync(request);  
     var responseString = await response.Content.ReadAsStringAsync();  
     Console.WriteLine($"Status Code: {response.StatusCode}");  
     Console.WriteLine($"Response: {responseString}");  
   }  
 }  

Usage:

var apns = new ApnsPushService();
await apns.SendPushNotificationAsync();

Notes:

  • Device Token: You must have the device token from your iOS app (registered with registerForRemoteNotifications).
  • HTTP/2 Requirement: APNs only supports HTTP/2, which is why HttpClient with SocketsHttpHandler is used.
  • JWT Token Lifetime: Max 1 hour (but recommended to reuse the token for performance).
  • Environment: For sandbox (development), use https://api.sandbox.push.apple.com

Troubleshooting

Error Cause Fix
403 Forbidden Invalid JWT token Check Key ID, Team ID, and token expiration
400 BadDeviceToken Malformed or wrong environment Ensure token matches sandbox or production
403 Missing or invalid token Malformed JWT or missing fields Validate JWT generation
SSL/TLS errors HTTP/2 not supported or TLS mismatch Ensure you're using .NET 6+ and proper server URL

Summary

Sending Apple push notifications from a C# backend is absolutely possible with a clean, secure, and modern approach using JWT-based authentication over HTTP/2. With Apple enforcing more security and performance through these standards, your C# apps can be robust contributors in delivering seamless iOS experiences.

Thanks

Kailash Chandra Behera

I am an IT professional with over 13 years of experience in the full software development life cycle for Windows, services, and web-based applications using Microsoft .NET technologies.

Previous Post Next Post

نموذج الاتصال