Skip to content

Commit aa6b8a6

Browse files
authored
Merge pull request #218 from Yasasr1/b2b-session-fix
Improve getUserSessions conditional auth function to resolve user accessing org when getting sessions during B2B logins.
2 parents 88ee6d1 + ef41983 commit aa6b8a6

File tree

6 files changed

+262
-11
lines changed

6 files changed

+262
-11
lines changed

components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@
238238
net.minidev.json; version="${net.minidev.json.imp.pkg.version.range}",
239239
org.wso2.carbon.identity.central.log.mgt.utils; version="${carbon.identity.package.import.version.range}",
240240
org.wso2.carbon.identity.conditional.auth.functions.common.utils,
241-
org.wso2.carbon.utils*;version="${carbon.kernel.package.import.version.range}"
241+
org.wso2.carbon.utils*;version="${carbon.kernel.package.import.version.range}",
242+
org.wso2.carbon.identity.organization.management.service;version="${org.wso2.carbon.identity.organization.management.core.version.range}",
243+
org.wso2.carbon.identity.organization.management.service.exception;version="${org.wso2.carbon.identity.organization.management.core.version.range}"
242244
</Import-Package>
243245
<DynamicImport-Package>
244246
org.graalvm.polyglot,

components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetUserSessionsFunctionImpl.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
2-
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
2+
* Copyright (c) 2019-2025, WSO2 LLC. (http://www.wso2.com).
33
*
4-
* WSO2 Inc. licenses this file to you under the Apache License,
4+
* WSO2 LLC. licenses this file to you under the Apache License,
55
* Version 2.0 (the "License"); you may not use this file except
66
* in compliance with the License.
77
* You may obtain a copy of the License at
@@ -18,6 +18,7 @@
1818

1919
package org.wso2.carbon.identity.conditional.auth.functions.user;
2020

21+
import org.apache.commons.lang.StringUtils;
2122
import org.apache.commons.logging.Log;
2223
import org.apache.commons.logging.LogFactory;
2324
import org.graalvm.polyglot.HostAccess;
@@ -31,6 +32,7 @@
3132
import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder;
3233
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserSession;
3334
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsWrapperFactoryProvider;
35+
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
3436
import org.wso2.carbon.user.core.UserRealm;
3537

3638
import java.util.List;
@@ -62,14 +64,14 @@ private List<UserSession> getUserSessions(AuthenticatedUser authenticatedUser)
6264
throws UserSessionRetrievalException {
6365

6466
List<UserSession> userSessions = null;
65-
String tenantDomain = authenticatedUser.getTenantDomain();
67+
String tenantDomain = getUserTenantDomain(authenticatedUser);
6668

6769
try {
6870
UserRealm userRealm = Utils.getUserRealm(tenantDomain);
6971
if (userRealm != null) {
7072
String userId = authenticatedUser.getUserId();
7173
userSessions = UserFunctionsServiceHolder.getInstance()
72-
.getUserSessionManagementService().getSessionsByUserId(userId);
74+
.getUserSessionManagementService().getSessionsByUserId(userId, tenantDomain);
7375
}
7476
} catch (SessionManagementException e) {
7577
throw new UserSessionRetrievalException("Error occurred while retrieving sessions: ", e);
@@ -81,4 +83,20 @@ private List<UserSession> getUserSessions(AuthenticatedUser authenticatedUser)
8183
return userSessions;
8284
}
8385

86+
private String getUserTenantDomain(AuthenticatedUser authenticatedUser) throws UserSessionRetrievalException {
87+
88+
String tenantDomain = authenticatedUser.getTenantDomain();
89+
String userAccessingOrganization = authenticatedUser.getAccessingOrganization();
90+
if (StringUtils.isNotBlank(userAccessingOrganization)) {
91+
try {
92+
tenantDomain = UserFunctionsServiceHolder.getInstance().getOrganizationManager()
93+
.resolveTenantDomain(userAccessingOrganization);
94+
} catch (OrganizationManagementException e) {
95+
throw new UserSessionRetrievalException(
96+
"Error occurred while resolving tenant domain of user accessing organization: " +
97+
userAccessingOrganization, e);
98+
}
99+
}
100+
return tenantDomain;
101+
}
84102
}

components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.wso2.carbon.identity.conditional.auth.functions.user.SetAccountAssociationToLocalUser;
6363
import org.wso2.carbon.identity.conditional.auth.functions.user.UpdateUserPasswordFunction;
6464
import org.wso2.carbon.identity.conditional.auth.functions.user.UpdateUserPasswordFunctionImpl;
65+
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
6566
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
6667
import org.wso2.carbon.idp.mgt.IdpManager;
6768
import org.wso2.carbon.user.core.service.RealmService;
@@ -290,4 +291,21 @@ protected void unsetRoleManagementService(RoleManagementService roleManagementSe
290291
LOG.debug("Role management service is unset in the conditional authentication user functions bundle");
291292
}
292293
}
294+
295+
@Reference(name = "identity.organization.management.component",
296+
service = OrganizationManager.class,
297+
cardinality = ReferenceCardinality.MANDATORY,
298+
policy = ReferencePolicy.DYNAMIC,
299+
unbind = "unsetOrganizationManager")
300+
protected void setOrganizationManager(OrganizationManager organizationManager) {
301+
302+
UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
303+
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle.");
304+
}
305+
306+
protected void unsetOrganizationManager(OrganizationManager organizationManager) {
307+
308+
UserFunctionsServiceHolder.getInstance().setOrganizationManager(null);
309+
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle.");
310+
}
293311
}

components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceHolder.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry;
2222
import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService;
2323
import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
24+
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
2425
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
2526
import org.wso2.carbon.idp.mgt.IdpManager;
2627
import org.wso2.carbon.user.core.service.RealmService;
@@ -35,6 +36,7 @@ public class UserFunctionsServiceHolder {
3536
private ApplicationManagementService applicationManagementService;
3637
private RoleManagementService roleManagementService;
3738
private JsFunctionRegistry jsFunctionRegistry;
39+
private OrganizationManager organizationManager;
3840

3941
private UserFunctionsServiceHolder() {
4042

@@ -106,4 +108,14 @@ public void setJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {
106108

107109
this.jsFunctionRegistry = jsFunctionRegistry;
108110
}
111+
112+
public OrganizationManager getOrganizationManager() {
113+
114+
return organizationManager;
115+
}
116+
117+
public void setOrganizationManager(OrganizationManager organizationManager) {
118+
119+
this.organizationManager = organizationManager;
120+
}
109121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.wso2.carbon.identity.conditional.auth.functions.user;
20+
21+
import org.mockito.Mock;
22+
import org.testng.Assert;
23+
import org.testng.annotations.AfterMethod;
24+
import org.testng.annotations.BeforeMethod;
25+
import org.testng.annotations.Test;
26+
import org.wso2.carbon.context.PrivilegedCarbonContext;
27+
import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService;
28+
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser;
29+
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.graaljs.JsGraalAuthenticatedUser;
30+
import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceDataHolder;
31+
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
32+
import org.wso2.carbon.identity.application.authentication.framework.model.UserSession;
33+
import org.wso2.carbon.identity.common.testng.WithCarbonHome;
34+
import org.wso2.carbon.identity.common.testng.WithRealmService;
35+
import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder;
36+
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserSession;
37+
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
38+
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
39+
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
40+
41+
import java.util.ArrayList;
42+
import java.util.List;
43+
44+
import static org.mockito.Mockito.mock;
45+
import static org.mockito.Mockito.when;
46+
import static org.mockito.MockitoAnnotations.initMocks;
47+
48+
/**
49+
* Unit tests for GetUserSessionsFunctionImpl class.
50+
*/
51+
@WithCarbonHome
52+
@WithRealmService(injectToSingletons = {UserFunctionsServiceHolder.class, IdentityTenantUtil.class,
53+
FrameworkServiceDataHolder.class})
54+
public class GetUserSessionsFunctionImplTest {
55+
56+
private static final String TEST_USER_NAME = "testUser";
57+
private static final String TENANT_DOMAIN_CARBON_SUPER = "carbon.super";
58+
private static final String USER_STORE_DOMAIN_PRIMARY = "PRIMARY";
59+
private static final String TEST_USER_ID_123 = "test-user-id-123";
60+
private static final String TEST_USER_ID_456 = "test-user-id-456";
61+
private static final String TEST_USER_ID_ORG_123 = "test-user-id-org-123";
62+
private static final String TEST_USER_ID_ORG_456 = "test-user-id-org-456";
63+
private static final String ORG_ID_123 = "org123";
64+
private static final String ORG_TENANT_DOMAIN = "org.tenant.com";
65+
private static final String INVALID_ORG = "invalidOrg";
66+
private static final String ORG_NOT_FOUND_MESSAGE = "Organization not found";
67+
68+
@Mock
69+
private UserSessionManagementService userSessionManagementService;
70+
@Mock
71+
private OrganizationManager organizationManager;
72+
private GetUserSessionsFunctionImpl getUserSessionsFunction;
73+
74+
@BeforeMethod
75+
public void setUp() {
76+
77+
initMocks(this);
78+
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(TENANT_DOMAIN_CARBON_SUPER, true);
79+
80+
getUserSessionsFunction = new GetUserSessionsFunctionImpl();
81+
UserFunctionsServiceHolder.getInstance().setUserSessionManagementService(userSessionManagementService);
82+
UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
83+
}
84+
85+
@AfterMethod
86+
public void tearDown() {
87+
88+
PrivilegedCarbonContext.destroyCurrentContext();
89+
}
90+
91+
@Test
92+
public void testGetUserSessionsSuccess() throws Exception {
93+
94+
// Create test user.
95+
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
96+
authenticatedUser.setUserName(TEST_USER_NAME);
97+
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
98+
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
99+
authenticatedUser.setUserId(TEST_USER_ID_123);
100+
101+
JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);
102+
103+
// Create mock user sessions.
104+
List<UserSession> mockSessions = new ArrayList<>();
105+
UserSession session1 = mock(UserSession.class);
106+
UserSession session2 = mock(UserSession.class);
107+
mockSessions.add(session1);
108+
mockSessions.add(session2);
109+
110+
// Mock the session management service.
111+
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_123, TENANT_DOMAIN_CARBON_SUPER))
112+
.thenReturn(mockSessions);
113+
114+
// Execute the function.
115+
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);
116+
117+
// Verify results.
118+
Assert.assertNotNull(result);
119+
Assert.assertEquals(result.size(), 2);
120+
}
121+
122+
@Test
123+
public void testGetUserSessionsWithEmptyResult() throws Exception {
124+
125+
// Create test user.
126+
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
127+
authenticatedUser.setUserName(TEST_USER_NAME);
128+
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
129+
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
130+
authenticatedUser.setUserId(TEST_USER_ID_456);
131+
132+
JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);
133+
134+
// Mock empty session list.
135+
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_456, TENANT_DOMAIN_CARBON_SUPER))
136+
.thenReturn(new ArrayList<>());
137+
138+
// Execute the function.
139+
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);
140+
141+
// Verify results.
142+
Assert.assertNotNull(result);
143+
Assert.assertEquals(result.size(), 0);
144+
}
145+
146+
@Test
147+
public void testGetUserSessionsWithOrganization() throws Exception {
148+
149+
// Create test user with accessing organization.
150+
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
151+
authenticatedUser.setUserName(TEST_USER_NAME);
152+
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
153+
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
154+
authenticatedUser.setUserId(TEST_USER_ID_ORG_123);
155+
authenticatedUser.setAccessingOrganization(ORG_ID_123);
156+
157+
JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);
158+
159+
// Mock organization manager.
160+
when(organizationManager.resolveTenantDomain(ORG_ID_123)).thenReturn(ORG_TENANT_DOMAIN);
161+
162+
// Create mock user sessions
163+
List<UserSession> mockSessions = new ArrayList<>();
164+
UserSession session = mock(UserSession.class);
165+
mockSessions.add(session);
166+
167+
// Mock the session management service with resolved tenant domain.
168+
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_ORG_123, ORG_TENANT_DOMAIN))
169+
.thenReturn(mockSessions);
170+
171+
// Execute the function.
172+
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);
173+
174+
// Verify results.
175+
Assert.assertNotNull(result);
176+
Assert.assertEquals(result.size(), 1);
177+
}
178+
179+
@Test
180+
public void testGetUserSessionsWithOrganizationManagementException() throws Exception {
181+
182+
// Create test user with accessing organization.
183+
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
184+
authenticatedUser.setUserName(TEST_USER_NAME);
185+
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
186+
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
187+
authenticatedUser.setUserId(TEST_USER_ID_ORG_456);
188+
authenticatedUser.setAccessingOrganization(INVALID_ORG);
189+
190+
JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);
191+
192+
// Mock organization manager to throw exception.
193+
when(organizationManager.resolveTenantDomain(INVALID_ORG))
194+
.thenThrow(new OrganizationManagementException(ORG_NOT_FOUND_MESSAGE));
195+
196+
// Execute the function.
197+
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);
198+
Assert.assertNull(result);
199+
}
200+
}

pom.xml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@
246246
<artifactId>nimbus-jose-jwt</artifactId>
247247
<version>${nimbusds.version}</version>
248248
</dependency>
249+
<dependency>
250+
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
251+
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
252+
<version>${identity.organization.management.core.version}</version>
253+
</dependency>
249254

250255
<dependency>
251256
<groupId>org.jacoco</groupId>
@@ -321,12 +326,6 @@
321326
<artifactId>org.wso2.carbon.crypto.impl</artifactId>
322327
<version>${carbon.crypto.version}</version>
323328
</dependency>
324-
<dependency>
325-
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
326-
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
327-
<version>${identity.organization.management.core.version}</version>
328-
<scope>test</scope>
329-
</dependency>
330329
<dependency>
331330
<groupId>org.jacoco</groupId>
332331
<artifactId>jacoco-maven-plugin</artifactId>
@@ -530,6 +529,8 @@
530529
<carbon.user.package.import.version.range>[1.0.1, 2.0.0)</carbon.user.package.import.version.range>
531530
<carbon.identity.framework.version>7.7.34</carbon.identity.framework.version>
532531
<identity.organization.management.core.version>1.0.89</identity.organization.management.core.version>
532+
<org.wso2.carbon.identity.organization.management.core.version.range>[1.0.0, 2.0.0)
533+
</org.wso2.carbon.identity.organization.management.core.version.range>
533534
<carbon.identity.framework.testutils.version>5.20.447</carbon.identity.framework.testutils.version>
534535
<carbon.identity.package.import.version.range>[5.14.0, 8.0.0)</carbon.identity.package.import.version.range>
535536
<identity.governance.version>1.1.17</identity.governance.version>

0 commit comments

Comments
 (0)