From d16a0526afeb3d0032a4ac209ade7769d9d7c112 Mon Sep 17 00:00:00 2001 From: Matthias Blom Date: Wed, 22 Apr 2026 10:15:54 +0200 Subject: [PATCH 1/2] Do not get session id in JWT session --- .../main/logger-engine/classes/Logger.cls | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index 27c2ca577..e2bd6c46c 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -86,13 +86,44 @@ global with sharing class Logger { set; } + private static Boolean IS_JWT_SESSION { + get { + if (IS_JWT_SESSION == null) { + Boolean hasCurrentSession = false; + Boolean hasJwtSession = false; + + for (AuthSession session : [ + SELECT IsCurrent, IsAssociatedWithJwtAccessToken + FROM AuthSession + WHERE UsersId = :System.UserInfo.getUserId() + ]) { + if (session.IsAssociatedWithJwtAccessToken) { + hasJwtSession = true; + } + else if (session.IsCurrent) { + hasCurrentSession = true; + } + } + + IS_JWT_SESSION = !hasCurrentSession && hasJwtSession; + } + + return IS_JWT_SESSION ; + } + set; + } + private static final String USER_SESSION_ID { get { if (USER_SESSION_ID == null) { // TODO Spring '24 release - simplify this (and other lazy-loaded values) // by switching to the fancy, new ?? null coalescing operator try { - USER_SESSION_ID = System.UserInfo.getSessionId(); + // If we're in a JWT session, System.UserInfo.getSessionId() will throw an + // uncatchable exception + USER_SESSION_ID = IS_JWT_SESSION + ? '' + : System.UserInfo.getSessionId(); } catch (Exception ex) { USER_SESSION_ID = ''; } From a7c41748fdd223b36c9488ad468544b4840c1f85 Mon Sep 17 00:00:00 2001 From: Matthias Blom Date: Wed, 22 Apr 2026 16:48:59 +0200 Subject: [PATCH 2/2] Load AuthSession via LoggerEngineDataSelector --- .../main/logger-engine/classes/Logger.cls | 60 ++++++------------- .../classes/LoggerEngineDataSelector.cls | 13 +++- .../classes/LoggerSObjectProxy.cls | 1 + 3 files changed, 30 insertions(+), 44 deletions(-) diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index e2bd6c46c..19bb06b19 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -86,50 +86,12 @@ global with sharing class Logger { set; } - private static Boolean IS_JWT_SESSION { - get { - if (IS_JWT_SESSION == null) { - Boolean hasCurrentSession = false; - Boolean hasJwtSession = false; - - for (AuthSession session : [ - SELECT IsCurrent, IsAssociatedWithJwtAccessToken - FROM AuthSession - WHERE UsersId = :System.UserInfo.getUserId() - ]) { - if (session.IsAssociatedWithJwtAccessToken) { - hasJwtSession = true; - } - else if (session.IsCurrent) { - hasCurrentSession = true; - } - } - - IS_JWT_SESSION = !hasCurrentSession && hasJwtSession; - } - - return IS_JWT_SESSION ; - } - set; - } - private static final String USER_SESSION_ID { get { if (USER_SESSION_ID == null) { - // TODO Spring '24 release - simplify this (and other lazy-loaded values) - // by switching to the fancy, new ?? null coalescing operator - try { - // If we're in a JWT session, System.UserInfo.getSessionId() will throw an - // uncatchable exception - USER_SESSION_ID = IS_JWT_SESSION - ? '' - : System.UserInfo.getSessionId(); - } catch (Exception ex) { - USER_SESSION_ID = ''; - } - // If System.UserInfo.getSessionId() returns null, set to an empty string to - // avoid calling System.UserInfo.getSessionId() again - USER_SESSION_ID = USER_SESSION_ID ?? ''; + // If loadSessionId() returns null, set to an empty string to + // avoid calling loadSessionId() again + USER_SESSION_ID = loadSessionId() ?? ''; } return USER_SESSION_ID; } @@ -3968,6 +3930,22 @@ global with sharing class Logger { } } + private static String loadSessionId() { + LoggerSObjectProxy.AuthSession authSessionProxy = LoggerEngineDataSelector.getInstance().getCachedAuthSessionProxy(); + + if (authSessionProxy != null && authSessionProxy.IsAssociatedWithJwtAccessToken) { + // If the user is authenticated via a JWT access token, + // calling `getSessionId()` will throw an uncatchable exception + return null; + } + + try { + return System.UserInfo.getSessionId(); + } catch (Exception ex) { + return null; + } + } + private static void setAsyncContext(AsyncContext asyncContext) { // Only set the async context the first time that a non-null value is provided // Previous versions of Nebula Logger would always set it, but that wasn't the diff --git a/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls b/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls index 2e14df939..451c2a0a2 100644 --- a/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls +++ b/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls @@ -48,6 +48,7 @@ public without sharing virtual class LoggerEngineDataSelector { List authSessionRecords = [ SELECT Id, + IsAssociatedWithJwtAccessToken, LoginType, LoginHistoryId, LoginHistory.Application, @@ -61,8 +62,12 @@ public without sharing virtual class LoggerEngineDataSelector { SourceIp, UsersId FROM AuthSession - WHERE UsersId IN :userIds AND IsCurrent = TRUE - ORDER BY ParentId NULLS FIRST + WHERE UsersId IN :userIds + AND ( + IsCurrent = TRUE + OR IsAssociatedWithJwtAccessToken = TRUE + ) + ORDER BY ParentId NULLS LAST, IsCurrent DESC ]; List authSessionProxies = (List) System.JSON.deserialize( @@ -75,7 +80,9 @@ public without sharing virtual class LoggerEngineDataSelector { } for (LoggerSObjectProxy.AuthSession authSessionProxy : authSessionProxies) { - userIdToAuthSessionProxy.put(authSessionProxy.UsersId, authSessionProxy); + if (!userIdToAuthSessionProxy.containsKey(authSessionProxy.UsersId)) { + userIdToAuthSessionProxy.put(authSessionProxy.UsersId, authSessionProxy); + } } return userIdToAuthSessionProxy; } diff --git a/nebula-logger/core/main/logger-engine/classes/LoggerSObjectProxy.cls b/nebula-logger/core/main/logger-engine/classes/LoggerSObjectProxy.cls index 1304a70af..74be875b4 100644 --- a/nebula-logger/core/main/logger-engine/classes/LoggerSObjectProxy.cls +++ b/nebula-logger/core/main/logger-engine/classes/LoggerSObjectProxy.cls @@ -27,6 +27,7 @@ public without sharing class LoggerSObjectProxy { public String SessionType; public String SourceIp; public Id UsersId; + public Boolean IsAssociatedWithJwtAccessToken; } /**