I am trying to get apn-node to push to my devices. The server is hosted on Heroku, so I do not want to commit the file. Also, I do not want to fetch it from a remote server but instead put it in an environment variable.
I already tried the following (source):
I created and downloaded the certificate from Apple and now have it in my Keychain. I exported it as a *.p12
file and converted it with openssl pkcs12 -in dev.p12 -out dev.pem -nodes
into a *.pem
file.
To set the environment variable, I did export APN_CERT="$(cat dev.pem)"
. When I print it out in my application it shows the certificate perfectly fine.
However, when I actually send a notification (and node-apn opens the connection) it throws an [Error: wrong tag]
.
This error is emitted by the crypto module:
apn Raising error: +4ms [Error: wrong tag] undefined undefined
apn Error occurred with trace: +1ms Error: wrong tag
at Object.exports.createCredentials (crypto.js:176:17)
at Object.exports.connect (tls.js:1344:27)
at apnSocketLegacy
The module also throws a APN transmission error: moduleInitialisationFailed (Code: 513)
.
I was unable to find any useful information other than that this could be related to the crypto module itself of node itself. That's why I suspect I did something wrong when creating the certificate but thankful for any guiding advice.
The preference here would be to use an encrypted p12 stored alongside the applciation and specify a passphrase which you set via an environment variable.
I was unable to replicate your problem using the following script
Run with:
The error you are seeing
"wrong tag"
is from OpenSSL and suggests a parsing error of the data contained within the certificate data itself rather than the data being loaded incorrectly from the env. Loading PEM files from environment variables works correctlyI found this guide for apns-sharp which actually described how to generate a valid .p12 file.
Still, writing it into an environment variable did not work. My code for reading it is:
new Buffer(certString, 'binary')
but I thought it still was not supplied in a correct format.The solution for me was to actually read the buffer directly from a file via
fs.readFileSync
.To get the env variable to work you could encode the file via
cat cert.p12 | base64
and load it as such withnew Buffer(certString, 'base64')
. This finally worked for me.