beamable / BeamableProduct

The beamable product suite including com.beamable, com.beamable.server, microservice base image, portal, the installer, and build scripts
Other
5 stars 0 forks source link

Way to suppress or prevent frictionless anonymous account creation #3541

Open allister-beamable opened 3 months ago

allister-beamable commented 3 months ago

Describe your Feature Request

As a Game Maker with strict player identity requirements, In order to only make player accounts when they have credentials, I want to avoid creating anonymous frictionless accounts.

Although normally the Beamable SDK's automatic guest account creation is beneficial for typical mobile apps, there are other styles of app where, as a game developer, I would prefer to only allow players to engage with the app when they are authenticated with credentials (such as username and password, or 3rd party platform credentials). As such, it would be nice to avoid the unnecessary creation of anonymous accounts. These anonymous accounts can be problematic from an analytics standpoint, as they artificially inflate DAU and MAU numbers.

Describe the Desired Solution

I would like to have full control over when and how accounts get created:

  1. I want to prevent anonymous accounts from being created at initialization time.
  2. I want to only initiate new-account creation when I know the player is prepared to enter credentials (practically speaking, when they have already entered credentials and the app is holding those creds temporarily in memory)
  3. When an existing player logs in on a new device, I want the first account on that device to be the one that they log into with credentials.

Initialization without an actual player could prove problematic, if there are parts of the SDK that assume that there is a valid player. Because of that, it might be sensible to assert that, when operating in a credentials-required situation, Beamable SDK initialization must be deferred or held in abeyance until the app is ready for a real player account. In order to support "no anonymous" modes of operation, I would like to have the option to pre-load Beamable SDK initialization with credentials.

  1. In the case of a new account, I would like to be able to start up the SDK in "account creation mode"... it is okay for this mode to create the usual anonymous frictionless account behind the scenes, but it must immediately register credentials to that account.
  2. In the case of a returning player, I would like to be able to start up the SDK in "login mode"... in this case, handling failed logins is important; as a developer I need to have a way to detect the failure and offer the player a chance to try again.

(alternatively, if it IS okay for the SDK to exist in an initialized-but-not-associated-with-any-player state, that could be useful for various code interactions such as checking for email availability, explicitly creating an initial account, registering credentials, etc. -- doing it this way would make the failed login case easier to handle, since it would simply be "inside" the existing SDK runtime, and trying again would be as simple as calling Login or RecoverWithEmail again)

Describe Alternatives You Have Considered

At present, the app with the "must have credentials" requirement is solving this by preventing the player from progressing to the game itself if they have not got email credentials, AND clearing any existing access tokens from PlayerPrefs every single time the game runs. This is the desired outcome for the Game Makers creating this game: players must sign in with email and password every single time they play, and no "remembered account" data is to be stored on device ever.

Clearing PlayerPrefs every time is effective at enforcing the "must have credentials" portion of things, but it leads to many throw-away anonymous accounts, as each time any returning player starts the app, they get a new account that is immediately discarded the moment they log in with their email and password.

cdhanna commented 3 months ago
BeamContext.Default // initialize the blank player

BeamContext.ForPlayer("slot") // initialize a player in a specific _slot_

BeamContext.ForToken(accessToken, "slot")

Task<BeamContext> ctx = BeamContext.ForEmailAndPassword(email, password, "slot") // this should fail if there is no existing account
Task<BeamContext> ctx = BeamContext.CreateAccount(email, password, "slot") // this should fail if there is an existing account

Task<(BeamContext, status)> ctx = BeamContext.ForEmailAndPasswordAuto(email, password, "slot") // try ForEmailAndPassword- fail then go to CreateAccount

ctx.Item1 // 

// status could be, "error", or "created-account", or "signed-into-existing"

Open question on the return type of ForEmailAndPasswordAuto, because the tuple feels bad from a ux-standpoint, but good from a type-standpoint

cdhanna commented 3 months ago

This is the starter-code to get going. The general gist is "fake it 'till you make it".

        public static async Promise<BeamContext> CreateAccount(string email, string password, string playerCode)
        {
            var env = BeamableEnvironment.Data;

            var requester = new PlatformRequester(
                host: env.ApiUrl, beamableVersion: env.SdkVersion, new AccessTokenStorage("nowhere?"), null, null);
            var authApi = new AuthApi(requester);
            var token = await authApi.CreateUser();
            // TODO: apply the token the requester via the tokenStorage

            var accountApi = new AccountsApi(requester);
            var res = await accountApi.PostRegister(new AccountRegistration {email = email, password = password});

            // TODO: create a beam context with the token.
        }