3

I develop a kind of casino application, and users can win real cash on it. To avoid fraud we need to check that user only use one device at the same time.

When I look to Android doc about how to identify device : https://developer.android.com/training/articles/user-data-ids#best-practices-android-identifier:

Use a Firebase installation ID (FID) or a privately stored GUID whenever possible for all other use cases, except for payment fraud prevention and telephony. For the vast majority of non-ads use cases, an FID or GUID should be sufficient.

So doc says :

  • to use FID or GUID except for payment fraud (which is my case)
  • to avoid using hardware identifiers such as IMEI or DEVICE_ID

So what're best practices for fraud ?

LaurentY
  • 7,495
  • 3
  • 37
  • 55
  • 1
    I like this [answer to piracy](https://stackoverflow.com/a/4711365/295004) which is in the same space as fraud. I'm assuming you've read further down your linked page: https://developer.android.com/training/articles/user-data-ids.html#abuse-detection so server side detection is a requirement. – Morrison Chang Feb 16 '23 at 01:04
  • Also, the user needs to create an account to access your app, right? If so and the requirement is like you stated "To avoid fraud we need to check that user only use one device at the same time." you can allow only one open session per registered user at the same time on the backend side and the problem is solved. – bmaciejm Feb 16 '23 at 11:30
  • There's already many controls done on API side, and check one user = one device is an additional control on device, we want – LaurentY Feb 16 '23 at 16:33

7 Answers7

1

What do you think about creating some random deviceId during the user's registration flow, for example using UUID.randomUUID.toString()? You store it then encrypted on a device in the app's private storage. During the registration, you are sending it to the backend to pair this ID alongside the user. After that when the app calls an API, it needs to decrypt the stored deviceId and add it to the request header to identify.

With that, you have a unique id which cannot be easily bypassed because:

  • it is generated randomly per device
  • during registration it's paired with the user(and backend should identify it as the only deviceId this user is allowed to use when communicating with API)
  • it's stored encrypted in the app's private memory(so fraudster to access it basically needs to have a root or exploit some zero-day on Android, question is whether you plan to apply any root detection measures in the app as this is the weak spot)
  • app only decrypts it when calling the API(then should remove the decrypted deviceId from the memory until next usage)
bmaciejm
  • 101
  • 7
  • Thanks for your answer, but if user remove remove and re-install app, id will changed, and I don't want. – LaurentY Feb 22 '23 at 14:46
  • True, it still fulfils your "only use one device at the same time" requirement but on the other hand how backend will know that the user removed the app(which it needs to know to unpin the current deviceId from the user's profile). But even if you will be able to generate something unique for the whole Android device(which will survive the app removal) you are basically bricking your user to this one device. How would you know on the backend side that the user removed the app from phone1 and now wants to use your app on ONLY phone2 or lost his phone? He will be unable to use your app ever. – bmaciejm Feb 22 '23 at 15:02
1

Check the MAC address of the phone. Globally they're unique, link them to their account and you can easily keep track of them if they're connecting to your own infra.

MitchHS
  • 323
  • 1
  • 8
  • android doc says : Avoid using hardware identifiers :( – LaurentY Feb 22 '23 at 14:47
  • Honestly I think combining that with IP address is the only way for limiting devices per account. Unless you store a uuid in the shared preferences file of the device (assuming you're using an APK) and use that in API requests too. – MitchHS Feb 24 '23 at 05:41
0

When user opens the application and logs in, you should send a request to the server containing user's ID, assign that user a session ID and store the mapping {userId: sessionId} in a key-value store for the period when user remains online.

Now whenever a user opens your application and logs in (or is already logged in), check if that user's Id already exists in key-value store, if it does, then don't allow that session, otherwise log that user in, when user leaves your application, remove that mapping from the key-value store.

theGateway
  • 91
  • 1
  • 5
0

Just ask the user for his national id, and add it as uid in dp

Djoxy
  • 54
  • 4
0

You can maintain a session for a user by using its user id if dont want to user device id, as soon as it is logged in from a device, server will log out it from devices (if any).

For this, you basically need an API which will be called in the onResume() of an application and it will check it app still has session or not. if session is expired user will be logged out and redirected to log in page.

Kartika Vij
  • 493
  • 2
  • 4
  • 18
0

You can create field in DB like uniqueDeviceID for all users, when user logged in with right credentials check if uniqueDeviceID exist or not.

If it exist, that means user is already loggend in somewhere, you need to call action for logout on that uniqueDeviceID, and assign new uniqueDeviceID for this login.

and if user click on logout all you need to do is remove uniqueDeviceID from user field in db. so next time he/she tries to login, ID won't exist and will keep cycle on an on.

Cypher or KJ
  • 51
  • 2
  • 16
  • Thanks for your answer, but if user remove remove and re-install app, id will changed, and I don't want. – LaurentY Feb 22 '23 at 14:47
0

From what I understand you want to block a user having multiple accounts active on the same device. I presume that you are stopping the same user logging in twice from the server side. So you are looking at a user creating two accounts on your system but using the same device.

To do this, you would need to create some sort of mutex on the device. File based mutex might not work, if the app crashes, the user would never be allowed to log in. One way which I keep coming back to is:

  • Start a tcp listener on a hardcoded port, if an exception is thrown then the port is already in use, so exit the app. If app crashes for another reason, the port is made available by the OS.
JoeH
  • 63
  • 5