Skip to content

Commit d7d52b9

Browse files
authored
Merge pull request #451 from immutable/feat/redact-tokens-logs
[DX-3655] feat: redact tokens from logs
2 parents e20bd30 + b37c42b commit d7d52b9

File tree

8 files changed

+125
-17
lines changed

8 files changed

+125
-17
lines changed

sample/Assets/Scripts/Other/LaunchBrowserScript.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ public class LaunchBrowserScript : MonoBehaviour
99
{
1010
[SerializeField] private WebBrowserUIFull webBrowser;
1111
[SerializeField] private Button openDevToolsButton;
12-
12+
1313
private WebBrowserClient? webBrowserClient;
1414

1515
public void Start()
1616
{
1717
webBrowser.browserClient.OnLoadFinish += OnLoadFinish;
18-
18+
1919
void OnLoadFinish(string url)
2020
{
2121
webBrowser.browserClient.OnLoadFinish -= OnLoadFinish;

sample/Assets/Scripts/Passport/SelectAuthMethodScript.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ private async void InitialisePassport(string? redirectUri = null, string? logout
9090
// Set the log level for the SDK
9191
Passport.LogLevel = LogLevel.Info;
9292

93+
// Don't redact token values from logs
94+
Passport.RedactTokensInLogs = false;
95+
9396
// Initialise Passport
9497
string environment = Immutable.Passport.Model.Environment.SANDBOX;
9598
string clientId = "mp6rxfMDwwZDogcdgNrAaHnG0qMlXuMK";

src/Packages/Passport/Editor/PassportPostprocess.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,6 @@ private void CopyFilesTo(string destinationPath)
184184
}
185185
}
186186
}
187-
}
188-
187+
}
188+
189189
#endif

src/Packages/Passport/Runtime/Scripts/Private/Core/Logging/PassportLogger.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using UnityEngine;
1+
using System;
22

33
namespace Immutable.Passport.Core.Logging
44
{
@@ -8,13 +8,24 @@ public static class PassportLogger
88

99
public static LogLevel CurrentLogLevel { get; set; } = LogLevel.Info;
1010

11-
public static void Log(LogLevel level, string message)
11+
/// <summary>
12+
/// A function that defines how sensitive data should be redacted.
13+
/// If null, no redaction is applied.
14+
/// </summary>
15+
public static Func<string, string>? RedactionHandler { get; set; }
16+
17+
private static void Log(LogLevel level, string message)
1218
{
1319
if (level < CurrentLogLevel)
1420
{
1521
return; // Don't log messages below the current log level
1622
}
1723

24+
if (RedactionHandler != null)
25+
{
26+
message = RedactionHandler(message);
27+
}
28+
1829
switch (level)
1930
{
2031
case LogLevel.Debug:
@@ -30,7 +41,7 @@ public static void Log(LogLevel level, string message)
3041
UnityEngine.Debug.LogError($"{TAG} {message}");
3142
break;
3243
default:
33-
break;
44+
throw new ArgumentOutOfRangeException(nameof(level), level, null);
3445
}
3546
}
3647

src/Packages/Passport/Runtime/Scripts/Private/PassportFunction.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ public static class PassportFunction
66
public const string INIT_DEVICE_FLOW = "initDeviceFlow";
77
public const string RELOGIN = "relogin";
88
public const string RECONNECT = "reconnect";
9-
public const string CONNECT = "connect";
109
public const string LOGIN_PKCE = "loginPKCE";
1110
public const string CONNECT_PKCE = "connectPKCE";
1211
public const string GET_PKCE_AUTH_URL = "getPKCEAuthUrl";

src/Packages/Passport/Runtime/Scripts/Public/Passport.cs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System.Collections.Generic;
22
using System;
3+
using System.Text.RegularExpressions;
34
#if UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN)
45
#if !IMMUTABLE_CUSTOM_BROWSER
56
using VoltstroStudios.UnityWebBrowser;
67
using VoltstroStudios.UnityWebBrowser.Core;
78
using VoltstroStudios.UnityWebBrowser.Shared;
9+
using VoltstroStudios.UnityWebBrowser.Logging;
810
#endif
911
#elif (UNITY_ANDROID && !UNITY_EDITOR_WIN) || (UNITY_IPHONE && !UNITY_EDITOR_WIN) || UNITY_STANDALONE_OSX || UNITY_WEBGL
1012
using Immutable.Browser.Gree;
@@ -48,13 +50,19 @@ public class Passport
4850
public event OnAuthEventDelegate OnAuthEvent;
4951

5052
/// <summary>
51-
/// The log level for the SDK.
53+
/// Gets or sets the log level for the SDK.
5254
/// </summary>
5355
/// <remarks>
54-
/// The log level determines which messages are recorded based on their severity. The default value is <see cref="LogLevel.Info"/>.
56+
/// The log level determines which messages are recorded based on their severity.
57+
/// <para>
58+
/// The default value is <see cref="LogLevel.Info"/>.
59+
/// </para>
5560
/// <para>
5661
/// See <see cref="Immutable.Passport.Core.Logging.LogLevel"/> for valid log levels and their meanings.
5762
/// </para>
63+
/// <example>
64+
/// <code>Passport.LogLevel = LogLevel.Debug;</code>
65+
/// </example>
5866
/// </remarks>
5967
public static LogLevel LogLevel
6068
{
@@ -72,6 +80,35 @@ public static LogLevel LogLevel
7280

7381
private static LogLevel _logLevel = LogLevel.Info;
7482

83+
/// <summary>
84+
/// Determines whether sensitive token values should be redacted from SDK logs.
85+
/// </summary>
86+
/// <remarks>
87+
/// When set to <c>true</c>, access tokens and ID tokens will be replaced with <code>[REDACTED]</code> in log messages to enhance security.
88+
/// This setting is useful for preventing sensitive data from appearing in logs, especially when debugging or sharing logs with others.
89+
/// <para>
90+
/// The default value is <c>false</c>, meaning tokens will be logged in full at appropriate log levels.
91+
/// </para>
92+
/// <example>
93+
/// <code>Passport.RedactTokensInLogs = true;</code>
94+
/// </example>
95+
/// </remarks>
96+
public static bool RedactTokensInLogs
97+
{
98+
get => _redactTokensInLogs;
99+
set
100+
{
101+
_redactTokensInLogs = value;
102+
PassportLogger.RedactionHandler = value ? RedactTokenValues : null;
103+
104+
#if !IMMUTABLE_CUSTOM_BROWSER && (UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN))
105+
SetWindowsRedactionHandler();
106+
#endif
107+
}
108+
}
109+
110+
private static bool _redactTokensInLogs;
111+
75112
private Passport()
76113
{
77114
// Handle clean-up tasks when the application is quitting
@@ -191,7 +228,7 @@ private async UniTask Initialise(
191228
" 'windowsWebBrowserClient' must not be null.");
192229
#else
193230
webBrowserClient = gameObject.AddComponent<UwbWebView>();
194-
await ((UwbWebView)webBrowserClient).Init(engineStartupTimeoutMs);
231+
await ((UwbWebView)webBrowserClient).Init(engineStartupTimeoutMs, _redactTokensInLogs, RedactTokenValues);
195232
readySignalReceived = true;
196233
#endif
197234
}
@@ -558,8 +595,43 @@ private static void SetDefaultWindowsBrowserLogLevel()
558595
};
559596
}
560597
}
598+
599+
private static void SetWindowsRedactionHandler()
600+
{
601+
if (Instance?.webBrowserClient is WebBrowserClient browserClient)
602+
{
603+
browserClient.Logger = new DefaultUnityWebBrowserLogger(redactionHandler: _redactTokensInLogs ? RedactTokenValues : null);
604+
}
605+
}
561606
#endif
562607

608+
/// <summary>
609+
/// Redacts access and ID token data from a log message if found.
610+
/// </summary>
611+
private static string RedactTokenValues(string message)
612+
{
613+
try
614+
{
615+
var match = Regex.Match(message, @"({.*})");
616+
if (match.Success)
617+
{
618+
var jsonPart = match.Groups[1].Value;
619+
var response = JsonUtility.FromJson<StringResponse>(jsonPart);
620+
if (response?.responseFor is PassportFunction.GET_ACCESS_TOKEN or PassportFunction.GET_ID_TOKEN && !string.IsNullOrEmpty(response.result))
621+
{
622+
response.result = "[REDACTED]";
623+
return message.Replace(jsonPart, JsonUtility.ToJson(response));
624+
}
625+
}
626+
}
627+
catch (Exception)
628+
{
629+
// ignored
630+
}
631+
632+
return message;
633+
}
634+
563635
private PassportImpl GetPassportImpl()
564636
{
565637
if (passportImpl != null)

src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/[email protected]/Runtime/Logging/DefaultUnityWebBrowserLogger.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//
66
// This project is under the MIT license. See the LICENSE.md file for more details.
77

8+
using System;
89
using UnityEngine;
910

1011
namespace VoltstroStudios.UnityWebBrowser.Logging
@@ -17,25 +18,42 @@ public sealed class DefaultUnityWebBrowserLogger : IWebBrowserLogger
1718
private const string LoggingTag = "[UWB]";
1819

1920
private readonly ILogger logger;
20-
21-
public DefaultUnityWebBrowserLogger()
21+
22+
/// <summary>
23+
/// A function that defines how sensitive data should be redacted.
24+
/// If null, no redaction is applied.
25+
/// </summary>
26+
public Func<string, string>? redactionHandler;
27+
28+
public DefaultUnityWebBrowserLogger(Func<string, string>? redactionHandler = null)
2229
{
2330
logger = UnityEngine.Debug.unityLogger;
31+
this.redactionHandler = redactionHandler;
2432
}
2533

2634
public void Debug(object message)
2735
{
28-
logger.Log(LogType.Log, LoggingTag, message);
36+
logger.Log(LogType.Log, LoggingTag, redactIfRequired(message));
2937
}
3038

3139
public void Warn(object message)
3240
{
33-
logger.LogWarning(LoggingTag, message);
41+
logger.LogWarning(LoggingTag, redactIfRequired(message));
3442
}
3543

3644
public void Error(object message)
3745
{
38-
logger.LogError(LoggingTag, message);
46+
logger.LogError(LoggingTag, redactIfRequired(message));
47+
}
48+
49+
private object redactIfRequired(object message)
50+
{
51+
if (redactionHandler != null && message is string)
52+
{
53+
return redactionHandler((string)message);
54+
}
55+
56+
return message;
3957
}
4058
}
4159
}

src/Packages/Passport/Runtime/ThirdParty/UnityWebBrowser/[email protected]/Runtime/UwbWebView.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#if !IMMUTABLE_CUSTOM_BROWSER && (UNITY_STANDALONE_WIN || (UNITY_ANDROID && UNITY_EDITOR_WIN) || (UNITY_IPHONE && UNITY_EDITOR_WIN))
22

3+
using System;
34
using System.IO;
45
using System.Linq;
56
using System.Net;
@@ -15,6 +16,7 @@
1516
using VoltstroStudios.UnityWebBrowser.Core.Engines;
1617
using VoltstroStudios.UnityWebBrowser.Core.Js;
1718
using VoltstroStudios.UnityWebBrowser.Helper;
19+
using VoltstroStudios.UnityWebBrowser.Logging;
1820
using VoltstroStudios.UnityWebBrowser.Shared;
1921
using VoltstroStudios.UnityWebBrowser.Shared.Core;
2022

@@ -28,7 +30,7 @@ public class UwbWebView : MonoBehaviour, IWebBrowserClient
2830

2931
private WebBrowserClient? webBrowserClient;
3032

31-
public async UniTask Init(int engineStartupTimeoutMs)
33+
public async UniTask Init(int engineStartupTimeoutMs, bool redactTokensInLogs, Func<string, string> redactionHandler)
3234
{
3335
GameObject persistentObject = new GameObject("UWB");
3436
WebBrowserNoUi browser = persistentObject.AddComponent<WebBrowserNoUi>();
@@ -49,6 +51,9 @@ public async UniTask Init(int engineStartupTimeoutMs)
4951
_ => LogSeverity.Info
5052
};
5153

54+
// Logger
55+
webBrowserClient.Logger = new DefaultUnityWebBrowserLogger(redactionHandler: redactTokensInLogs ? redactionHandler : null);
56+
5257
// Js
5358
webBrowserClient.jsMethodManager = new JsMethodManager { jsMethodsEnable = true };
5459
webBrowserClient.RegisterJsMethod<string>("callback",

0 commit comments

Comments
 (0)