Android Time Synchronization in UTC - android

I have an application that relies heavily on current timestamps. Currently, when user submits a request, I get the current timestamp in UTC using System.currentTimeMillis(). While this works fine, it becomes a problem when the user starts manipulating their Date/Time on their device and would result as inaccurate timestamps.
Why do it on the client then? Why not just handle it on the server? Well, my application needs to work offline. All my requests get pushed into a jobQueue when connectivity to the internet is unavailable. In these cases, I must have the original time wherein the user did the action so if I submit a request at 4:02pm, but due to network problems, server will only receive it around 7:30pm, server MUST know that I sent the request at 4:02pm.
Now what options have I considered?
Upon user login, I sync the device time with the server time and store that time locally. If any user manipulation occurs while the user is logged in, I'll have a BroadcastReceiver listening in onto any intents of Date/Time manipulation, then store the offset so that whenever a user submits a request, I will calculate the synced time with the offset to ensure the timestamp is accurate.
Have a server sync api done in the backend and set up a service within my application to continuously sync up with the server time and look for any drift while also listening in onto any user manipulation.
Use push notifications and listen downstream for time synchronization adjustments while also listening onto any user manipulation.
I could also make use of the NTP servers to synchronize time with my device.
I'm not entirely sure which would be the most optimal (assuming I have listed down all the possible solutions). If there are other solutions I haven't thought of, please let me know.
P.S. If I happen to use the BroadcastReceiver to listen onto any datetime manipulation on the device, how would I even calculate the offset in that?

It has been some time since I asked this question and there hasn't been any elegant answers to the problem so after some research and some trial and error, I decided to take the NTP route and after some digging around, I found a nice library that does the entire thing for you.
It can be found here:
NTP TRUE TIME
Credits to these guys who had made life a lot easier.
You must sync with the ntp servers just once and from there on, they will calculate the Delta for us giving us accurate UTC regardless of SystemClock time.

For time synchronization you can implement like getting time zone from server. Once we have timzone we can get the current time of server.

Related

Preventing request replay attack

I have a simple REST API and to prevent the request replay attack. I have added a UTC timestamp with the request and allowing request if the difference in seconds in not more than 60 seconds.
This API is consumed by Android and iOS applications. After moving the app into production, we realized that most of users have inaccurate time and time zone and this prevents them to use the app.
How can I improve the mitigation?
Any chance I can get UTC time irrespective of phone's time and timezone?
You should not rely on the timestamp sent by the device, as it may be easily tampered with.
If (and only if) you are able to identify requests coming from the same user or device, then you can use the timestamp on the server and do the same mitigation strategy, but this time you have a unified time measure. (You need to save the "last" access timestamp on per-user or per-device basis.)
A way to identify an user or a device can be that of creating a hash of (e.g. time of first run + IP address + ...) the first time of use, and send that along the REST API request all the subsequent times.
If the user is required to log-in, then you could save this value along with the user's info; otherwise you can "identify" the device similarly.
EDIT: This edit is in light of your comment which adds information that was not clear before
I want to check if the originating time of the request and the receiving time on server should not have large interval (say more than 1 minute).*
Rephrasing, you want to invalidate requests based on their generation time (not older than 60 seconds). If now I interpret it correctly, the idea is that very likely client's requests would need much less than 60 seconds to be answered, so the assumption is that too-old a message was very likely already consumed properly - it might be a reply attack.
Unfortunately, your solution would only (predictably) reduce the space of messages that the attacker can use to carry out reply attacks, that are therefore far from being prevented, even with synchronised timestamps. Additionally, if the message can be tampered with, i.e. the attacker can freshen old messages with newer timestamps, the the mitigation would be totally ineffective.
Anyway, if your purpose was not that of preventing reply attacks, but to simply discard expired messages, then you can achieve your goal by offering two REST APIs:
one for "preparation" (you do not even need to collect a reply)
the other for the actual "request"
and both with client's timestamps and with the same request identifier.
So you will see server side the two pairs timestamp-requestID: (t,ID) and (t',ID).
This will allow you to simply make the difference of timestamps, t' - t, which is independent on the time shift or time zone they set up.
You can also time the requests server-side to discard the "request" arriving too late related to their corresponding "preparation".
Additionally to improve security, you might let the client App sign the messages (including the timestamps and the request ID) to guarantee integrity - the messages cannot be tampered with without noticing, so that you can rely on timestamps sent to the APIs. One way is to use public-key cryptography, but be careful on how you distribute public keys.
(This way you limit the attacker to reply only the most recent requests).

Is it good practice to fetch current time from internet?

I am making a mobile application and I need to have the current time. However, I don't want to depend on the user's phone time since it can be changed to whatever they want. Is it a good practice to fetch from a server its local time every minute or similar interval?
P.S: The app will use the time to show if a shop is open or closed so I don't mind about different timezones, I only need the time in the server's timezone.
Depending on the need of the application. If your application would require a connection from the internet, then yes. You can also put that in case there is an issue catching the online time, you can just take the user's time.
From personal experience I never had issues that the user would want to change their phone time, but there have been a few exception.
To use server times is fine. But based on that making decisions on data (shop open/not) is not a good practice. Whenever you make an api call, get the status if its closed or not. This will avoid user side data issues
If you want to show this information on a single shop page, fetch the time difference between current time and closing time from the server. This will help you to maintain the status on app side. this should not be for a very long time. You can use this solution if the difference is less than 10 or 15 mins.

Mobile App: how to get correct time when offline

We're building an App using Ionic/cordova that will need to run on Android, iOS and Windows 10 Mobile.
The goal is to register start and stop events, we'll need the exact time and location when this events are registered.
There is a serious concern that the users will modify the timesettings on their phone to send false data.
As long as these events are sent immediately to the server, we can use the server time to validate what the user is sending us. But there is also a requirement to be able to work when offline.
Our first thought was to use the GPS time. In cordova the position object has a timestamp.
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-geolocation/
But after further reading, here and here, that this isn't necessarily the time of the GPS server but also just the local time. I've read about work arounds using the uptime of the device, but this won't work as soon as there is a reboot. But most of these conversations are a few years old.
For now we think the simples approach will be to flag events that are sent offline as 'suspicious'.
Is there any other way to accurately determine the time when you're offline without risk that the user tampered with it?
Haven't tried it myself,but what about getting the time from the Network Provider, as said in this SO: I want to get time from GSM network
long networkTS = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getTime();
Time returned by getLastKnowLocation could be old if you want current
time use
locMan.requestSingleUpdate() and pass the network provider
Though, this may not work in iOS or Windows.

Keeping an app's internal time in sync

Disclaimer: I am a backend developer, and I have no idea of what happens inside an Android or iOS app, so please bear with me.
In a specific use case of our platform we would need all client applications (Android and iOS) to keep an internal timer accurate and in sync with an external source of time (so that they can accurately timestamp messages sent between one another). Is this possible at all (using, for example, an NTP client or a different / better technique)?
When the client connects to the server it can fetch what the server's reference time source is. Once it has obtained this it can calculate and store the difference between the server's time and the device's time.
Then when the client needs to do something based on the time* on the handset it takes the server's time into consideration when doing whatever it needs to do such as schedule a timer or whatever.
*You can't really do anything based on time in iOS, only if the app is in the foreground. An exception is posting a local notification. Its not possible to schedule a timer for example if the app is in the background.
As per Martin H, you could use an offset from the device's internal time. The client device will probably be within a second of current time if the user has not manually set the time (which does happen - I just read about a user that changed her date/time to tomorrow to get a reward in a game).
I have dealt with this in a time-based app by using the device time. The client and server validate against server time when communicating with the server.
For example, when the client and server communicate, the server can validate the client time against server time. If the user time is off by more than 'x' minutes, the server sends back an error message.
It will be difficult to keep all clients within a few milliseconds of each other. One idea is to use the server to coordinate messages (messages are not sent between devices, but to the server, which then sends the message on). Then, you can use the received time at the server as the basis for the message time.

Get accurate time from android/iphone to server

We have an android(or iphone) client we are developing. The client allows the android user to send entries to a server which we also develop. If the client does not have data services (GPRS) at the moment the user sends the entry to the server, the client also supports saving the entry to an offline database and sending it later to the server.
One important aspect of the whole process is accuracy of the timestamps on which the user sent the entry to the server (whether the entry is made in real time or sent by the client from the offline database)
When available on the client, we get a GPS location and are able to use the GPS timestamp to send that to the server (or save the GPS timestamp on the offline DB and send it later to the server). However if the user has turned off the GPS (and all other location services), the device will not have a GPS fix and therefore the server can not determine accurately when an entry was made.
We can not use the local device clock as the user may change the clock to make entries on different times than they actually occurred (these entries are part of the users salary so he might have an interest to "fix" them).
So basically I am searching for a way to determine as best I can the time some entry was made when I can not trust the internal clock of the mobile. The algorithm should support both entries sent in real time or entries sent from an offline DB. the algorithm should also support cases where the user changes the time of the mobile, turns the mobile on/off, turns the GPS on/off while the application is running on the mobile etc...
Few ideas that I thought of:
Although I can not trust the mobile's time, it can still perform as a stop watch:
Have a class that will loop until the application exists, the loop will sleep 1 second and increase an internal clock variable by 1 second. On every GPS location my code gets we update the internal clock variable. This way I have an absolute clock that came from outside the device (from the GPS) and when the client sends an entry to the server, we can use the internal clock as an absolute time.
PROS: the user can not modify this clock as it is only updated when we get a location from the GPS
CONS: the application needs at least one GPS fix before the user can make any reliable entries
I can take advantage of the fact that the server has an accurate clock which is correct. If the client would send to the server info that the age of the entry is 10 minutes, the server could use its internal time and know the exact time the entry was made on.
The biggest problem is how to know the entry age? I thought about saving the entries to the offline DB with an age of 0, then every 1 second increase the age of the entry in the DB. The problem is that if the app is closed and/or the device is off this will now happen
This is where I am currently stuck. Any ideas on how to solve this are more than welcome
Thanks
Here's how I handle this issue for iPhone. When the app starts, I call my server and ask for the current GMT time (you could also call a public NTP server if you preferred). I then compare it to the system time. If it is different by more than X then I popup a message saying, sorry your system time is wrong so you can't use the app until you fix this. I then monitor for the user changing the system time while the app is running and if they do that, then I do the compare again (and popup the error message if the time is off by more than X). This ensures that their system time is always correct (within some reasonable allowance) and you can trust [NSDate date]. However, this solution does require a valid network connection. If this solution works for you, I can post the sample code.
i think i am going to combine Jules and Joel's answers into one solution which will provide for my needs the best solution:
since the user might change the clock when the mobile doed not have GPRS, just detecting the time change event will not help us as we can not validate at that moment the new time is correct.
As Joel recommended i will pull the time from my server when my application is started (at that point i still must have communications with the server or else my application will not start). The time pulled from the server along with the current device upTime will be saved.
when the user wants to make an entry i will calculate the current time using (Server Base Time + Current UpTime - Base UpTime). this way i will have an independent source of time regardless of the current clock of the device
this will defenitly work on android
on iPhone we will try to use something out of http://www.cocoadev.com/index.pl?FindingUptime to get the upTime
Jules & Joel, thanks for your answers!
Look into android.os.SystemClock. Specifically, elapsedRealtime() returns a time since the phone was switched on, which is not affected if the clock is changed by the user.
You can correlate times in event the phone is switched off by having code that runs when it is switched on and checks the realtime clock. As the clock can't be changed when the phone is off, I suspect you could use this to put together a system that will catch any simple attempts at cheating. (If the user roots the phone all bets are off -- they could modify the behaviour of the APIs from under you).
Running code every second will kill the phone's battery life. Most phones would be unlikely to last a day if you did this.

Categories

Resources