question

brendan avatar image
brendan asked

How to prevent duplicate login?

Vaion07281
started a topic on Fri, 03 July 2015 at 2:31 AM

Hi!

I use Photon Cloud and Playfab to my game

when PlayFabClientAPI.LoginWithPlayFab is success, will connect to photon cloud

then I try repeat login , it still success!!

how can i do?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

Updating to replace the missing logic description:

Basically, it's possible to add a Cloud Script-based "is the player already logged in" check for until we support blocking second-screen sign-ins. You'd still need to account for dropped connections, so the way this would work is like so:

  • On login, read User Internal Data to look for a session ticket (see below) - you could write this to a "currentTicket" key, for example
  • If there is one, and the timestamp for the data shows that it's two minutes old or less, delete the local session ticket - the player isn't allowed to sign in
  • If not, write the local session ticket to User Internal Data
  • Every 2 minutes or so, if the session ticket hasn't expired, re-write it to that same key
  • If the session ticket expires, log back in to get a new ticket and write it to the key
12 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

nickpruehs avatar image nickpruehs commented ·

Hey @Brendan! It seems like a session is now issued on login by Playfab itself. Are there any news on using this for preventing users from signing in multiple times? Am I missing a configuration option or API parameter? Thanks! Nick

1 Like 1 ·
brendan avatar image brendan nickpruehs commented ·

Can you clarify what you're referring to? Nothing has changed in the login API calls or Session Ticket as of yet. We are looking into when we want to schedule this work, currently.

0 Likes 0 ·
Andy avatar image Andy ♦♦ brendan commented ·

I believe Nick is referring to the new Session tracking telemetry that powers our screen time analytics (please correct me if I'm mistaken). That work isn't related to restrictions on multiple logins. Those restrictions are, as Brendan mentioned, something we're trying to get scheduled.

0 Likes 0 ·
Show more comments
A A avatar image A A commented ·

Hello @Brendan, I know this is an old thread but I still have questions. Is there any documentation about this. I mean I don't really know how to read User Internal Data to look for a session ticket. I am not sure about this whole thing. Is there a documentation or even a tutorial about that. I couldn't find anything.

PS: If it helps, I am using the Unity SDK, so I work with Unity.

Thank you already in advance.

1 Like 1 ·
brendan avatar image brendan A A commented ·

Yes, you can find documentation on our data systems here: https://docs.microsoft.com/en-us/gaming/playfab/features/data/playerdata/quickstart. And for the Cloud Script service, there are docs and tutorials here: https://docs.microsoft.com/en-us/gaming/playfab/features/automation/cloudscript/

0 Likes 0 ·
Rez avatar image Rez brendan commented ·

Hello everyone, I too am looking for the right way to obtain thesession ticket.

Can we just use the session ticket returned by the LoginResult on a successful login, or do we have to use PlayFabServerAPI to get the session ticket?

0 Likes 0 ·
Show more comments
Gunther avatar image Gunther commented ·

Hello @Brendan. This post is quite old and I'm curious if the mentioned "until we support blocking second-screen sign-ins" feature is something that's now supported out-of-the-box or if the process outlined here is still the best solution for preventing duplicate logins?

0 Likes 0 ·
Mohamed Younes avatar image Mohamed Younes commented ·

This solution would work theoretically, for real though it's not realistic. unless you don't mind getting a huge PlayFab bill, oh wait you work for them. never mind bye :))

0 Likes 0 ·
RGV avatar image RGV Mohamed Younes commented ·

Yup! The solution is not feasible as from new billing plan, which started back in November 2020. A write operation tick each 2 minutes per player, as proposed, would fill your limit in the blink of an eye.

0 Likes 0 ·
brendan avatar image
brendan answered

Best Answer
Brendan Vanous said on Sun, 05 July 2015 at 9:36 PM

Our system is designed to allow players to be signed in from multiple different devices, for companion application experiences (a console game with a paired application running on phone or tablet, for instance). So yes, we do not prevent the player from signing in if she recently signed in, as that would prevent a number of valid scenarios. As Hamza recommended, the thing to do in this case would be to check in the title code. If you need this to be a secure sever-side operation, you can use Cloud Script to drive the logic for this.


8 Comments
Brendan Vanous said on Fri, 03 July 2015 at 4:32 AM

Could you clarify the issue you're seeing? If a user provides valid sign-in credentials, he will be given a session ticket. This is true even if the user just signed in, since a player's device could have just reset, and the player legitimately needs to sign in again.

Brendan


Vaion07281 said on Sun, 05 July 2015 at 7:55 PM

In simple terms, my question is to repeat the login is allowed
But I do not want that


johntube said on Sun, 05 July 2015 at 8:21 PM

@Vaion07281 :

Why don't you "disallow it" from client code ?


Vaion07281 said on Sun, 05 July 2015 at 8:45 PM

So,Playfab can't prevent the same account repeat the login,I need judge in my code


Brendan Vanous said on Sun, 05 July 2015 at 9:36 PM

Our system is designed to allow players to be signed in from multiple different devices, for companion application experiences (a console game with a paired application running on phone or tablet, for instance). So yes, we do not prevent the player from signing in if she recently signed in, as that would prevent a number of valid scenarios. As Hamza recommended, the thing to do in this case would be to check in the title code. If you need this to be a secure sever-side operation, you can use Cloud Script to drive the logic for this.


Vaion07281 said on Sun, 05 July 2015 at 9:43 PM

OK!I get it,thank for your answer


Carlo.rodriguez08 said on Fri, 04 September 2015 at 1:40 AM

Hey Brendan, is there a way to prevent duplicate logins for those with Standard Tier, since Cloud Scripts aren't available for that tier? I know that this isn't necessarily the place to ask for it, but would it be hard to add a flag that determines whether a player is logged in/online and allow the developer the ability to be able to allow simultaneous logins or not?


Brendan Vanous said on Fri, 04 September 2015 at 1:42 AM

Hi Carlo,

If you need this to be server-authoritative, you'd really need to use Cloud Script right now. Are you principally concerned about the player being signed in on multiple devices? What are the risks you're attempting to mitigate?

Brendan

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

dev-3 avatar image
dev-3 answered

Hi @Brendan,

Could you please share an example of the Cloud Script which will block second-screen sign ins?

Alex

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image brendan commented ·

The basic Cloud Script which is added to all titles as revision 1 (and which is available in our GitHub repo, here) contains examples of reading and writing User Internal Data. Depending on how you want to enforce this and what other data uses, the rest of the solution is going to vary from title to title. For example, if your game is an asynchronous turn-based multiplayer game, you might do a check of this data, comparing it to what the client sends up in a call to ExecuteCloudScript which returns the information on the latest moves the player has available. Because the implementation details are going to be title-specific, we don't really have a way to provide a single script that would show this, but all you really know to know is how to read/write the data, and compare timestamps, both of which are shown in the processPlayerMove handler in that basic Cloud Script example.

0 Likes 0 ·
Falcon Land avatar image
Falcon Land answered

Just want to let everyone know the problem with this solution. If player suspends the application ( by soft closing it on mobile, locking the phone or many other ways on android emulators) the ticket will stop being updated. Then the player can load up the game and login on different device. Next he will wake up the game on the old device and now he has 2 devices logged to the same account and he can start exploiting whatever he wants. We actually put a lot of effort to figure out these issues caused by multi-logging users. They try to exploit the game by doing this all the time. The best bulletproof solution for us at the moment is just to store the logged device ID in the playfab and does not allow to login any other device. If the player want to login on other device he MUST first click so on "log out" button in the game which will free up the device id entry in Playfab and closes the game. The disadvantage of this solution is that if player somehow lose access to his device he is not able to logout. This must be then solved individually by our support.

3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

garrygaber avatar image garrygaber commented ·

Have you found a better way to do this since this post? I am concerned about the case where a player doesn't exit the game properly (i.e. a suspend or exit) and so never gets logged out of the game as far as Playfab is concerned.

0 Likes 0 ·
Rez avatar image Rez garrygaber commented ·

And ... like garrygaber mentioned, this solution has the potentially to gamebreakingly lock out users unless devices are automatically logged out after a time period.

0 Likes 0 ·
Rez avatar image Rez commented ·

Thank you for sharing your solution, your solution suggests that it's impossible for the server to call a logout function through a specific device id.

Therefore making it so that the workarounds require each user to check it's read-only data sent from a duplicate user on another device on login, where, in this case you made it so that the user checks if there's a current logged in device through a device id and then preventing a login.

0 Likes 0 ·
dev-3 avatar image
dev-3 answered

Hi @Brendan,

Is there any way (via CloudScript) to get the list of all current sessions with their tickets for a given PlayFab Account ID?

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image brendan commented ·

The current system is not a true "session" model - we'll be adding that in a future update. Right now, Session Tickets are a signed piece of info which includes an expiration. We do not track on active tickets for all users, as there's no need in that model. Users must have an unexpired ticket, and a non-banned account to access the Client API calls that the title has enabled.

0 Likes 0 ·
dev-3 avatar image
dev-3 answered

Hi @Brendan,

Is it possible to login Client via CloudScript call with a native Login call inside?

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image brendan commented ·

No, calling ExecuteCloudScript requires a Session Ticket (a signed-in user). What is the problem you're trying to solve? Starting from a top-down design methodology is usually best, as it lets us examine the problem itself to determine what the right technological approach is.

0 Likes 0 ·
garrygaber avatar image
garrygaber answered

I think @Falcon Land 's solution makes a lot of sense. Instead of a logout button, would it just be better to give a dialog to the player that says "Logged in on other device" and automatically log them out when they confirm or close?

3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Rez avatar image Rez commented ·

Bump, Is there a documentation link where serverapi functions can call functions through a specific device id?

Because correct me if i'm wrong, isn't the only way to force a log out on another device with the same playfabID is to specifically call the logout function on that device?

1 Like 1 ·
Noam Sapir avatar image Noam Sapir Rez commented ·

+1 Same, is there documentation or a way to do that

1 Like 1 ·
brendan avatar image brendan Noam Sapir commented ·

Please see the solution described in the answer above. The authority on whether or not the client has a valid session ticket it can use is the client itself. There is no server-authoritative way to invalidate the session ticket, currently.

0 Likes 0 ·
Christian avatar image
Christian answered

Hi there,

We are very interested on this feature being implemented in a server-authoritative way so since we tried to look for one without luck we created a feature request here. I'm encouraging everyone here to vote!

Best,

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Arbuzov P avatar image
Arbuzov P answered

@Brendan i use cloud script, log in - set statistic 1 , log out - 0 , but how i can check this statistic when used PlayFabClientAPI.LoginWithEmailAddress

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

wwwnewbninja avatar image
wwwnewbninja answered

You could use something like this:

     using PlayFab;
     using PlayFab.ClientModels;
     using UnityEngine;
        
     public class LoginManager : MonoBehaviour
     {
         private bool isLoggingIn = false;
        
         private string email;
         private string password;
        
         private void Start()
         {
             // Initialize PlayFab SDK
             PlayFabSettings.TitleId = "YOUR_TITLE_ID_HERE";
         }
        
         public void Login()
         {
             if (isLoggingIn)
             {
                 return;
             }
        
             isLoggingIn = true;
        
             var request = new LoginWithEmailAddressRequest
             {
                 Email = email,
                 Password = password
             };
        
             PlayFabClientAPI.LoginWithEmailAddress(request, OnLoginSuccess, OnLoginFailure);
         }
        
         private void OnLoginSuccess(LoginResult result)
         {
             isLoggingIn = false;
        
             Debug.Log("Login successful");
        
             if (result.SettingsForUser.NeedsAttribution)
             {
                 Debug.Log("Attribution needed");
             }
        
             if (result.InfoResultPayload != null)
             {
                 Debug.Log("User Info: " + result.InfoResultPayload.PlayFabId);
             }
        
             if (result.EntityToken != null)
             {
                 Debug.Log("Entity Token: " + result.EntityToken.EntityToken);
             }
        
            // Check if the player is already logged in from another device
             if (result.SettingsForUser != null && result.SettingsForUser.UserAccountInfo != null)
             {
                 var lastLoginTime = result.SettingsForUser.UserAccountInfo.LastLoginTime;
                 var currentTime = DateTime.UtcNow;
                 var timeDifference = currentTime - lastLoginTime;
    
                 if (timeDifference.TotalSeconds < 10 && SystemInfo.deviceUniqueIdentifier != result.SettingsForUser.UserAccountInfo.TitleInfo.TitlePlayerAccount)
                 {
                     // Ask the user if they want to disconnect the other device and login again
                     Debug.Log("You are currently logged in from another device.");
                     Debug.Log("Last login time: " + lastLoginTime);
    
                     // Prompt the user to disconnect the other device and login again
                     ShowDisconnectDevicePrompt();
                 }
             }
         }
        
         private void OnLoginFailure(PlayFabError error)
         {
             isLoggingIn = false;
        
             Debug.LogError("Login failed: " + error.ErrorMessage);
         }
        
         private void ShowDisconnectDevicePrompt()
         {
             // Implement UI to prompt the user to disconnect the other device and login again
             // You can use PlayFabClientAPI.ForgetAllCredentials() to log out the current session
             // Once the user disconnects the other device, call Login() again to attempt login
         }
     }

Hope this helps ;)

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

zaferokeanix avatar image zaferokeanix commented ·

There is no such methods as "result.SettingsForUser.CurrentDevices.Count"

0 Likes 0 ·
wwwnewbninja avatar image wwwnewbninja zaferokeanix commented ·

You're correct, sorry about that, you could use this instead to check the last login time for the user.

 // Check if the player is already logged in from another device
 if (result.SettingsForUser != null && result.SettingsForUser.UserAccountInfo != null)
 {
     var lastLoginTime = result.SettingsForUser.UserAccountInfo.LastLoginTime;
     var currentTime = DateTime.UtcNow;
     var timeDifference = currentTime - lastLoginTime;
    
     if (timeDifference.TotalSeconds < 10 && SystemInfo.deviceUniqueIdentifier != result.SettingsForUser.UserAccountInfo.TitleInfo.TitlePlayerAccount)
     {
         // Ask the user if they want to disconnect the other device and login again
         Debug.Log("You are currently logged in from another device.");
         Debug.Log("Last login time: " + lastLoginTime);
    
         // Prompt the user to disconnect the other device and login again
         ShowDisconnectDevicePrompt();
     }
 }
0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.