iOS13 PKPushCredentials broken

Hi guys


Just been testing our app under iOS13 and I've noticed something odd with VOIP push notifications when getting the token


When I obtain the push token to send to the server, the value looks completely wrong under iOS13


In iOS12 and before this would be a typical token that was returned from credentials.token


<124686a5 556a72ca d808f572 00c323b9 3eff9285 92445590 3225757d b83997ba>


Whereas now under iOS 13, the same call returns this (including the brackets, dots and text)


{length = 32, bytes = 0xd3d997af 967d1f43 b405374a 13394d2f ... 28f10282 14af515f }


Of course when I pass this to the server to send on to Apple to send for the push notification, I get the following response from the Apple server


Invalid Device Token Format Error sending Apple Push Notification Device Token has a length of [69] and not the required 64 bytes!


Does anybody know what is going on here


Hope you can help


Trevor

Replies

So it turns out that the description method on NSData now returns different results.


Originally my code was as follows....


-(void)pushRegistry:(PKPushRegistry *)regsitry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {

NSData* deviceToken = credentials.token;

NSString* tkn = [NSString stringWithFormat:@"%@", deviceToken];


This gave me a token of something like


<124686a5 556a72ca d808f572 00c323b9 3eff9285 92445590 3225757d b83967be>


which I could then remove the chevrons and spaces and use for the push notification.


But now, the same code gives me the following string


{length = 32, bytes = 0xd3d997af 967d1f43 b405374a 13394d2f ... 28f10282 14af515f }


After spotting this I'm now using


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {

const unsigned *tokenBytes = [deviceToken bytes];

NSString *tkn = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",

ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),

ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),

ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];


which gives me the correct string for the token for push notification


So the format of the [... description] has changed under iOS13, didn't see that documented anyway!


Before anybody mentions, yes, it was a school boy error to use the description method


Hope this helps somebody


Trev

Which SDK did you use to Build the App.

I have done similar things with description of data but did not seen an error with iOS 12 build on an iOS 13 device.

we have same issue. Some of ios 13 device token string broken but some of is correct format. Do you know any solution or update for this problem?


Update: If user already installed app, push token return correct format otherwise push token string broken same with trevr2example.

{length=32,bytes=0x3d1697e3f8d9d1db7402b4d043e...55103f58353a8896}

So our project has a deployment Target of iOS11.0


The solution that worked for me was to no longer use the description method, this is always dangerous as this could change (and obviously has). I've changed our code to that as shown in my second post and this works fine on both ios12 and ios13

Hi guys


I just found a temporal solution but I don't know it is correct, try to change [.... description] to [... debugDescription] only for iOS13, similar like this:


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *tokenDescription = [[[UIDevice currentDevice] systemVersion] floatValue] >= 13.0 ? [deviceToken debugDescription] : [deviceToken description];
    NSString *token = [tokenDescription stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    ......
}


As you said, it seems that the [... description] format has changed in iOS 13, but there is no documentation about that!

you could try Facebook' lib solution.

https://github.com/facebook/facebook-objc-sdk/blob/master/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKInternalUtility.m#L571

+ (NSString *)hexadecimalStringFromData:(NSData *)data
{
    NSUInteger dataLength = data.length;
    if (dataLength == 0) {
        return nil;
    }
    
    const unsigned char *dataBuffer = data.bytes;
    NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
    for (int i = 0; i < dataLength; ++i) {
        [hexString appendFormat:@"%02x", dataBuffer[i]];
    }
    return [hexString copy];
}

I have the same issue. Also, I don't think it is safe to expect the device tokens to always be 32 bytes. I found this from raywenderlich.com that handles the "{length = 32, ...}" description scenario...


let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }

deviceTokenString = tokenParts.joined()


However, it doesn't work for the other tokens with description "<... >" 😕

This is a really serious change that will break a lot of apps. The "description" method has been the documented way to get the push token in dozens of books, hundreds of online tutorials, SDKs, etc.


For example, this StackOverflow answer guides readers towards this implementation and has over 160,000 views: https://stackoverflow.com/questions/8798725/get-device-token-for-push-notification/8798981#8798981


This problem was introduced in iOS 13 Beta 2 and doesn't appear to have affected Beta 1. So even though we tested the beta, we didn't notice until just now.

Bumping this up to show more signal that this is a pretty serious breaking change that affects a lot of apps...

We are getting same error. Some times device token call returns including the brackets, dots and text.

???

Why is this change happening? I am really puzzled, as already mentioned it was the described (in many many places) way to get the token.

Do we have to update all our apps and resubmit it to the store? Or will there be a change back in 13.x?


(Already wondered why I get less Notifications with 13.1)

When i can find this source code? What the file?

You are again doing a dangerous mistake. APNS token length is not fixed and can change over time.

The following code or something similar can be a feasible solution that doesn't depend on the assumed and hardcoded token length:


constchar *data = [deviceToken bytes];
NSMutableString *token = [NSMutableString new];
for (NSUInteger i = 0; i < [deviceToken length]; i++) {
    [token appendFormat:@"%02.2hhX", data[i]];
}

self.application.devicePushNotificationToken = token;


And by no means any developer should use the description method of any object unless that is explicitly overriden and you know the expected outcome. That method has merely been put for debugging purpose and can change without any documentation update.