I have been setting up Apple Push Notifications for an iOS app, using JSON Web Tokens rather than certificates.
I can generate a JWT and make the required POST request from within the app (using the Swift-JWT package) and the notification is delivered.
I am using MongoDB Realm, which has serverless functions (in JavaScript with a Node environment) that are called from the iOS app. A scheduled trigger updates my JWT, as Apple advise it should be refreshed every hour.
However, despite trying several Node modules for making the POST request there were always errors (like “BadDeviceToken” or “InvalidProviderToken”).
I finally got it working using the node-apn package! However, I have two queries about using it in this serverless function context:
Provider.shutdown()
does not seem to stop the connection. I don’t think I can have a long-running process to receive future requests in a serverless context.node-apn
manages the JWT for you, but in a serverless context, will it be generating a new token every time the function is called? Notifications do seem to get delivered every time I test it in development mode (to the Apple sandbox endpoint).I’d be grateful for clarity on these points, and whether node-apn
is appropriate to use in serverless functions.
Update
Provider.shutdown()
not working seems to be a recognised issue.
I was able to shut down using this workaround:
Provider.client.endpointManager._endpoints.forEach(endpoint => endpoint.destroy());
I would still like to know about whether it is reasonable for this to be used in a serverless function. I am concerned about JWT being refreshed with every request, which Apple may not like!
I have scanned through Apple's documentation on this and given some thought to your question about refreshing tokens within a serverless context.
You could imagine the following approach for ensuring that you refresh the token no more than once every 20 minutes and at least once every hour, as per Apple's documentation:
apn_tokens
) inside of MongoDB (optionally alongside a createdAt
timestamp field)createdAt
date (or iat
field on the JWT itself) is less than an hour (or within some threshold less than the hour e.g 50 mins), then reuse the token in sending the push notification requestNote on this process: It would require that your database (or theapn_tokens
collection) is only accessible from trusted sources (i.e your cloud application/functions alone), if they aren't already. Clients should not have access to this table in any way. You can imagine setting Collection-Level Access Control for your serverless environment. As an extra layer of security, you could imagine deleting "expired" tokens after re-generation in step 1, such that there is only one token present in the table at any time in order to prevent potentially active tokens from laying around in the database without use.
I hope this helps!