Describe the bug
It appears that Endpoint addresses are being saved incorrectly on iOS 13. The CLI shows that they are being saved as follows:
"Address": "{length=32,bytes=0xbffe8061069c0eee935443596bdaeaa3...7aeb1d152cb856d0}"
instead of the following on iOS 12:
"Address": "ff37d7e6a223f0014d5409de0b42ffeb16e3059dedcb425b2546f1ada14cd71d",
The above are both from the same version of the app, using 2.11.0 of the API.
Testing via the Pinpoint dashboard also provides an error when sending to these endpoints. Error text from console is:
Message not sent: We weren't able to send your push message to {length=32,bytes=0xbffe8061069c0eee935443596bdaeaa3...7aeb1d152cb856d0}.
Details
Request Id 492 : {"errorMessage":"Unregistered or expired token","channelType":"APNS","pushProviderStatusCode":"0","pushProviderError":"Device token is invalid in hex form","pushProviderResponse":"hexBinary needs to be even-length: {length=32,bytes=0xbffe8061069c0eee935443596bdaeaa3...7aeb1d152cb856d0}"}
To Reproduce
Register for push notifications on a device running iOS 13, then pull endpoint data via the CLI or try sending a test message via Dashboard
Which AWS service(s) are affected?
Pinpoint Push notifications for iOS
Expected behavior
Store the token address in a useable format
Environment:
```
pod 'AWSCore', '~> 2.11.0'
pod 'AWSMobileClient', '~> 2.11.0'
pod 'AWSS3', '~> 2.11.0'
pod 'AWSAPIGateway', '~> 2.11.0'
pod 'AWSPinpoint', '~> 2.11.0'
- Dependency Manager: Cocoapods
- Swift Version : 4.2
**Device Information (please complete the following information):**
- Device: iPhone XS Max, iPhone XS
- iOS Version: iOS 13.0
- Specific to simulators: No
**Additional context**
The below is output from get-user-endpoints from the aws CLI to better illustrate the issue:
**iOS 13**
{
"EndpointsResponse": {
"Item": [
{
"Address": "{length=32,bytes=0xbffe8061069c0eee935443596bdaeaa3...7aeb1d152cb856d0}",
"ApplicationId": "99f506c7dd954d6883b738ad020f5364",
"Attributes": {},
"ChannelType": "APNS",
"CohortId": "8",
"CreationDate": "2019-06-21T15:44:50.413Z",
"Demographic": {
"AppVersion": "1.3",
"Locale": "en_US",
"Make": "apple",
"Model": "iPhone",
"Platform": "ios",
"PlatformVersion": "13.0",
"Timezone": "America/Chicago"
},
"EffectiveDate": "2019-09-19T20:21:04.845Z",
"EndpointStatus": "ACTIVE",
"Id": "e185925b-a353-452f-8031-3c1204aec824",
"Location": {
"Country": "US"
},
"Metrics": {},
"OptOut": "ALL",
"RequestId": "a3d904c5-f98a-46f6-97df-2185c709dbe9",
"User": {
"UserId": "fafd32c3-fd60-4474-b787-0cd9c6aa43a4"
}
}
]
}
}
**iOS 12**
{
"EndpointsResponse": {
"Item": [
{
"Address": "ff37d7e6a223f0014d5409de0b42ffeb16e3059dedcb425b2546f1ada14cd71d",
"ApplicationId": "99f506c7dd954d6883b738ad020f5364",
"Attributes": {},
"ChannelType": "APNS",
"CohortId": "66",
"CreationDate": "2019-09-19T21:03:43.946Z",
"Demographic": {
"AppVersion": "1.3",
"Locale": "en_US",
"Make": "apple",
"Model": "iPhone",
"Platform": "ios",
"PlatformVersion": "12.4.1",
"Timezone": "America/Chicago"
},
"EffectiveDate": "2019-09-19T21:03:44.358Z",
"EndpointStatus": "ACTIVE",
"Id": "a30308ad-ccb4-4e96-8df9-c92cf1920006",
"Location": {
"Country": "US"
},
"Metrics": {},
"OptOut": "NONE",
"RequestId": "a792d3a2-6149-498d-b825-ec385fda8557",
"User": {
"UserId": "5e55781d-5f06-44b4-b1cb-7dde3070ae5d"
}
}
]
}
}
```
@xC0der Thanks for the report and the investigation. Looks like we'll need to change the way the address is serialized into the payload.
Looks like the problem is how we convert from NSData to string. In https://github.com/aws-amplify/aws-sdk-ios/blob/master/AWSPinpoint/AWSPinpointEndpointProfile.m#L67, we use description to retrieve a hexadecimal representation of the bytes, and then do some string manipulation:
NSString *deviceTokenString = [[[[userDefaults objectForKey:AWSDeviceTokenKey] description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
The description behavior changed in iOS 13:
let data = Data([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f])
let base64Encoded = data.base64EncodedString()
let nsData = NSData(base64Encoded: base64Encoded, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
// iOS < 13: produces "data.description: 16 bytes"
// iOS 13: produces "nsData.description: <00010203 04050607 08090a0b 0c0d0e0f>"
print("data.description: \(data.description)")
// iOS < 13: produces "nsdata.description: 16 bytes"
// iOS 13: produces "nsData.description: {length = 16, bytes = 0x000102030405060708090a0b0c0d0e0f}"
print("nsData.description: \(nsData.description)")
We'll need to convert the bytes directly or use a purpose-built API, instead of relying on description.
We've put in a fix for this on #1928, which we're reviewing and testing now. Assuming all goes well, we'll plan on releasing this tomorrow with 2.11.1.
In the meantime, you can use the PR as a patch; or wait for it to be merged into the master branch and build from that.
Thanks again for finding & troubleshooting the issue--it saved a lot of time on our end!
Awesome turnaround time - thanks!
This was released on https://github.com/aws-amplify/aws-sdk-ios/releases/tag/2.11.1. Please let us know if you have any problems.
I just finished testing, and can confirm that it does now store the token properly on iOS 13 and push notifications are successful. Thanks again!
Response from the CLI below:
{
"EndpointsResponse": {
"Item": [
{
"Address": "5cd3b73d6a5ec0f56a8ce5361583cebe6ad67eec14f57f5b04f7d03396c76eed",
"ApplicationId": "99f506c7dd954d6883b738ad020f5364",
"Attributes": {},
"ChannelType": "APNS",
"CohortId": "8",
"CreationDate": "2019-06-21T15:44:50.413Z",
"Demographic": {
"AppVersion": "1.3",
"Locale": "en_US",
"Make": "apple",
"Model": "iPhone",
"Platform": "ios",
"PlatformVersion": "13.0",
"Timezone": "America/Chicago"
},
"EffectiveDate": "2019-09-20T18:07:16.691Z",
"EndpointStatus": "ACTIVE",
"Id": "e185925b-a353-452f-8031-3c1204aec824",
"Location": {
"Country": "US"
},
"Metrics": {},
"OptOut": "NONE",
"RequestId": "6f9e6e08-b2d3-43bc-baf1-76454cdcf0a3",
"User": {
"UserId": "fafd32c3-fd60-4474-b787-0cd9c6aa43a4"
}
}
]
}
}
Thanks for confirming!