parse-community / parse-server-push-adapter

A push notification adapter for Parse Server
https://parseplatform.org
MIT License
87 stars 99 forks source link

Support Apple's APNS Token Authentication #50

Closed natanrolnik closed 7 years ago

natanrolnik commented 7 years ago

(Issue originally opened by @EricNetsch in ParsePlatform/parse-server#3315)

I would like to start using Apple's new push notification authentication protocol instead of using traditional certs. Is this possible with parse-server yet? This would be a fantastic addition to the platform to simplify push certificate management.

Provider Authentication Tokens

To securely connect to APNs, you can use provider authentication tokens or provider certificates. This section describes connections using tokens.

The provider API supports the JSON Web Token (JWT) specification, letting you pass statements and metadata, called claims, to APNs, along with each push notification. For details, refer to the specification at https://tools.ietf.org/html/rfc7519. For additional information about JWT, along with a list of available libraries for generating signed JWTs, see https://jwt.io

A provider authentication token is a JSON object that you construct, whose header must include:

The encryption algorithm (alg) you use to encrypt the token A 10-character key identifier (kid) key, obtained from your developer account The claims payload of the token must include:

The issuer (iss) registered claim key, whose value is your 10-character Team ID, obtained from your developer account The issued at (iat) registered claim key, whose value indicates the time at which the token was generated, in terms of the number of seconds since Epoch, in UTC After you create the token, you must sign it with a private key. You must then encrypt the token using the Elliptic Curve Digital Signature Algorithm (ECDSA) with the P-256 curve and the SHA-256 hash algorithm. Specify the value ES256 in the algorithm header key (alg). For information on how to configure your token, search Xcode help for the phrase “Configure push notifications.”

A decoded JWT provider authentication token for APNs has the following format:

{ "alg": "ES256", "kid": "ABC123DEFG" } { "iss": "DEF123GHIJ", "iat": 1437179036 } NOTE

APNs supports only provider authentication tokens that are signed with the ES256 algorithm. Unsecured JWTs, or JWTs signed with other algorithms, are rejected, and your provider server receives the InvalidProviderToken (403) response.

To ensure security, APNs requires new tokens to be generated periodically. A new token has an updated issued at claim key, whose value indicates the time the token was generated. If the timestamp for token issue is not within the last hour, APNs rejects subsequent push messages, returning an ExpiredProviderToken (403) error.

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html

Please advise on any existing solutions/ implementations.

natanrolnik commented 7 years ago

@EricNetsch I was planning to do this but I wasn't sure about the implementation. The dependency used here, APN, already supports using APNS authentication tokens. But it's a major update on their package, that has some breaking changes to the one currently used here.

EricNetsch commented 7 years ago

@natanrolnik Ok, got it. It definitely adds some complexity to the token management and would require a cache per "defaultTopic" or bundle Id. This feature is critical for one of our projects which supports multiple iOS applications on one parse-server (multiple bundle ID's). Please keep me updated and let me know how I can help

natanrolnik commented 7 years ago

@EricNetsch if I remember correctly, you already can send push to multiple applications with different bundle ids in the current versions. Take a look here, and check how you can pass an array of configurations.

funkenstrahlen commented 7 years ago

I would also love to see this supported.

EricNetsch commented 7 years ago

@NatanRolnik that's not good solution. We need to be able to support dynamic bundle ID's without re-deploying the server code every time we have a new app. Using the tokenized method is the right solution

natanrolnik commented 7 years ago

@EricNetsch if I remember correctly, the module apn also requires the bundle id, otherwise it's not able to package the JWT. I might be wrong, but if that's the case, it would need re-deploying anyway.

EricNetsch commented 7 years ago

Yes, it does require a bundle ID to create a token. The idea is that you could pass it the bundle ID (dynamically) to create the token. All bundle ID's will work if they share the same Team Identifier. This would allow us to create tokens for new apps without having to re-deploy/update the server code. The bundle ID could be passed as a parameter when creating a token.

natanrolnik commented 7 years ago

There is a PR open that enables support for APNS Auth Token. You can look at it here: #52

However, @EricNetsch, the current implementation on that PR does require a deploy in order to add/remove bundle IDs.

flovilmart commented 7 years ago

@natanrolnik with the release of v2.0.0 that features APNS v2 is that issue still relevant?

natanrolnik commented 7 years ago

🙏🏻🎉