This is an automated email from the ASF dual-hosted git repository.

ashishvijaywargiya pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 39ec4fda5c Improved: Align tenant resolution between LoginWorker and 
ContextFilter (#1835)
39ec4fda5c is described below

commit 39ec4fda5c36094ea902b138a7eb2645f6d5dee4
Author: Krishna Uprit <[email protected]>
AuthorDate: Wed Sep 2 10:58:55 2026 +0530

    Improved: Align tenant resolution between LoginWorker and ContextFilter 
(#1835)
    
    `ContextFilter` and `LoginWorker` each resolve `userTenantId` for a request 
but use opposite precedence, and `ContextFilter` updates the session 
`delegatorName` in place when the resolved tenant changes. This makes the two 
consistent.
    
    - `LoginWorker.login(...)` now resolves `userTenantId` the same way
      `ContextFilter` already does: request attribute first, request parameter 
as
      fallback. Previously it read the parameter first, so the two could resolve
      different tenants for the same request.
    
    - `ContextFilter` now compares the tenant encoded in the session's existing
      `delegatorName` (`name#tenantId`) against the tenant resolved for the 
current
      request. When they differ it invalidates the session, so `dispatcher`,
      `security` and `userLogin` are rebuilt for the current tenant on the next
      request instead of `delegatorName` alone being overwritten. A warning is
      logged when this happens.
    
    No change for single-tenant deployments or when the session tenant and the 
request tenant already match.
    
    Thank you Krishna Uprit for the contribution.
    
    Co-authored-by: Krishnauprit18 <[email protected]>
---
 .../apache/ofbiz/webapp/control/ContextFilter.java | 26 ++++++++++++++++++++++
 .../apache/ofbiz/webapp/control/LoginWorker.java   |  8 +++++--
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git 
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
 
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
index 20b0303113..75f01a7210 100644
--- 
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
+++ 
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
@@ -30,6 +30,7 @@ import jakarta.servlet.ServletRequest;
 import jakarta.servlet.ServletResponse;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilGenerics;
@@ -143,6 +144,31 @@ public class ContextFilter implements Filter {
                     tenantId = null;
                 }
                 if (UtilValidate.isNotEmpty(tenantId)) {
+                    // If an existing session already carries a delegatorName 
for a different
+                    // tenant than the one resolved for this request, 
invalidate it here rather
+                    // than only overwriting delegatorName below: dispatcher, 
security and
+                    // userLogin stay bound to the old tenant otherwise, so a 
clean session is
+                    // rebuilt on the next request instead. Use 
getSession(false) so a request
+                    // that has no session yet is left alone - it cannot carry 
a stale tenant.
+                    HttpSession existingSession = 
httpRequest.getSession(false);
+                    if (existingSession != null) {
+                        String existingDelegatorName = (String) 
existingSession.getAttribute("delegatorName");
+                        if (UtilValidate.isNotEmpty(existingDelegatorName)) {
+                            int hashIndex = existingDelegatorName.indexOf('#');
+                            String existingTenantId =
+                                    hashIndex > 0 ? 
existingDelegatorName.substring(hashIndex + 1).trim() : null;
+                            if (existingTenantId != null && 
!tenantId.equals(existingTenantId)) {
+                                // Log a fixed message only; request-derived 
values (host name,
+                                // userTenantId) are deliberately kept out of 
the log line.
+                                Debug.logWarning("Tenant context mismatch: the 
session is bound to a"
+                                        + " different tenant than the one 
resolved for this request."
+                                        + " Invalidating the session so a 
clean per-tenant context is"
+                                        + " rebuilt on the next request.", 
MODULE);
+                                existingSession.invalidate();
+                            }
+                        }
+                    }
+
                     // if the request path is a root mount then redirect to 
the initial path
                     if ("".equals(httpRequest.getContextPath()) && 
"".equals(httpRequest.getServletPath())) {
                         GenericValue tenant = 
EntityQuery.use(baseDelegator).from("Tenant").where("tenantId", 
tenantId).queryOne();
diff --git 
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
 
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
index 457a4aef8c..27d91889b0 100644
--- 
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
+++ 
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
@@ -459,8 +459,12 @@ public final class LoginWorker {
         // if a tenantId was passed in, see if the userLoginId is associated 
with that tenantId
         // (can use any delegator for this, entity is not tenant-specific)
         String tenantId = request.getParameter("userTenantId");
-        if (UtilValidate.isEmpty(tenantId)) {
-            tenantId = (String) request.getAttribute("userTenantId");
+        // Align with ContextFilter: when this request already carries a 
resolved userTenantId
+        // attribute (for example from a hostname mapped to a tenant), that 
value wins over a
+        // conflicting request parameter, so both components authenticate 
against the same tenant.
+        String requestTenantId = (String) request.getAttribute("userTenantId");
+        if (UtilValidate.isNotEmpty(requestTenantId)) {
+            tenantId = requestTenantId;
         }
         if (UtilValidate.isNotEmpty(tenantId)) {
             // see if we need to activate a tenant delegator, only do if the 
current delegatorName has a hash symbol in it,

Reply via email to