Hi,
We have a service, which is spanned across servers in multiple regions. We are using Token-based Authentication to communicate to APNS to send notifications to our clients. As per Apple Documentation, the authToken is a combination of KeyId, TeamId, issuedAt fieldd and a signing key used to sign the JSON data. We use the same authToken properties(KeyId, TeamID) to contact APNS via HTTP2 in all of these servers, except that these servers generate the token on their own once every 59 minutes, by adding issuedAt field.
As per Apple Documentation,
Refresh Your Token Regularly
For security, APNs requires you to refresh your token regularly. Refresh your token no more than once every 20 minutes and no less than once every 60 minutes. APNs rejects any request whose token contains a timestamp that is more than one hour old. Similarly, APNs reports an error if you recreate your tokens more than once every 20 minutes.
On your provider server, set up a recurring task to recreate your token with a current timestamp. Encrypt the token again and attach it to subsequent notification requests.
Currently, what we are observing is that we are receiving '429 TooManyProviderTokenUpdates' error very often. I am updating the token in each machine once every 59 minutes. What I am suspecting is that we are updating the authToken simultaneously (closer than 20 mins) in multiple machines which are making calls to APNS, and therefore we are getting this error. Can someone please confirm if this is the case?
Also any suggestions to how to solve this issue?
One solution could be to have all the machines in sync and only one machine update the token and store in some database for other machines to fetch. I tried another solution where in all the machines I am just using current UTC time and rounding down to the latest hour, as UTC will be globally unique time and so all machines will send the same token in sync. But this solution did not work. My code is in C#. Posting code sample below.
///
/// We are rounding down time to 0 and 30 min mark, so that we do not end up changing token every 20 mins across machines
///
///
private DateTime RoundDownUTCNowTimeStamp()
{
DateTime roundTime;
DateTime currTime = DateTime.UtcNow;
if (currTime.Minute <= 30)
{
roundTime = new DateTime(currTime.Year, currTime.Month, currTime.Day, currTime.Hour, 0, 0, DateTimeKind.Utc);
}
else
{
roundTime = new DateTime(currTime.Year, currTime.Month, currTime.Day, currTime.Hour, 30, 0, DateTimeKind.Utc);
}
return roundTime;
}