We develop apps for the three main platforms (iOS, Android and Windows). These all come with their own variety of notification service to allow you to send out user specific notifications as and when you need to.
Windows and Android are fairly straightforward to set up.
Apple’s iOS is not.
Known as the Apple Push Notification Service or APNS, it involves a mind-bending set of certificates and keys to get it running. And to keep us DevOps on our toes, the certificates have a limited lifetime, requiring periodic curation and associated memory refresh of all the ‘how tos’ to keep the service reliable.
So consider this post a bit of an aide-memoire for us as we maintain and support various push notification services for our client’s apps.
There are currently two flavours of APNS, the older ‘binary provider API’ and as of April 2016 the newer ‘HTTP/2 API’. Both are described by Apple here.
We’re only using the former at present, so will stick to that one for this note.
Our servers are generally PHP based (though we do maintain a number of other servers too, e.g. Windows .NET and Node.js). So the excellent ApnsPHP_Push library is the weapon of choice. This needs two certificate files. There’s no easy way to name these, so I will just use the PHP variable name. We have the $ios_trust_cert_file and the $ios_server_cert_file.
We generally host on Linux, so AWS, Digital Ocean, Linode, Google Cloud etc. A good place to put the certificates is in a /etc/yourappname/ directory. Make sure you have the correct permissions and ownership. For example, on AWS with Apache server, it is :
-rw-r–r– 1 ec2-user apache cert.pem
This is an easy one to configure, simply download the Entrust certificate authority certificate from here.
Then place it in your /etc/yourappname/ directory, set permissions and reference it in your instantiation of an ApnsPHP_Push object
This is the real mind-bender.
To create this file, we need to include two PEM files in one file.
The first PEM file is created by you (or more accurately by us for you) in your (or our if we’re hosting your app) Apple developer account under certificates and IDs.
Note that in iOS, as if it isn’t complicated enough, there is also the concept of a development and production set of keys. I will gloss over the development route for now. Suffice to say, that during beta testing via TestFlight, you will need the development option.
Select App IDs under Identifiers, then browse to your app’s ID. Select the App ID, click edit, (this is where developer.apple.com is really slow at times).
Select the Push notification part, follow the wizard to create a certificate signing request [let’s call it B.csr] on your Mac, upload to developer.apple.com as instructed and then download your newly created Apple_push_production_cert.cer (let’s call it A.cer] file.
Double click on the A.cer file to import into your Mac’s keychain. Then open KeyChainAccess and right click on the new certificate, choose export and save it as A.p12 file (e.g. to your desktop).
Now convert the A.p12 to A.pem using the command line
openssl pkcs12 -in A.p12 -out A.pem -nodes -clcerts
The last step in this recipe is we need to concatenate the private key used for your certificate signing request with A.pem.
So we go back to the csr we generated [B.csr], double click to import into our Mac KeyChain, then open KeyChainAccess, browse to keys and to your CSR key, right click to export. Save as .p12 and convert to .pem (as for A.pem) then open in a text editor (e.g. nano) and paste the CSR key underneath the A.pem contents.
Save to your /etc/yourappname/ directory, set permissions accordingly and set the ApnsPHP_Push $ios_server_cert_file to the filename.
Now start troubleshooting 🙂
E.g. to test connectivity, use this
openssl s_client -connect gateway.push.apple.com:2195 -A.pem -CAfile entrust_2048_ca.cer