How can I flag an abuser and potential hacker's device, given the fact that it can only be done if the device sends a token?
We can wait for the user to send a request containing the token, until then act natural so the user won't suspect, then flag the device.
But it is a possible scenario where we spot a bad user, but the user stops the iOS app from sending any token.
How can we flag this user's device?
Related
I come bringing a query about Firebase in Swift. My app configures Firebase and thus gets the firebase token upon launching. I store the token with no issues and go ahead.
But... What happens if the user launches the app when his device is offline? The app tries to retrieve the token, but fails because there's no internet connection. It tries up to five time and then stops trying.
The app is also locked in the login screen because to be logged you need to have Internet.
Imagine if after the five tries, the device finally gets a connection, and the user logins and enters the app. But I don't have a firebase token and I can't send notifications to the user until he restarts the app!
Can I somehow retry the firebase registration if the user logins without a token?
Thanks a lot in advance.
You don't have to solve a problem that isn't actually a problem. A push token won't always get refreshed. Here's the description of Firebase's didReceiveRegistrationToken.
This method will be called once a token is available, or has been
refreshed. Typically it will be called once per app start, but may be
called more often, if token is invalidated or updated.
Furthermore, like Firebase said, once you this method gets invoked, take advantage of it and store the token in your server! When the user starts your app without internet connection, don't worry about it. The user has probably saved the token onto your server. And if the user starts your app for the first time, and without the internet connection, don't worry about it too. He'll get a new one in the next run.
I hope this helps.
After googling more further, I've found that calling InstanceID.instanceID().token() does trigger a new retry to get a FCM token if your current token is empty, and returns your current token if you have one.
I've added that call when the user successfully logins, so that the app can atleast try to get a FCM token again.
I have a VOIP IOS application based on pjsip. I have a problem with network switch. For example when my app becomes inactive the network might change and when I get push on incoming call I can not answer because I don't have registration. I don't know what is the best way to figure out if I have registration on PARTICULAR NETWORK or not. (It is not enough to check pjsua_acc_get_info because it still might have registration from previous network).
Registration is done in a periodical basis. You can state that you are not registered if the time for registration has expired. So you should check also, as stated in Chek account registration status the field "expires" from the struct returned by pjsua_acc_get_info
Apples docs are a bit vague on when a device's deviceToken can change. It pays to code defensively, and to test that code.
I've written my app so that at startup it registers for push notifications and handles the didRegisterForRemoteNotificationsWithDeviceToken callback.
My didRegisterForRemoteNotificationsWithDeviceToken saves the last device token to user defaults, and if the token is still the same, it moves on. If it doesn't have a saved token at all, or if the tokens don't match, it uploads the new token our server.
I also have a mechanism that lets me name my test devices with human-readable names like "4s_1" "5s_1" "5s_2", etc. I have a server command line tool that takes the human-readable device name, looks up the device's 'identifierForVendor' from that, and then looks up the device token using the identifier. It then triggers a sandbox notification.
It seems that deleting the app and reinstalling it causes the 'identifierForVendor' to change, but not the deviceToken, which is exactly the opposite of what I'd like to have happen for testing. I want some value that never changes to uniquely identify a test device, and away to change the device token so I can test my code.
EDIT: Since writing this I've changed the app to generate it's own UUID and save that to the keychain as suggested by Wain in his answer.
Is there a way to force Apple's APNs to change a device's token so I can test out my code (both client side and server side) for handling the case where the token changes?
I don't believe so.
If you want a single unique identifier then you should create one explicitly and store it in the keychain, then you can store the device name and all other details against this so you have a single point of truth.
Any identifier you stored in the keychain would survive until it was explicitly removed or the device was restored from a backup without that keychain content.
I'm not sure if this approach also resets the token, but you may try to reset the permission:
Resetting the Push Notifications Permissions Alert on iOS The first
time a push-enabled app registers for push notifications, iOS asks the
user if they wish to receive notifications for that app. Once the user
has responded to this alert it is not presented again unless the
device is restored or the app has been uninstalled for at least a day.
If you want to simulate a first-time run of your app, you can leave
the app uninstalled for a day. You can achieve the latter without
actually waiting a day by following these steps:
Delete your app from the device. Turn the device off completely and
turn it back on. Go to Settings > General > Date & Time and set the
date ahead a day or more. Turn the device off completely again and
turn it back on.
Regarding the change of device identifiers: You could install a second application on your test devices (a blank one from the same issuer). If you reinstall your actual app, the identifierForVendor shouldn't change.
Client side you could test be changing the stored device token.
Terminate App in device
Download (xcode devices window) the Container.
Find default in Library/Perferences/ app bundle plist.
Edit entry in plist.
Replace Container (xcode devices window)
Important: I found a restart of the device was required for the changes to take effect.
Then on restart your old device token will be incorrect and what ever action is required can be done.
I used this when debugging an adhoc app I did not have src code for. But, if you have src code might be easier to just make the compare of deviceTokens fail.
In order for us to send users iOS notifications the following flow occurs: a user installs our app, registers with APNS, and sends the registration token to our server to be used later to send notifications.
The above process is repeated for every device on which the user installs our app; we'd like them to get notifications on all their devices.
In addition to this, the process is repeated when a user uninstalls our app and reinstalls on the same device.
Every time the process repeats we get a new, distinct registration token. This is all well and good however, we noticed that only recently when our app is uninstalled, the device token remains valid after it is reinstalled and a new token is generated. It is our understanding that a single unique token can exist for a device.
Apple's documentation seems to suggest this as well (https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW12)
The form of this phase of token trust ensures that only APNs generates the token which it will later honor, and it can assure itself that a token handed to it by a device is the same token that it previously provisioned for that particular device—and only for that device.
When a new token is generated after reinstall and sent to our backend, we've got two device tokens that point to the same device and as a result we send multiple notifications to that device. Are we misunderstanding the documentation? If so, what's the typical way of dealing with the reinstall scenario?
Thanks!
We just did a test here. On our iOS 8.4.1 test device after reinstalling our app we've received the same token, whereas on iOS 9.1 we always receive a new token after re-installing. This wouldn't be a problem if APNS invalidates the older device tokens, but as far as I can tell it does not. The result is that we're sending duplicate notifications to our users to the same device. Maybe it takes some time to invalidate older token?
We decided to do a server-side fix for this and remove duplicate tokens for one user from our database. Not a good and permanent solution, but a short-term fix for us since our users use the app usually on one device only.
Yes, I am seeing a single device with the same app (my app), which has been issued different APNS over its short life, many of which are still capable of still receiving a push notification (from production APNS server).
The easy fix would be to just have our backend APNS sending service to only honor the last APNS token received. This is doable, assuming there is another primary key that is unique to every iOS device. Well, since UUID is no longer available, then we have to rely on the Apple Vendor ID. That problem with the Apple Vendor ID is that value can also change over time, so be sure to account for that.
We currently only send push notifications to devices which have our unique member/user ID. This is known to our app, once a user has signed into our app. So, we could use our member/user ID, but if a member/user has multiple devices, that means if we use the last APNS token value as the one that wins, than the same member could NOT have multiple iOS devices receiving push notifications (think iPad and iPhone, pretty common these days).
So, with that being said, when upper-management wants to send push notifications to devices in which no unique member/user has actually signed into, there is a risk of the streams getting crossed.
We have the same problem that we found 2 valid device tokens for 1 device.
However, when we tried to verify "uninstalling and reinstalling would generate a new device token, and the former device token is still valid", we got the opposite result.
Namely, the new device token was generated, but the former device toke became invalid.
I verified this on 3/9/2016 and 3/10/2016.
Not sure if Apple has fixed this bug partially:
a) when the app is uninstalled and reinstalled from now on, the old deviceToken become invalid. (no new issues)
b) currently valid device tokens will continue to be valid. (old issues can't be fixed, the device will still receive multi notificatioins from each valid device token)
Looks like we'll have to use "identifierForVendor" to distinguish a unique device: Cleaning our registration table (and keep the latest deviceToken only) if we see 2 deviceTokens share the same identifierForVendor.
"Every time the process repeats we get a new, distinct registration token".
Are you sure about that? 100% sure?
In my experience if you uninstall the app, then re-install it then 99.99% of the time you will get the same device token. If you are getting a new unique device token every single time you uninstall and then reinstall the app then that is something I've never seen in multiple years and multiple apps. Hence maybe something strange is going on.
There are instances when a new device token will get generated but they are rare, are you sure you are not doing something else between uninstallation/re-installation?
P.S. there is a different device token for production builds and release builds, eliminate this factor from your observations - i.e. make sure you're not doing something like installing a prod build, then uninstalling it and re-installing a dev build or vice versa. Even if you are doing this the total number of unique dev tokens would still only be two (though only one is valid per environment).
Im about to use GCM for android and APNS for ios in my app.
on my server side I save in my DB the device id and account id each login.
When the user logs out I delete that entry, so the user wont receive it any more (and even if it logs in with a different account on the same device)
The scenario im thinking about is when the user uninstalls the app while he is still logged in. That means the user didnt go through the logout request, which is the request that deletes the device id entry on my DB.
Now the user installs the app again but logs in with a different account.
In my DB i'll have the same device id with 2 account ids, which means the user will get push notifications that does not belong to him (his device will keep getting notifications for the previous logged account).
To my knowledge android got device id for each app "instance" so I dont have a problem here (even though a message will be sent to a ghost device which is weird), but on ios I know the device Id you send to apns is unique to each device...
Bottom line -
Did I get anything wrong?
Solution I thought about is setting timeout for device same as the login timeout (still the interlaced time will get notifications from 2 accounts)
Still this problem look very trivial and that must be a cleaner solution.
For iOS, an approach would be to add a key to NSUserDefaults to check if the app is on its first run or not.
On successive runs, if the above key is present, you do nothing since it isn't your first run. If the key is not present yet ( first run after install ) you send a request with the deviceid, which removes the current deviceid from your server DB with all its logged in entries. You set the key to true, then you can proceed to normal login.
This will only work if the deviceid doesn't change between installs.
I guess there is a similar mechanic for Android too.