From 5e79abc1bb8bccfd9e00ee778f0c3955e717f58a Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Mon, 17 Apr 2023 16:57:03 -0400 Subject: [PATCH 1/4] truncating generated GUID string, & displaying authentication exception --- .../Gameplay/GameState/ClientMainMenuState.cs | 8 ++------ .../Auth/AuthenticationServiceFacade.cs | 20 +++++++++++++++++++ Assets/Scripts/Utils/ProfileManager.cs | 3 ++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs b/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs index c1b2a691f..59e2957ae 100644 --- a/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs +++ b/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs @@ -66,12 +66,8 @@ private async void TrySignIn() { try { - var unityAuthenticationInitOptions = new InitializationOptions(); - var profile = m_ProfileManager.Profile; - if (profile.Length > 0) - { - unityAuthenticationInitOptions.SetProfile(profile); - } + var unityAuthenticationInitOptions = + m_AuthServiceFacade.GenerateAuthenticationOptions(m_ProfileManager.Profile); await m_AuthServiceFacade.InitializeAndSignInAsync(unityAuthenticationInitOptions); OnAuthSignIn(); diff --git a/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs b/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs index c8f8396aa..04d3aa9b2 100644 --- a/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs +++ b/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs @@ -12,6 +12,26 @@ public class AuthenticationServiceFacade { [Inject] IPublisher m_UnityServiceErrorMessagePublisher; + public InitializationOptions GenerateAuthenticationOptions(string profile) + { + try + { + var unityAuthenticationInitOptions = new InitializationOptions(); + if (profile.Length > 0) + { + unityAuthenticationInitOptions.SetProfile(profile); + } + + return unityAuthenticationInitOptions; + } + catch (Exception e) + { + var reason = $"{e.Message} ({e.InnerException?.Message})"; + m_UnityServiceErrorMessagePublisher.Publish(new UnityServiceErrorMessage("Authentication Error", reason, UnityServiceErrorMessage.Service.Authentication, e)); + throw; + } + } + public async Task InitializeAndSignInAsync(InitializationOptions initializationOptions) { try diff --git a/Assets/Scripts/Utils/ProfileManager.cs b/Assets/Scripts/Utils/ProfileManager.cs index aa7c75713..abf2048e3 100644 --- a/Assets/Scripts/Utils/ProfileManager.cs +++ b/Assets/Scripts/Utils/ProfileManager.cs @@ -80,7 +80,8 @@ static string GetProfile() var hashedBytes = new MD5CryptoServiceProvider() .ComputeHash(Encoding.UTF8.GetBytes(Application.dataPath)); Array.Resize(ref hashedBytes, 16); - return new Guid(hashedBytes).ToString("N"); + // Authentication service only allows profile names of maximum 30 characters + return new Guid(hashedBytes).ToString("N").Substring(2, 30); #else return ""; #endif From a63ad5b2a1b2d99306ba8ade4e3c9245386cd388 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Sun, 23 Apr 2023 19:04:11 -0400 Subject: [PATCH 2/4] feedback, and comments on authentication service name requirements --- Assets/Scripts/Gameplay/UI/UIProfileSelector.cs | 6 +++++- Assets/Scripts/Utils/ProfileManager.cs | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Assets/Scripts/Gameplay/UI/UIProfileSelector.cs b/Assets/Scripts/Gameplay/UI/UIProfileSelector.cs index c6300cb38..7699605df 100644 --- a/Assets/Scripts/Gameplay/UI/UIProfileSelector.cs +++ b/Assets/Scripts/Gameplay/UI/UIProfileSelector.cs @@ -26,6 +26,9 @@ public class UIProfileSelector : MonoBehaviour [Inject] IObjectResolver m_Resolver; [Inject] ProfileManager m_ProfileManager; + // Authentication service only accepts profile names of 30 characters or under + const int k_AuthenticationMaxProfileLength = 30; + void Awake() { m_ProfileListItemPrototype.gameObject.SetActive(false); @@ -44,7 +47,8 @@ public void SanitizeProfileNameInputText() string SanitizeProfileName(string dirtyString) { - return Regex.Replace(dirtyString, "[^a-zA-Z0-9]", ""); + var output = Regex.Replace(dirtyString, "[^a-zA-Z0-9]", ""); + return output[..Math.Min(output.Length, k_AuthenticationMaxProfileLength)]; } public void OnNewProfileButtonPressed() diff --git a/Assets/Scripts/Utils/ProfileManager.cs b/Assets/Scripts/Utils/ProfileManager.cs index abf2048e3..466e60a8c 100644 --- a/Assets/Scripts/Utils/ProfileManager.cs +++ b/Assets/Scripts/Utils/ProfileManager.cs @@ -80,8 +80,9 @@ static string GetProfile() var hashedBytes = new MD5CryptoServiceProvider() .ComputeHash(Encoding.UTF8.GetBytes(Application.dataPath)); Array.Resize(ref hashedBytes, 16); - // Authentication service only allows profile names of maximum 30 characters - return new Guid(hashedBytes).ToString("N").Substring(2, 30); + // Authentication service only allows profile names of maximum 30 characters. We're generating a GUID based + // on the project's path. Truncating the first 30 characters of said GUID string suffices for uniqueness. + return new Guid(hashedBytes).ToString("N")[..30]; #else return ""; #endif From b296c2908041c65d6a5d9016c4070dc51f3288dc Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 26 Apr 2023 13:27:39 -0400 Subject: [PATCH 3/4] formatting --- .../Gameplay/GameState/ClientMainMenuState.cs | 46 ++++++++++++------- .../Auth/AuthenticationServiceFacade.cs | 8 ++-- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs b/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs index 59e2957ae..53da328ae 100644 --- a/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs +++ b/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs @@ -22,20 +22,31 @@ namespace Unity.BossRoom.Gameplay.GameState /// public class ClientMainMenuState : GameStateBehaviour { - public override GameState ActiveState { get { return GameState.MainMenu; } } - - [SerializeField] NameGenerationData m_NameGenerationData; - [SerializeField] LobbyUIMediator m_LobbyUIMediator; - [SerializeField] IPUIMediator m_IPUIMediator; - [SerializeField] Button m_LobbyButton; - [SerializeField] GameObject m_SignInSpinner; - [SerializeField] UIProfileSelector m_UIProfileSelector; - [SerializeField] UITooltipDetector m_UGSSetupTooltipDetector; - - [Inject] AuthenticationServiceFacade m_AuthServiceFacade; - [Inject] LocalLobbyUser m_LocalUser; - [Inject] LocalLobby m_LocalLobby; - [Inject] ProfileManager m_ProfileManager; + public override GameState ActiveState => GameState.MainMenu; + + [SerializeField] + NameGenerationData m_NameGenerationData; + [SerializeField] + LobbyUIMediator m_LobbyUIMediator; + [SerializeField] + IPUIMediator m_IPUIMediator; + [SerializeField] + Button m_LobbyButton; + [SerializeField] + GameObject m_SignInSpinner; + [SerializeField] + UIProfileSelector m_UIProfileSelector; + [SerializeField] + UITooltipDetector m_UGSSetupTooltipDetector; + + [Inject] + AuthenticationServiceFacade m_AuthServiceFacade; + [Inject] + LocalLobbyUser m_LocalUser; + [Inject] + LocalLobby m_LocalLobby; + [Inject] + ProfileManager m_ProfileManager; protected override void Awake() { @@ -61,13 +72,12 @@ protected override void Configure(IContainerBuilder builder) builder.RegisterComponent(m_IPUIMediator); } - private async void TrySignIn() { try { - var unityAuthenticationInitOptions = - m_AuthServiceFacade.GenerateAuthenticationOptions(m_ProfileManager.Profile); + var unityAuthenticationInitOptions = + m_AuthServiceFacade.GenerateAuthenticationOptions(m_ProfileManager.Profile); await m_AuthServiceFacade.InitializeAndSignInAsync(unityAuthenticationInitOptions); OnAuthSignIn(); @@ -88,6 +98,7 @@ private void OnAuthSignIn() Debug.Log($"Signed in. Unity Player ID {AuthenticationService.Instance.PlayerId}"); m_LocalUser.ID = AuthenticationService.Instance.PlayerId; + // The local LobbyUser object will be hooked into UI before the LocalLobby is populated during lobby join, so the LocalLobby must know about it already when that happens. m_LocalLobby.AddUser(m_LocalUser); } @@ -99,6 +110,7 @@ private void OnSignInFailed() m_LobbyButton.interactable = false; m_UGSSetupTooltipDetector.enabled = true; } + if (m_SignInSpinner) { m_SignInSpinner.SetActive(false); diff --git a/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs b/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs index 04d3aa9b2..ef26eceeb 100644 --- a/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs +++ b/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs @@ -10,7 +10,8 @@ namespace Unity.BossRoom.UnityServices.Auth { public class AuthenticationServiceFacade { - [Inject] IPublisher m_UnityServiceErrorMessagePublisher; + [Inject] + IPublisher m_UnityServiceErrorMessagePublisher; public InitializationOptions GenerateAuthenticationOptions(string profile) { @@ -31,7 +32,7 @@ public InitializationOptions GenerateAuthenticationOptions(string profile) throw; } } - + public async Task InitializeAndSignInAsync(InitializationOptions initializationOptions) { try @@ -57,6 +58,7 @@ public async Task SwitchProfileAndReSignInAsync(string profile) { AuthenticationService.Instance.SignOut(); } + AuthenticationService.Instance.SwitchProfile(profile); try @@ -87,6 +89,7 @@ public async Task EnsurePlayerIsAuthorized() { var reason = $"{e.Message} ({e.InnerException?.Message})"; m_UnityServiceErrorMessagePublisher.Publish(new UnityServiceErrorMessage("Authentication Error", reason, UnityServiceErrorMessage.Service.Authentication, e)); + //not rethrowing for authentication exceptions - any failure to authenticate is considered "handled failure" return false; } @@ -98,6 +101,5 @@ public async Task EnsurePlayerIsAuthorized() throw; } } - } } From 2393563bf716a8b61d32155e45bc81264c22e9b2 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 26 Apr 2023 13:30:18 -0400 Subject: [PATCH 4/4] changelog addition --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c130a4b..78ae0a7de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Additional documentation and release notes are available at [Multiplayer Documen * Replaced our custom pool implementation using queues with ObjectPool (#824) * Upgraded Boss Room to NGO 1.3.1 (#828) NetworkPrefabs inside NetworkManager's NetworkPrefabs list have been converted to NetworkPrefabsList ScriptableObject. * Upgraded Boss Room to NGO 1.4.0 (#829) +* Profile names generated are now only 30 characters or under to fit Authentication Service requirements (#831) ### Cleanup * Clarified a TODO comment inside ClientCharacter, detailing how anticipation should only be executed on owning client players (#786)