From 4390d630cfa9c1c0865778d5f9f41646f0c1ddd5 Mon Sep 17 00:00:00 2001 From: Natalie Bunduwongse Date: Fri, 4 Apr 2025 11:52:57 +1300 Subject: [PATCH 1/3] feat: redact tokens from logs --- .../Passport/SelectAuthMethodScript.cs | 3 + .../Private/Core/Logging/PassportLogger.cs | 17 +++- .../Scripts/Private/PassportFunction.cs | 1 - .../Runtime/Scripts/Public/Passport.cs | 78 ++++++++++++++++++- .../Logging/DefaultUnityWebBrowserLogger.cs | 28 +++++-- .../Runtime/UwbWebView.cs | 7 +- 6 files changed, 121 insertions(+), 13 deletions(-) diff --git a/sample/Assets/Scripts/Passport/SelectAuthMethodScript.cs b/sample/Assets/Scripts/Passport/SelectAuthMethodScript.cs index d8517f66..9eec6809 100644 --- a/sample/Assets/Scripts/Passport/SelectAuthMethodScript.cs +++ b/sample/Assets/Scripts/Passport/SelectAuthMethodScript.cs @@ -90,6 +90,9 @@ private async void InitialisePassport(string? redirectUri = null, string? logout // Set the log level for the SDK Passport.LogLevel = LogLevel.Info; + // Don't redact token values from logs + Passport.RedactTokensInLogs = false; + // Initialise Passport string environment = Immutable.Passport.Model.Environment.SANDBOX; string clientId = "mp6rxfMDwwZDogcdgNrAaHnG0qMlXuMK"; diff --git a/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs b/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs index 905a8dce..99e80967 100644 --- a/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs +++ b/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using System; namespace Immutable.Passport.Core.Logging { @@ -7,13 +7,24 @@ public static class PassportLogger private const string TAG = "[Immutable]"; public static LogLevel CurrentLogLevel { get; set; } = LogLevel.Info; + + /// + /// A function that defines how sensitive data should be redacted. + /// If null, no redaction is applied. + /// + public static Func? RedactionHandler { get; set; } - public static void Log(LogLevel level, string message) + private static void Log(LogLevel level, string message) { if (level < CurrentLogLevel) { return; // Don't log messages below the current log level } + + if (RedactionHandler != null) + { + message = RedactionHandler(message); + } switch (level) { @@ -30,7 +41,7 @@ public static void Log(LogLevel level, string message) UnityEngine.Debug.LogError($"{TAG} {message}"); break; default: - break; + throw new ArgumentOutOfRangeException(nameof(level), level, null); } } diff --git a/src/Packages/Passport/Runtime/Scripts/Private/PassportFunction.cs b/src/Packages/Passport/Runtime/Scripts/Private/PassportFunction.cs index cf05ce50..76c5c967 100644 --- a/src/Packages/Passport/Runtime/Scripts/Private/PassportFunction.cs +++ b/src/Packages/Passport/Runtime/Scripts/Private/PassportFunction.cs @@ -6,7 +6,6 @@ public static class PassportFunction public const string INIT_DEVICE_FLOW = "initDeviceFlow"; public const string RELOGIN = "relogin"; public const string RECONNECT = "reconnect"; - public const string CONNECT = "connect"; public const string LOGIN_PKCE = "loginPKCE"; public const string CONNECT_PKCE = "connectPKCE"; public const string GET_PKCE_AUTH_URL = "getPKCEAuthUrl"; diff --git a/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs b/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs index c1d01def..c5318bd9 100644 --- a/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs +++ b/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System; +using System.Text.RegularExpressions; #if UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN) #if !IMMUTABLE_CUSTOM_BROWSER using VoltstroStudios.UnityWebBrowser; @@ -16,6 +17,7 @@ using Immutable.Passport.Core.Logging; using Cysharp.Threading.Tasks; using UnityEngine; +using VoltstroStudios.UnityWebBrowser.Logging; #if UNITY_EDITOR using UnityEditor; #endif @@ -48,13 +50,19 @@ public class Passport public event OnAuthEventDelegate OnAuthEvent; /// - /// The log level for the SDK. + /// Gets or sets the log level for the SDK. /// /// - /// The log level determines which messages are recorded based on their severity. The default value is . + /// The log level determines which messages are recorded based on their severity. + /// + /// The default value is . + /// /// /// See for valid log levels and their meanings. /// + /// + /// Passport.LogLevel = LogLevel.Debug; + /// /// public static LogLevel LogLevel { @@ -72,6 +80,35 @@ public static LogLevel LogLevel private static LogLevel _logLevel = LogLevel.Info; + /// + /// Determines whether sensitive token values should be redacted from SDK logs. + /// + /// + /// When set to true, access tokens and ID tokens will be replaced with [REDACTED] in log messages to enhance security. + /// This setting is useful for preventing sensitive data from appearing in logs, especially when debugging or sharing logs with others. + /// + /// The default value is false, meaning tokens will be logged in full at appropriate log levels. + /// + /// + /// Passport.RedactTokensInLogs = true; + /// + /// + public static bool RedactTokensInLogs + { + get => _redactTokensInLogs; + set + { + _redactTokensInLogs = value; + PassportLogger.RedactionHandler = value ? RedactTokenValues : null; + +#if !IMMUTABLE_CUSTOM_BROWSER && (UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN)) + SetWindowsRedactionHandler(); +#endif + } + } + + private static bool _redactTokensInLogs; + private Passport() { // Handle clean-up tasks when the application is quitting @@ -191,7 +228,7 @@ private async UniTask Initialise( " 'windowsWebBrowserClient' must not be null."); #else webBrowserClient = gameObject.AddComponent(); - await ((UwbWebView)webBrowserClient).Init(engineStartupTimeoutMs); + await ((UwbWebView)webBrowserClient).Init(engineStartupTimeoutMs, _redactTokensInLogs, RedactTokenValues); readySignalReceived = true; #endif } @@ -558,8 +595,43 @@ private static void SetDefaultWindowsBrowserLogLevel() }; } } + + private static void SetWindowsRedactionHandler() + { + if (Instance?.webBrowserClient is WebBrowserClient browserClient) + { + browserClient.Logger = new DefaultUnityWebBrowserLogger(redactionHandler: _redactTokensInLogs ? RedactTokenValues : null); + } + } #endif + /// + /// Redacts access and ID token data from a log message if found. + /// + private static string RedactTokenValues(string message) + { + try + { + var match = Regex.Match(message, @"({.*})"); + if (match.Success) + { + var jsonPart = match.Groups[1].Value; + var response = JsonUtility.FromJson(jsonPart); + if (response?.responseFor is PassportFunction.GET_ACCESS_TOKEN or PassportFunction.GET_ID_TOKEN && !string.IsNullOrEmpty(response.result)) + { + response.result = "[REDACTED]"; + return message.Replace(jsonPart, JsonUtility.ToJson(response)); + } + } + } + catch (Exception) + { + // ignored + } + + return message; + } + private PassportImpl GetPassportImpl() { if (passportImpl != null) diff --git a/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/Logging/DefaultUnityWebBrowserLogger.cs b/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/Logging/DefaultUnityWebBrowserLogger.cs index 77582774..43ca8aa2 100644 --- a/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/Logging/DefaultUnityWebBrowserLogger.cs +++ b/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/Logging/DefaultUnityWebBrowserLogger.cs @@ -5,6 +5,7 @@ // // This project is under the MIT license. See the LICENSE.md file for more details. +using System; using UnityEngine; namespace VoltstroStudios.UnityWebBrowser.Logging @@ -17,25 +18,42 @@ public sealed class DefaultUnityWebBrowserLogger : IWebBrowserLogger private const string LoggingTag = "[UWB]"; private readonly ILogger logger; - - public DefaultUnityWebBrowserLogger() + + /// + /// A function that defines how sensitive data should be redacted. + /// If null, no redaction is applied. + /// + public Func? redactionHandler; + + public DefaultUnityWebBrowserLogger(Func? redactionHandler = null) { logger = UnityEngine.Debug.unityLogger; + this.redactionHandler = redactionHandler; } public void Debug(object message) { - logger.Log(LogType.Log, LoggingTag, message); + logger.Log(LogType.Log, LoggingTag, redactIfRequired(message)); } public void Warn(object message) { - logger.LogWarning(LoggingTag, message); + logger.LogWarning(LoggingTag, redactIfRequired(message)); } public void Error(object message) { - logger.LogError(LoggingTag, message); + logger.LogError(LoggingTag, redactIfRequired(message)); + } + + private object redactIfRequired(object message) + { + if (redactionHandler != null && message is string) + { + return redactionHandler((string)message); + } + + return message; } } } diff --git a/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/UwbWebView.cs b/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/UwbWebView.cs index 80418220..fd9afc20 100644 --- a/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/UwbWebView.cs +++ b/src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/dev.voltstro.unitywebbrowser@2.2.5/Runtime/UwbWebView.cs @@ -1,5 +1,6 @@ #if !IMMUTABLE_CUSTOM_BROWSER && (UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN)) +using System; using System.IO; using System.Linq; using System.Net; @@ -15,6 +16,7 @@ using VoltstroStudios.UnityWebBrowser.Core.Engines; using VoltstroStudios.UnityWebBrowser.Core.Js; using VoltstroStudios.UnityWebBrowser.Helper; +using VoltstroStudios.UnityWebBrowser.Logging; using VoltstroStudios.UnityWebBrowser.Shared; using VoltstroStudios.UnityWebBrowser.Shared.Core; @@ -28,7 +30,7 @@ public class UwbWebView : MonoBehaviour, IWebBrowserClient private WebBrowserClient? webBrowserClient; - public async UniTask Init(int engineStartupTimeoutMs) + public async UniTask Init(int engineStartupTimeoutMs, bool redactTokensInLogs, Func redactionHandler) { GameObject persistentObject = new GameObject("UWB"); WebBrowserNoUi browser = persistentObject.AddComponent(); @@ -49,6 +51,9 @@ public async UniTask Init(int engineStartupTimeoutMs) _ => LogSeverity.Info }; + // Logger + webBrowserClient.Logger = new DefaultUnityWebBrowserLogger(redactionHandler: redactTokensInLogs ? redactionHandler : null); + // Js webBrowserClient.jsMethodManager = new JsMethodManager { jsMethodsEnable = true }; webBrowserClient.RegisterJsMethod("callback", From fad245de39c23604ae18bead613d4d5df98ed81f Mon Sep 17 00:00:00 2001 From: Natalie Bunduwongse Date: Fri, 4 Apr 2025 12:09:54 +1300 Subject: [PATCH 2/3] style: fix lint --- sample/Assets/Scripts/Other/LaunchBrowserScript.cs | 4 ++-- src/Packages/Passport/Editor/PassportPostprocess.cs | 4 ++-- .../Runtime/Scripts/Private/Core/Logging/PassportLogger.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sample/Assets/Scripts/Other/LaunchBrowserScript.cs b/sample/Assets/Scripts/Other/LaunchBrowserScript.cs index 970c58c1..975bd8a6 100644 --- a/sample/Assets/Scripts/Other/LaunchBrowserScript.cs +++ b/sample/Assets/Scripts/Other/LaunchBrowserScript.cs @@ -9,13 +9,13 @@ public class LaunchBrowserScript : MonoBehaviour { [SerializeField] private WebBrowserUIFull webBrowser; [SerializeField] private Button openDevToolsButton; - + private WebBrowserClient? webBrowserClient; public void Start() { webBrowser.browserClient.OnLoadFinish += OnLoadFinish; - + void OnLoadFinish(string url) { webBrowser.browserClient.OnLoadFinish -= OnLoadFinish; diff --git a/src/Packages/Passport/Editor/PassportPostprocess.cs b/src/Packages/Passport/Editor/PassportPostprocess.cs index 44df2365..cdea39f7 100644 --- a/src/Packages/Passport/Editor/PassportPostprocess.cs +++ b/src/Packages/Passport/Editor/PassportPostprocess.cs @@ -184,6 +184,6 @@ private void CopyFilesTo(string destinationPath) } } } -} - +} + #endif \ No newline at end of file diff --git a/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs b/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs index 99e80967..30e0e8f1 100644 --- a/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs +++ b/src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs @@ -7,7 +7,7 @@ public static class PassportLogger private const string TAG = "[Immutable]"; public static LogLevel CurrentLogLevel { get; set; } = LogLevel.Info; - + /// /// A function that defines how sensitive data should be redacted. /// If null, no redaction is applied. @@ -20,7 +20,7 @@ private static void Log(LogLevel level, string message) { return; // Don't log messages below the current log level } - + if (RedactionHandler != null) { message = RedactionHandler(message); From b37c42bf0e19df2880c6c49982cc685d827a4071 Mon Sep 17 00:00:00 2001 From: Natalie Bunduwongse Date: Fri, 4 Apr 2025 12:35:11 +1300 Subject: [PATCH 3/3] fix: uwb import --- src/Packages/Passport/Runtime/Scripts/Public/Passport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs b/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs index c5318bd9..7f937b51 100644 --- a/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs +++ b/src/Packages/Passport/Runtime/Scripts/Public/Passport.cs @@ -6,6 +6,7 @@ using VoltstroStudios.UnityWebBrowser; using VoltstroStudios.UnityWebBrowser.Core; using VoltstroStudios.UnityWebBrowser.Shared; +using VoltstroStudios.UnityWebBrowser.Logging; #endif #elif (UNITY_ANDROID && !UNITY_EDITOR_WIN) || (UNITY_IPHONE && !UNITY_EDITOR_WIN) || UNITY_STANDALONE_OSX || UNITY_WEBGL using Immutable.Browser.Gree; @@ -17,7 +18,6 @@ using Immutable.Passport.Core.Logging; using Cysharp.Threading.Tasks; using UnityEngine; -using VoltstroStudios.UnityWebBrowser.Logging; #if UNITY_EDITOR using UnityEditor; #endif