Sign In Register

How can we help you today?

Start a new topic
Answered

Preventing concurrent login II

I understand there are other forum entries handling the same topic, but they are all marked as answered without giving me a satisfying way on how to actually achieve this. 


Like multiple users stated here, it is necessary for many other people as well to prevent users from logging in with the same account (on same or different device) at the same time. Sure, we could adept our backend code to sync all connected devices, but for us that just means allot of more work, trouble, risk and time without having a real benefit for our game vision. 


Like other users stated, it would be best for us as well to just set a flag somewhere in the backend and - bang - multiple loggins are just forbidden globally.


Or can you please give us an idea on how to handle it on our own: In the AuthenticationRequest cloud code script, how can I load a player by name and password to check if he is already online to let the request fail?


Best Answer

Hi Fiete,


Apologies that no one has got back to you sooner about this. Spark.getPlayer().disconnect(true) in the AuthenticationResponse would be the correct way to handle this. As Roman mentions above, this will log the player out on all of the other devices and the latest one will be able to Authenticate and continue on in the game. You can't avoid having both instances of the players logged in at some stage, it has to happen if you want to disconnect the older sessions.


Roman if you don't want the latest player to authenticate you could place a check in scriptData if Spark.getPlayer().getScriptData(userLoggedIn) is 'true', you could set this in a successful AuthenticationResponse then check it each time after. If userLoggedIn = true you could throw an error to prevent authentication from continuing or prompt the user to disconnect all of the other instances of that player with Spark.getPlayer().disconnect(true). Hope this helps.


Thanks,

Liam


4 people have this question

Hi Liam,


thank you for your answer =D


Just for clarification:


Use case I - Latest user first (disconnect old player when new one authenticates)


  1. Call Spark.getPlayer().disconnect(true); in the AuthenticationResponse

  2. This will send a SessionTerminatedMessage to the currently logged-in player. This message should be handled by the client, i.e. showing a message, changing game states, terminating the game or whatsoever.


Use case II - Keep old user (prevent new logins while player is connected)


  1. Set a bool in the player's script data indicating that the player is currently connected when the player authenticates (AuthenticationResponse):

    Spark.getPlayer().setScriptData("IsLoggedIn", true);

  2. Set it to false or remove it when the player disconnects (GS_PLAYER_DISCONNECT aka "Player Disconnected" system event):

    Spark.getPlayer().removeScriptData("IsLoggedIn");

  3. Finally throw an error when a player logs in and is connected already:

    var IsLoggedIn = Spark.getPlayer().getScriptData("IsLoggedIn");
    if (IsLoggedIn !== null && IsLoggedIn) throw "ALREADY_LOGGED_IN";

For me that works fine, (@followers:) anybody else needs more information?



4 people like this

Hi Guys,


Just to keep you guys updated on this. It was mentioned to the dev team and added to our backlog as a feature request. I'm afraid we can't offer more of an update on it at the moment. If there is any change in the status of this feature I will update this thread.


Thanks,

Liam


1 person likes this

Hi Marcin,


I think an EndSessionRequest would satisfy your needs here (https://docs.gamesparks.com/api-documentation/request-api/analytics/endsessionrequest.html)


Kind regards,

 - Steve


1 person likes this

hi, i'm afraid we are still having problem with preventing concurrent login. we are doing the following:

Use case I - Latest user first (disconnect old player when new one authenticates)

Call Spark.getPlayer().disconnect(true); in the AuthenticationResponse

This will send a SessionTerminatedMessage to the currently logged-in player. This message should be handled by the client, i.e. showing a message, changing game states, terminating the game or whatsoever.

and it works if client A is logged in and the app is running while client B logs in. however, if client A is logged into the app, but the app is in the background (e.g. client A is answering a phone call), and then client B logs in, client A would not receive the SessionTerminatedMessage, and when client A returns to the app (after the phone call), we would still end up with two clients concurrently logged in. 


is there a way to ensure that client A is logged out even when the app is running in the background?


1 person likes this

bump.


Did anyone ever figure this out?


One idea I have is to completely stop relying on GAmeSparks auth tokens, and keep the username/password encrypted on the disk on the device.

From there, the disconnect/resetauthtokens() method of booting the user should work.


Only problem I'm not sure about is how to also do the same for Facebook/Google/etc authentication...


Surely someone must have solved this by now? Does Customer Support have any answers for us?


players still get stuck in sessions even when trying the following:

this is in AuthenticationRequest:
if (Spark.getPlayer() !== null)
{
  var IsLoggedIn = Spark.getPlayer().getScriptData("IsLoggedIn");
  if (IsLoggedIn !== null && IsLoggedIn)
  {
  throw "ALREADY_LOGGED_IN";
  }
}

 this is in EndSessionResponse & GS_PLAYER_DISCONNECT:

if (Spark.getPlayer() !== null)
  Spark.getPlayer().removeScriptData("IsLoggedIn");


this is in AuthenticationResponse:

if (Spark.getPlayer() !== null)
{
  Spark.getPlayer().setScriptData("IsLoggedIn", true);
  //Spark.getPlayer().disconnect(true);
}


players still get stuck and cannot login...also how would you send the throw message error into unity to pop up a "already in use" message box?

We assign the user an ID when they login, which is then passed to any sensitive cloud code functions. The ID is then checked to make sure it matches the latest one generated, and if it does not, the cloud code returns with an invalid login, and the game displays a message to the user that they have logged in elsewhere. This was the technique we used on our old database before we migrated to GameSparks.

hi roman, i'm afraid the issue still persists. we have yet to find a solution that blocks concurrent login yet does not break the reconnect function.

Hi, 


I implemented this technique, and it works quite well.

Spark.getPlayer().disconnect(true); in the AuthenticationResponse

 


But very often I have this fatal error on this line :

{"stackTrace":"\tat 296608-response-AuthenticationResponse:5\n","error":"TypeError: Cannot call method \"disconnect\" of null (296608-response-AuthenticationResponse#5)","script":"AuthenticationResponse"}


How can the Spark.getPlayer() be null in the AuthenticationResponse ?

How can I fix that ?

 

Thanks

Eric

Hi Eric,


The only way you'd get null in the AuthenticationResponse would be if there was an error Authenticating, examples of this would include using an invalid token for a social auth or a bad userName/password combination. You do have quite a few failed FacebookConnectReqeusts in your game which look like the cause of the issue you are having.


Thanks,

Liam

This probably happens when there is no user logged at the time, so the usual case.

We are using this code with a simple null check:
if (Spark.getPlayer() !== null)
    Spark.getPlayer().disconnect(true);

 

 

Hi Oisin,

thank you for your fast answer. I understand I can use Spark.getPlayer().disconnect(true) to disconnect a loaded player. This will probably send a SessionTerminatedMessage to client, which will handle stuff there.

But my question originally aimed on the concept of how to identify (then load and disconnect) a player which is connected already:

If I do the isOnline check in AuthenticationRequest, the player is not loaded yet in this scope, doing it in the AuthenticationResponse seems to be to late already since the player might be connected twice already then.

Would you always send a SessionTerminatedMessage in the AuthenticationRequest, without checking if it is even necessary?

Feels like I still miss the point of matter..

 

Any solutions on this? I´ve found a similar problem managing Push notification, but using the same device with different users:


* Login user A in device D. (PushRegistration call)

* Logout user A.

* Login user B in device D. (PushRegistration call)


* Sending a Message ONLY to playerID A is showed as a push notification in device D (where supposed to be only logged the user B)


Any suggestion???

Bump. I'm weighing in -- we have spent way too much time on this one issue already. Like fiete said -- it's a big problem for many developers, and it desperately needs a solution.

This is an important topic for us too, I would also need a solution or at least a code example based on SessionTerminatedMessage.

Thanks

Login to post a comment