Code

Allow game makers to manage player accounts

Overview

This guide includes everything needed to use the AuthService in the "Beamable SDK for Unity".

Upon Beamable initialization, the current session is automatically granted a user token. Each time the game is started, the same user token is applied. This allows Beamable to consistently authorize the player and track the player's behavior across a range of Beamable features.

🚧

Gotchas

Here are hints to help explain some of the trickier concepts:

• The notion of "Signing in" to an account can be misleading, because the game always ensures there is a player token loaded, even it is an anonymous user with no credentials.

Players can update the active users's info or add third-party credentials to the access token, which can be used to retrieve the token at a later date, or on a separate device.

Update Active User Info

await _beamableAPI.AuthService.RegisterDBCredentials(email,  password);

API

📘

Learning Fundamentals

Game makers who are new to Unity and C# can review the fundamentals here.

• See Beamable: Asynchronous Programming for more info

Here are API highlights for beamableAPI.AuthService.

Method NameDetail
CreateUserCreate new active user
GetCurrentProjectGet the active project info
GetUserGet the active user info
LoginThirdPartyLogin the active user via AuthThirdParty integrations
RegisterDBCredentialsUpdate the email and password for the active user

Examples

Here are examples which cover common programming needs.

📘

Beamable SDK Examples

The following example code is available for download at GitHub.com/Beamable_SDK_Examples

This AuthServiceExample.cs demonstrates CreateUser(), RegisterDBCredentials(), and more.

using System.Collections.Generic;
using System.Threading.Tasks;
using Beamable.Api;
using Beamable.Common.Api;
using Beamable.Common.Api.Auth;
using UnityEngine;
using UnityEngine.Events;
using Random = UnityEngine.Random;

namespace Beamable.Examples.Services.AuthService
{
   /// <summary>
   /// Holds data for each mock user to toggle between for demo
   /// </summary>
   public class MockUser
   {
      public string Alias = "";
      public string Email = "";
      public string Password = "";

      public MockUser(string alias, string email, string password)
      {
         Alias = alias;
         Password = password;
         Email = email;
      }

      // Randomize for demo usage
      public static string GetMockEmail(string index)
      {
         return "blah@blah" + Random.Range(10000, 99999) + "_" + index + ".com";
      }
   }
   
   
   /// <summary>
   /// Holds data for use in the <see cref="AuthServiceExampleUI"/>.
   /// </summary>
   [System.Serializable]
   public class AuthServiceExampleData
   {
      public List<string> MainTexts = new List<string>();
      public List<string> DetailTexts = new List<string>();
      public bool IsBeamableSetup = false;
   }
   
   
   [System.Serializable]
   public class AuthServiceExampleExampleEvent : UnityEvent<AuthServiceExampleData> { }

   /// <summary>
   /// Demonstrates <see cref="AuthService"/>.
   ///
   /// NOTE: The notion of "Signing in" to an account can be misleading, because
   /// the game always ensures there is a player token loaded, even it is an anonymous
   /// user with no credentials.
   /// 
   /// </summary>
   public class AuthServiceExample : MonoBehaviour
   {
      //  Events  ---------------------------------------
      [HideInInspector]
      public AuthServiceExampleExampleEvent OnRefreshed = new AuthServiceExampleExampleEvent();
      
      
      //  Fields  ---------------------------------------
      private IBeamableAPI _beamableAPI;
      private AuthServiceExampleData _authServiceExampleData = new AuthServiceExampleData();
      private MockUser _mockUser01 = null;
      private MockUser _mockUser02 = null;
      private string _lastRegisteredEmail = "";

      
      //  Unity Methods  --------------------------------
      protected void Start()
      {
         Debug.Log($"Start()");

         // Create 2 new mock users for demo purposes
         string mockEmail01 = MockUser.GetMockEmail("01");
         string mockEmail02 = MockUser.GetMockEmail("02");
         _mockUser01 = new MockUser ("Alias01", mockEmail01, "myPasswordFoo");
         _mockUser02 = new MockUser ("Alias02", mockEmail02, "myPasswordBar");
      
         SetupBeamable();
      }

      
      protected void OnDestroy()
      {
         // Unsubscribe to events
         _beamableAPI.OnUserChanged += BeamableAPI_OnUserChanged;
         _beamableAPI.OnUserLoggingOut += BeamableAPI_OnUserLoggingOut;
      }

      
      //  Methods  --------------------------------------
      private async void SetupBeamable()
      { 
         _beamableAPI = await Beamable.API.Instance;
            
         Debug.Log($"beamableAPI.User.id = {_beamableAPI.User.id}");
         
         // Create 2 new users from mock users for demo purposes,
         // Then later from UI: switch and update the active user
         _authServiceExampleData.DetailTexts.Clear();
 
         await CreateUser(_mockUser01.Alias);
         await UpdateCurrentUser();
         
         await CreateUser(_mockUser02.Alias);
         await UpdateCurrentUser();
         
         _authServiceExampleData.IsBeamableSetup = _beamableAPI != null;
         
         // Subscribe to events
         _beamableAPI.OnUserChanged += BeamableAPI_OnUserChanged;
         _beamableAPI.OnUserLoggingOut += BeamableAPI_OnUserLoggingOut;
         
         Refresh();
      }
      
      
      private async Task<EmptyResponse> CreateUser(string alias)
      {
         var tokenResponse = await _beamableAPI.AuthService.CreateUser();
         await _beamableAPI.ApplyToken(tokenResponse); 
         
         await _beamableAPI.StatsService.SetStats("public", new Dictionary<string, string>()
         {
            { "alias", alias },
         });

         string detailText = $"CreateUser() Alias = {alias}";
         _authServiceExampleData.DetailTexts.Add(detailText);

         return new EmptyResponse();
      }

      
      public void Refresh()
      {
         //Debug.Log($"Refresh()");

         if (_authServiceExampleData.IsBeamableSetup)
         {
            _authServiceExampleData.MainTexts.Clear();
            string mainText = $"Active User.Id = {_beamableAPI.User.id}, User.Email = {_beamableAPI.User.email}";
            _authServiceExampleData.MainTexts.Add(mainText);
         }

         OnRefreshed?.Invoke(_authServiceExampleData);
      }

      
      /// <summary>
      /// Attach an email/password to active user
      /// </summary>
      public async Task<EmptyResponse> UpdateCurrentUser()
      {
         // Choose the OTHER mock user
         MockUser nextMockUser = _mockUser02;
         if (_lastRegisteredEmail != _mockUser01.Email)
         {
            nextMockUser = _mockUser01;
         }

         bool isSuccess = false;
         string error = "";
         try
         {
            // This method actually changes the active Beamable user
            var user = await _beamableAPI.AuthService.RegisterDBCredentials(nextMockUser.Email, 
               nextMockUser.Password);
            
            isSuccess = true;
         }
         catch (PlatformRequesterException e) 
         {
            // Errors if: The email has either already been taken by another account, or
            // The current account already has an email.
            error = e.Message;
         }
         
         // Update UI
         _authServiceExampleData.DetailTexts.Clear();
         string detailText = $"UpdateCurrentUser() User.id = {_beamableAPI.User.id}, nextMockUser.Email = {nextMockUser.Email}, isSuccess = {isSuccess}";
         Debug.Log(detailText);
         _authServiceExampleData.DetailTexts.Add(detailText);
         
         if (isSuccess)
         {
            _lastRegisteredEmail = nextMockUser.Email;
         }
         else
         {
            string warningText = $"\nThat email was already registered. That is ok.";
            _authServiceExampleData.DetailTexts.Add(warningText);
            //Debug.Log(warningText);
         }
         
         Refresh();

         return new EmptyResponse();
      }

      
      public async Task<EmptyResponse> SwitchCurrentUser()
      {
         // Choose the OTHER mock user
         MockUser nextMockUser = _mockUser02;
         if (_beamableAPI.User.email != _mockUser01.Email)
         {
            nextMockUser = _mockUser01;
         }
         
         Debug.Log($"SwitchCurrentUser() From User.id = {_beamableAPI.User.id}");

         bool isSuccess = false;
         string error = "";
         TokenResponse tokenResponse = null;
         try
         {
            bool mergeUserIdToAccount = false;
            tokenResponse = await _beamableAPI.AuthService.Login(nextMockUser.Email, 
               nextMockUser.Password, mergeUserIdToAccount);
            
            isSuccess = true;

         }
         catch (PlatformRequesterException e) 
         {
            // Errors if: No account with that email exists yet
            error = e.Message;
         }
         
         // Update UI
         _authServiceExampleData.DetailTexts.Clear();
         string detailText = $"SwitchCurrentUser() To User.Email = {nextMockUser.Email}, isSuccess = {isSuccess}";
         if (!isSuccess)
         {
            detailText += $", Error = {error}";
         }
         else
         {
            // This method actually changes the active Beamable user
            await _beamableAPI.ApplyToken(tokenResponse); 
         }
         
         Debug.Log(detailText);
         _authServiceExampleData.DetailTexts.Add(detailText);
         Refresh();

         return new EmptyResponse();
      }
      
      
      //  Event Handlers  -------------------------------
      private void BeamableAPI_OnUserLoggingOut(User user)
      {
         Debug.Log($"OnUserLoggingOut() User.id = {user.id}");
      }

      
      private void BeamableAPI_OnUserChanged(User user)
      {
         Debug.Log($"OnUserChanged() User.id = {user.id}");
      }
   }
}

Advanced

This section contains any advanced configuration options and workflows.

Auth Token Storage

The Beamable access tokens are stored for reuse within an active auth session.

  • Unity Play Mode (Runtime) - path/is/tbd/
  • Unity Edit Mode - path/is/also/tbd

User Events

User events are available for advanced usage.

Subscribe To Events

var beamableAPI = await Beamable.API.Instance;
beamableAPI.OnUserChanged += BeamableAPI_OnUserChanged;
beamableAPI.OnUserLoggingOut += BeamableAPI_OnUserLoggingOut;

See the AuthServiceExample.cs above for a full demonstration.