Using Mobile Device IDs as additional factor of authentication(something you have)
Introduction
If you are a producer of mobile apps used by your end customers, it is critical for you to keep track of the which devices have your mobile app installed by using a unique permanent device identifier(Device ID) on the mobile device. Besides the many uses that a unique mobile Device ID could have for you to increase the usability and personalization of your mobile app (out of scope for this paper), one of the key advantages in the security realm of a unique device ID is to keep track of the particular device associated to a particular user. Then if the user uses a different device to sign in to your site(or your server side API), you could challenge the user via an One Time Password(OTP) sent over a SMS or an email, thus introducing an additional factor of authentication in the user identification and authentication process.
In this blog post, I will cover some of the best ways to create a device ID for your android and ios mobile apps to use the device ID as a “something you have” factor of authentication by linking the mobile device to the user account.
Key Requirements of a Mobile Device ID:
Before we get into solutioning on how to generate a Device ID, here are some of the main characteristics a permanent Device ID needs to have in order for it to be effective:
1. Device ID needs to be able to survive App Upgrades. We know the mobile app providers release upgrades to the mobile apps regularly. If the Device ID changes on each app upgrade, the mobile user will be challenged via an OTP on every app upgrade, thus deteriorating the user experience and resulting in user fatigue and user abandonment for your mobile app. Thus, it is of utmost importance, that the device ID of the app not change between app upgrades, thus reliving the user of unnecessary authentication workload.
2. Device ID needs to survive Mobile OS backup and restore and Mobile OS upgrades. The permanent Device ID should also not change when the user does a back and restore of the Mobile OS or upgrades the Mobile OS again.
3. Device ID needs to be cryptographically random so there are minimal chances of the collision. With tens of millions of mobile users it is very important that the Device ID are globally unique so as no two users get identical Device IDs. Gladly, a lot of researches have already worked on this problem and the mobile app developers don’t need to worry about how to do it — just use the readily available solutions to do this without writing their own solution (discussed below).
Where to generate the permanent Mobile Device ID
The permanent mobile Device IDs can be generated both on the server side as well on the mobile app itself during the app installation. Although, both have their advantages and disadvantages, my personal recommendation is using the mobile app itself to generate the Permanent Mobile Device ID just to use OS functionality available on the mobile devices to do so and reliving some of the load from your servers. Google Play API recently started providing a server side Instant ID to provide a Global Device ID for your mobile device and it is also a viable option to create Device ID. What you pick will be totally upto your use case.
Device ID generation on Client side (on mobile device)
- Can be generated during app installation
- No network call to get device ID
- Can use the processing power of the device
- The good news is all major mobile OS make it very simple to generate on the device side.
Device ID generation on the Server
- Consistent implementation for all platforms including iOS, Android, Windows
- More control and more predictable device ID
- Independent of the mobile operating system
Options to generate Mobile Device ID on Apple iOS
On Apple iOS devices, there are several ways to create a device ID. This includes a CFUUID, NSUUID, OpernUDID, IDFV, Ad ID and UDID. This blog post written by Jay Graves does a very good job of detailing several options and a nice comparison and characteristics for all of them. You may be able to use one of them as per your use case but generically I strongly recommend that you use NSUUID for your mobile apps on iOS 6+ and CFUUID for supporting anything earlier than iOS 6 for the identification and authentication use case we described above.
Use CFUUID for iOS 5 or earlier
Similar to NSUUID just a different way of implementation in the code
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
Use NSUUID for iOS 6 and later
- Creates a random 128 bit Universally Unique ID
- It is not persisted at all
- App needs to store it in the device keychain and also NSUserDefaults in case the provisioning profile is changed during an App upgrade
- NSUUID is newer and has a nice modern Objective C interface
- UUIDs (Universally Unique Identifiers), also known as GUIDs (Globally Unique Identifiers) or IIDs (Interface Identifiers), are 128-bit
- values. UUIDs created by NSUUID conform to RFC 4122 version 4 and are created with random bytes using PRNG.
- Almost not chances of collision
- “Only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%”
- Example: 68753A44–4D6F-1226–9C60–0050E4C00067
- Very easy to call in native code:
NSString *uuid = [[NSUUID UUID] UUIDString];
Options to generate Mobile Device ID on Android Devices
When it comes to Android mobile devices, there are several options just like Apple devices to generate Device IDs. Here are all the options you have to generate Device Ids on the Android Devices.
Android ID
- 64 bit quantity generated when phone is booted for first time
- Problems
- Reset when phone is wiped
- Not 100% reliable on releases prior to 2.2
- There has been at least one widely-observed bug in a popular handset from a major manufacturer, where every instance has the same ANDROID_ID
IMEI or MEID or ESN (Device ID)
- Android allows to retrieve IMEI for GSM and the MEID or ESN for CDMA phones
- Problems
- It doesn’t work reliably
- When it does work, that value survives device wipes (“Factory resets”) and thus you could end up making a nasty mistake when one of your customers wipes their device and passes it on to another person.
- You have to ask user for an additional permission to read device state
Mac Address
- As of Android M, it is possible to retrieve a Mac address from a device’s WiFI or Bluetooth hardware
- Problems
- Not reliable as not all devices have WiFI
- If WiFi is not turned on, the hardware may not report a Mac Address
Serial Number
- Since Android 2.3 (“Gingerbread”) this is available via android.os.Build.SERIAL
- Devices without telephony are required to report a unique device ID here; some phones may do so also
- Problems:
- Not reliable
Random UUID
- One of the best option is to use an UUID as an identifier and simply create a new one when the app initializes or runs first time after installation.
- Random UUID is generated using the variant 2 of RFC 4122, the Leach Saltz variant and Android provides a way to generate it very easily in your add code.
- Below is a way to generated the UUID in your android app code:
String uniqueID = UUID.randomUUID().toString();
Instance ID
There is another better mechanism to create a unique identifier for your mobile apps using a server side mobile service provided by Google Play. It works on iOS, Android as well as Chrome apps/extensions. It involves importing a Google Play services SDK in your app code and then getting the Instance ID at App runtime. As I mentioned before, this is a server side way of generating a Unique Device ID. This is another very good alternative to create a UUID for your mobile apps. You would need to be the best judge whether generating a client side UUID or a server side UUID using instance ID will work best for your use case.
Implementation in your app code
The three best methods I mentioned above for iOS(NSUUID), Android(Random UUID) and Android(Instance ID) create unique identifiers that are non persistent. For Apple devices, you would have to store the Device ID in the device keychain and for Android devices, the UUID needs to be stored in the internal storage for the app so it is not shared with other apps. It is recommended to follow below behavior during the App lifecycle.
Conclusion
There are many other identifiers available for both iOS and Android as I discussed above. You must see which one will be the best identifier to use as per your use case. However, the three methods I mentioned above for iOS(NSUUID), Android(Random UUID) and Android/iOS(Instance ID) are the best methods to create a unique Device Identifiers for your mobile app instances as of February 2017. This can be used to link the user account to the Device Identifier and then challenge the user if the user is coming from a device identifier that does not map to the one stored against the user account.