From 5b0bb86b3e0bc566b92ab5348b2b4ceba69ac531 Mon Sep 17 00:00:00 2001 From: Shan Chathusanda Jayathilaka Date: Fri, 17 Jan 2025 09:43:57 +0530 Subject: [PATCH] Allow sub organization applications to issue tokens to access the resources in sub organizations --- .../carbon/identity/oauth2/OAuth2Service.java | 25 ++++++++++- .../BasicAuthClientAuthenticator.java | 23 ++++++++++- .../OAuthClientAuthnService.java | 18 ++++++++ .../oauth2/dao/AccessTokenDAOImpl.java | 18 ++++++++ .../oauth2/dao/TokenManagementDAOImpl.java | 23 ++++++++++- .../oauth2/token/AccessTokenIssuer.java | 27 +++++++++++- .../identity/oauth2/token/JWTTokenIssuer.java | 41 ++++++++++++++++++- .../AbstractAuthorizationGrantHandler.java | 33 ++++++++++++++- .../handlers/grant/PasswordGrantHandler.java | 32 ++++++++++++++- .../handlers/grant/RefreshGrantHandler.java | 10 +++-- .../identity/oauth2/util/AuthzUtil.java | 12 +++++- .../carbon/identity/oauth2/util/JWTUtils.java | 12 ++++++ .../DefaultOAuth2ScopeValidator.java | 10 ++++- .../validators/TokenValidationHandler.java | 31 ++++++++++++++ .../openidconnect/DefaultIDTokenBuilder.java | 14 ++++++- 15 files changed, 309 insertions(+), 20 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java index d32a2abc8c1..79035c61416 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.oltu.oauth2.common.message.types.GrantType; import org.owasp.encoder.Encode; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.AbstractAdmin; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.central.log.mgt.utils.LogConstants; @@ -63,6 +64,7 @@ import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; import org.wso2.carbon.identity.openidconnect.model.Constants; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import org.wso2.carbon.user.api.Claim; import org.wso2.carbon.user.core.UserStoreManager; import org.wso2.carbon.utils.DiagnosticLog; @@ -676,7 +678,9 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques } else if (accessTokenDO != null) { if (revokeRequestDTO.getConsumerKey().equals(accessTokenDO.getConsumerKey())) { - if ((OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey()). + // Extracting the application details with consumer key and tenant domain. + String tenantDomain = IdentityTenantUtil.getTenantDomain(accessTokenDO.getTenantID()); + if ((OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey(), tenantDomain). isTokenBindingValidationEnabled()) && (!isValidTokenBinding(accessTokenDO. getTokenBinding(), revokeRequestDTO.getRequest()))) { if (LoggerUtils.isDiagnosticLogsEnabled()) { @@ -981,7 +985,24 @@ public Claim[] getUserClaims(String accessTokenIdentifier) { public String getOauthApplicationState(String consumerKey) { try { - OAuthAppDO appDO = OAuth2Util.getAppInformationByClientId(consumerKey); + String tenantDomain = IdentityTenantUtil.getTenantDomain(IdentityTenantUtil.getLoginTenantId()); + String appOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If appOrgId is not empty, then the request comes for an application which is registered directly in the + organization of the appOrgId. Therefore, we need to resolve the tenant domain of the organization. + */ + if (StringUtils.isNotEmpty(appOrgId)) { + try { + tenantDomain = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(appOrgId); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain for the organization ID: " + + appOrgId, e); + } + } + // Getting the application information by consumer key and tenant domain. + OAuthAppDO appDO = OAuth2Util.getAppInformationByClientId(consumerKey, tenantDomain); return appDO.getState(); } catch (IdentityOAuth2Exception e) { log.error("Error while finding application state for application with client_id: " + consumerKey, e); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/BasicAuthClientAuthenticator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/BasicAuthClientAuthenticator.java index 891fe5f1b15..c25688c7399 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/BasicAuthClientAuthenticator.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/BasicAuthClientAuthenticator.java @@ -24,13 +24,17 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.oltu.oauth2.common.OAuth; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.oauth.IdentityOAuthAdminException; import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext; import org.wso2.carbon.identity.oauth2.model.ClientAuthenticationMethodModel; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import java.util.ArrayList; import java.util.Base64; @@ -89,8 +93,25 @@ public boolean authenticateClient(HttpServletRequest request, Map log.debug("Authenticating client : " + oAuthClientAuthnContext.getClientId() + " with client " + "secret."); } + String tenantDomain = IdentityTenantUtil.resolveTenantDomain(); + String appOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If appOrgId is not empty, then the request comes for an application which is registered directly in the + organization of the appOrgId. Therefore, we need to resolve the tenant domain of the organization. + */ + if (StringUtils.isNotEmpty(appOrgId)) { + try { + tenantDomain = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(appOrgId); + } catch (OrganizationManagementException e) { + throw new InvalidOAuthClientException("Error while resolving tenant domain for the organization " + + "ID: " + appOrgId, e); + } + } + // Authenticating the client with the client id, the client secret and the extracted tenant domain. return OAuth2Util.authenticateClient(oAuthClientAuthnContext.getClientId(), - (String) oAuthClientAuthnContext.getParameter(OAuth.OAUTH_CLIENT_SECRET)); + (String) oAuthClientAuthnContext.getParameter(OAuth.OAUTH_CLIENT_SECRET), tenantDomain); } catch (IdentityOAuthAdminException e) { throw new OAuthClientAuthnException("Error while authenticating client", OAuth2ErrorCodes.INVALID_CLIENT, e); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/OAuthClientAuthnService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/OAuthClientAuthnService.java index a36fe3f1251..128146cfedb 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/OAuthClientAuthnService.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/client/authentication/OAuthClientAuthnService.java @@ -21,16 +21,19 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext; import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; import org.wso2.carbon.identity.oauth2.model.ClientAuthenticationMethodModel; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import java.util.ArrayList; import java.util.Arrays; @@ -321,6 +324,21 @@ private List getConfiguredClientAuthMethods(String cli throws OAuthClientAuthnException, InvalidOAuthClientException { String tenantDomain = IdentityTenantUtil.resolveTenantDomain(); + String appOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If appOrgId is not empty, then the request comes for an application which is registered directly in the + organization of the appOrgId. Therefore, we need to resolve the tenant domain of the organization. + */ + if (StringUtils.isNotEmpty(appOrgId)) { + try { + tenantDomain = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(appOrgId); + } catch (OrganizationManagementException e) { + throw new InvalidOAuthClientException("Error while resolving tenant domain for the organization ID: " + + appOrgId, e); + } + } List configuredClientAuthMethods = new ArrayList<>(); try { OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId, tenantDomain); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/AccessTokenDAOImpl.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/AccessTokenDAOImpl.java index 64fac73b8e2..3c39fdf8a7a 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/AccessTokenDAOImpl.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/AccessTokenDAOImpl.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.database.utils.jdbc.JdbcTemplate; import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -251,6 +252,23 @@ private void insertAccessToken(String accessToken, String consumerKey, AccessTok insertTokenPrepStmt.setString(19, authorizedOrganization); int appTenantId = IdentityTenantUtil.getLoginTenantId(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, we need to resolve the + tenant domain of the organization to get the application tenant id. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + try { + String tenantDomain = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + appTenantId = OAuth2Util.getTenantId(tenantDomain); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: " + + applicationResidentOrgId, e); + } + } if (OAuth2ServiceComponentHolder.isIDPIdColumnEnabled()) { if (OAuth2ServiceComponentHolder.isConsentedTokenColumnEnabled()) { insertTokenPrepStmt.setString(20, Boolean.toString(accessTokenDO.isConsentedToken())); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/TokenManagementDAOImpl.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/TokenManagementDAOImpl.java index aa7fe011a8c..bc36a726c54 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/TokenManagementDAOImpl.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/TokenManagementDAOImpl.java @@ -24,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ServiceProvider; @@ -163,7 +164,25 @@ public RefreshTokenValidationDataDO validateRefreshToken(String consumerKey, Str prepStmt = connection.prepareStatement(sql); prepStmt.setString(1, getPersistenceProcessor().getProcessedClientId(consumerKey)); - prepStmt.setInt(2, IdentityTenantUtil.getLoginTenantId()); + int tenantId = IdentityTenantUtil.getLoginTenantId(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, we need to resolve the + tenant domain of the organization to get the application tenant id. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + try { + String tenantDomain = OAuth2ServiceComponentHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: " + + applicationResidentOrgId, e); + } + } + prepStmt.setInt(2, tenantId); if (refreshToken != null) { prepStmt.setString(3, getHashingPersistenceProcessor().getProcessedRefreshToken(refreshToken)); } @@ -183,7 +202,7 @@ public RefreshTokenValidationDataDO validateRefreshToken(String consumerKey, Str validationDataDO.setAccessToken(resultSet.getString(1)); } String userName = resultSet.getString(2); - int tenantId = resultSet.getInt(3); + tenantId = resultSet.getInt(3); String userDomain = resultSet.getString(4); String tenantDomain = OAuth2Util.getTenantDomain(tenantId); validationDataDO.setRefreshToken(refreshToken); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java index 0158db681b1..06784405e84 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java @@ -26,6 +26,7 @@ import org.apache.oltu.oauth2.common.error.OAuthError; import org.apache.oltu.oauth2.common.message.types.GrantType; import org.owasp.encoder.Encode; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; @@ -308,6 +309,16 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) if (!isOfTypeApplicationUser) { tokReqMsgCtx.setAuthorizedUser(oAuthAppDO.getAppOwner()); tokReqMsgCtx.addProperty(OAuthConstants.UserType.USER_TYPE, OAuthConstants.UserType.APPLICATION); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, we are setting the authorized + user's accessing organization as the applicationResidentOrgId. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + tokReqMsgCtx.getAuthorizedUser().setAccessingOrganization(applicationResidentOrgId); + } } else { tokReqMsgCtx.addProperty(OAuthConstants.UserType.USER_TYPE, OAuthConstants.UserType.APPLICATION_USER); } @@ -1361,7 +1372,21 @@ private void setResponseHeaders(OAuthTokenReqMessageContext tokReqMsgCtx, private OAuthAppDO getOAuthApplication(String consumerKey) throws InvalidOAuthClientException, IdentityOAuth2Exception { - OAuthAppDO authAppDO = OAuth2Util.getAppInformationByClientId(consumerKey); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + // If the applicationResidentOrgId is not null, resolve the tenant domain from the organization id to get the + // application information by passing the consumer key and the tenant domain. + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + try { + tenantDomain = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: " + + applicationResidentOrgId, e); + } + } + OAuthAppDO authAppDO = OAuth2Util.getAppInformationByClientId(consumerKey, tenantDomain); String appState = authAppDO.getState(); if (StringUtils.isEmpty(appState)) { if (log.isDebugEnabled()) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java index 72b81f1e694..d54f6ee7e97 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java @@ -35,6 +35,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.base.IdentityConstants; @@ -55,6 +56,7 @@ import org.wso2.carbon.identity.openidconnect.CustomClaimsCallbackHandler; import org.wso2.carbon.identity.openidconnect.OIDCClaimUtil; import org.wso2.carbon.identity.openidconnect.util.ClaimHandlerUtil; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import java.security.Key; import java.security.cert.Certificate; @@ -418,7 +420,16 @@ private String getSigningTenantDomain(String clientID, AuthenticatedUser authent throws IdentityOAuth2Exception { String tenantDomain; - if (OAuthServerConfiguration.getInstance().getUseSPTenantDomainValue()) { + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. In this scenario, the signing tenant domain + should be the root tenant domain of the applicationResidentOrgId. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + } else if (OAuthServerConfiguration.getInstance().getUseSPTenantDomainValue()) { if (log.isDebugEnabled()) { log.debug("Using the tenant domain of the SP to sign the token"); } @@ -566,8 +577,25 @@ protected JWTClaimsSet createJWTClaimSet(OAuthAuthzReqMessageContext authAuthzRe // loading the stored application data OAuthAppDO oAuthAppDO; + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); try { - oAuthAppDO = OAuth2Util.getAppInformationByClientId(consumerKey); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, the tenant domain should be + extracted from the organization id to get the information of the application. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + try { + tenantDomain = OAuth2ServiceComponentHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: " + + applicationResidentOrgId, e); + } + } + oAuthAppDO = OAuth2Util.getAppInformationByClientId(consumerKey, tenantDomain); } catch (InvalidOAuthClientException e) { throw new IdentityOAuth2Exception("Error while retrieving app information for clientId: " + consumerKey, e); } @@ -584,6 +612,15 @@ protected JWTClaimsSet createJWTClaimSet(OAuthAuthzReqMessageContext authAuthzRe spTenantDomain = tokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain(); } + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. spTenantDomain is used to get the idTokenIssuer + for the token. In this scenario, the tenant domain that needs to be used as the issuer is the root tenant. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + spTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();; + } + boolean isMTLSrequest; if (authAuthzReqMessageContext != null) { /* If the auth request is originated from a request object reference(ex: PAR), then that endpoint should be diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java index 4a628f0bef3..f10390e74d1 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java @@ -66,6 +66,7 @@ import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeHandler; import org.wso2.carbon.identity.oauth2.validators.scope.ScopeValidator; import org.wso2.carbon.identity.openidconnect.OIDCClaimUtil; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import org.wso2.carbon.utils.DiagnosticLog; import java.sql.Timestamp; @@ -837,10 +838,24 @@ private OAuth2AccessTokenRespDTO createResponseWithTokenBean(AccessTokenDO exist OAuthAppDO oAuthAppDO; String consumerKey = existingAccessTokenDO.getConsumerKey(); try { - oAuthAppDO = OAuth2Util.getAppInformationByClientId(consumerKey); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, the tenant domain should be + extracted from the organization id to get the information of the application. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + tenantDomain = OAuth2ServiceComponentHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + } + oAuthAppDO = OAuth2Util.getAppInformationByClientId(consumerKey, tenantDomain); } catch (InvalidOAuthClientException e) { throw new IdentityOAuth2Exception("Error while retrieving app information for client_id : " + consumerKey, e); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: ", e); } if (issueRefreshToken(existingAccessTokenDO.getTokenType()) && @@ -884,7 +899,19 @@ private OAuthCacheKey getOAuthCacheKey(String scope, String consumerKey, String private OAuthAppDO getoAuthApp(String consumerKey) throws IdentityOAuth2Exception { OAuthAppDO oAuthAppBean; try { - oAuthAppBean = OAuth2Util.getAppInformationByClientId(consumerKey); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. Therefore, the tenant domain should be + extracted from the organization id to get the information of the application. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + tenantDomain = OAuth2ServiceComponentHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + } + oAuthAppBean = OAuth2Util.getAppInformationByClientId(consumerKey, tenantDomain); if (log.isDebugEnabled()) { log.debug("Service Provider specific expiry time enabled for application : " + consumerKey + ". Application access token expiry time : " + oAuthAppBean.getApplicationAccessTokenExpiryTime() @@ -893,6 +920,8 @@ private OAuthAppDO getoAuthApp(String consumerKey) throws IdentityOAuth2Exceptio } } catch (InvalidOAuthClientException e) { throw new IdentityOAuth2Exception("Error while retrieving app information for clientId: " + consumerKey, e); + } catch (OrganizationManagementException e) { + throw new RuntimeException("Error while resolving tenant domain from the organization id: ", e); } return oAuthAppBean; } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java index bba40461009..524996dabfe 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.AuthenticationDataPublisher; import org.wso2.carbon.identity.application.authentication.framework.AuthenticationService; import org.wso2.carbon.identity.application.authentication.framework.AuthenticatorFlowStatus; @@ -66,6 +67,7 @@ import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.UserStoreClientException; @@ -273,13 +275,30 @@ private void setPropertiesForTokenGeneration(OAuthTokenReqMessageContext tokReqM tokReqMsgCtx.setScope(tokenReq.getScope()); } - private String getFullQualifiedUsername(OAuth2AccessTokenReqDTO tokenReq, ServiceProvider serviceProvider) { + private String getFullQualifiedUsername(OAuth2AccessTokenReqDTO tokenReq, ServiceProvider serviceProvider) + throws IdentityOAuth2Exception { boolean isEmailUserNameEnabled = MultitenantUtils.isEmailUserName(); boolean isSaasApp = serviceProvider.isSaasApp(); boolean isLegacySaaSAuthenticationEnabled = IdentityTenantUtil.isLegacySaaSAuthenticationEnabled(); String usernameFromRequest = tokenReq.getResourceOwnerUsername(); String tenantDomainFromContext = IdentityTenantUtil.resolveTenantDomain(); + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is registered + directly in the organization of the applicationResidentOrgId. In this scenario the user is also in the + organization level and the tenant domain of the user should be resolved from the organization id. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + try { + tenantDomainFromContext = OAuth2ServiceComponentHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(applicationResidentOrgId); + } catch (OrganizationManagementException e) { + throw new IdentityOAuth2Exception("Error while resolving tenant domain from the organization id: " + + applicationResidentOrgId, e); + } + } if (!isSaasApp) { /* @@ -388,6 +407,17 @@ private AuthenticatedUser validateUserCredentials(OAuth2AccessTokenReqDTO tokenR tenantAwareUserName, isPublishPasswordGrantLoginEnabled, userTenantDomain, serviceProvider); } if (authenticatedUser.isPresent()) { + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is + registered directly in the organization of the applicationResidentOrgId. In this scenario the user's + accessing and resident organization will be the organization of the applicationResidentOrgId. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + authenticatedUser.get().setAccessingOrganization(applicationResidentOrgId); + authenticatedUser.get().setUserResidentOrganization(applicationResidentOrgId); + } return authenticatedUser.get(); } triggerPasswordExpiryValidationEvent(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT, tenantAwareUserName, diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java index 7a6762a1270..036c1e5b19c 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java @@ -576,11 +576,11 @@ private ResponseHeader[] getResponseHeaders(OAuthTokenReqMessageContext tokReqMs return respHeaders; } - private OAuthAppDO getOAuthApp(String clientId) throws IdentityOAuth2Exception { + private OAuthAppDO getOAuthApp(String clientId, String tenantDomain) throws IdentityOAuth2Exception { OAuthAppDO oAuthAppDO; try { - oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId); + oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId, tenantDomain); } catch (InvalidOAuthClientException e) { throw new IdentityOAuth2Exception("Error while retrieving app information for clientId: " + clientId, e); @@ -644,7 +644,8 @@ private void setTokenData(AccessTokenDO accessTokenDO, OAuthTokenReqMessageConte RefreshTokenValidationDataDO validationBean, OAuth2AccessTokenReqDTO tokenReq, Timestamp timestamp) throws IdentityOAuth2Exception { - OAuthAppDO oAuthAppDO = getOAuthApp(tokenReq.getClientId()); + OAuthAppDO oAuthAppDO = getOAuthApp(tokenReq.getClientId(), validationBean.getAuthorizedUser(). + getTenantDomain()); createTokens(accessTokenDO, tokReqMsgCtx); setRefreshTokenData(accessTokenDO, tokenReq, validationBean, oAuthAppDO, accessTokenDO.getRefreshToken(), timestamp, tokReqMsgCtx); @@ -864,7 +865,8 @@ private boolean checkExecutePreIssueAccessTokensActions(RefreshTokenValidationDa OAuthTokenReqMessageContext tokenReqMessageContext) throws IdentityOAuth2Exception { - OAuthAppDO oAuthAppBean = getOAuthApp(tokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId()); + OAuthAppDO oAuthAppBean = getOAuthApp(tokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId(), + refreshTokenValidationDataDO.getAuthorizedUser().getTenantDomain()); String grantType = refreshTokenValidationDataDO.getGrantType(); // Allow if refresh token is issued for token requests from following grant types and, diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java index 5811e251c08..6060814841b 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java @@ -255,7 +255,17 @@ public static boolean isUserAuthorized(AuthenticatedUser authenticatedUser, List // Application id is not required for basic authentication flow. List roleIds = getUserRoles(authenticatedUser, null); - List permissions = getAssociatedScopesForRoles(roleIds, authenticatedUser.getTenantDomain()); + List permissions; + /* + If the authenticatedUser contains an accessing organization, the the scopes should be checked against the + accessing organization. + */ + if (StringUtils.isNotEmpty(authenticatedUser.getAccessingOrganization())) { + permissions = getAssociatedScopesForRoles(roleIds, + authenticatedUser.getAccessingOrganization()); + } else { + permissions = getAssociatedScopesForRoles(roleIds, authenticatedUser.getTenantDomain()); + } if (OAuthServerConfiguration.getInstance().isUseLegacyPermissionAccessForUserBasedAuth()) { // Handling backward compatibility for previous access level. List internalScopes = getInternalScopes(authenticatedUser.getTenantDomain()); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/JWTUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/JWTUtils.java index af002c3fdc3..02c247cf737 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/JWTUtils.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/JWTUtils.java @@ -30,6 +30,7 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.IdentityProvider; +import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty; import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil; import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; @@ -54,6 +55,7 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.text.ParseException; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -298,6 +300,16 @@ public static String getSigningTenantDomain(JWTClaimsSet claimsSet, AccessTokenD if (log.isDebugEnabled()) { log.debug("Getting signing tenant domain from OAuth app."); } + // Check if the OAuth application is a sub-organization application. Based on that we can define what + // is the tenant that signed the JWT. In this case the signing tenant is the root organization. + String appTenantDomain = IdentityTenantUtil.getTenantDomain(accessTokenDO.getTenantID()); + ServiceProviderProperty[] serviceProviderProperties = OAuth2Util.getServiceProvider( + accessTokenDO.getConsumerKey(), appTenantDomain).getSpProperties(); + if (serviceProviderProperties != null && Arrays.stream(serviceProviderProperties) + .anyMatch(property -> "isSubOrgApp".equals(property.getName()) + && Boolean.parseBoolean(property.getValue()))) { + return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + } return OAuth2Util.getTenantDomainOfOauthApp(accessTokenDO.getConsumerKey()); } catch (InvalidOAuthClientException e) { throw new IdentityOAuth2Exception("Error while getting tenant domain from OAuth app with consumer key: " diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/DefaultOAuth2ScopeValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/DefaultOAuth2ScopeValidator.java index 1025c723f34..4e5451f00ee 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/DefaultOAuth2ScopeValidator.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/DefaultOAuth2ScopeValidator.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; @@ -129,8 +130,13 @@ public List validateScope(OAuthTokenReqMessageContext tokenReqMessageCon String tenantDomain = tokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain(); String clientId = tokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId(); String appId = getApplicationId(clientId, tenantDomain); - // When user is not accessing the resident organization, resolve the application id from the shared app table. - if (!AuthzUtil.isUserAccessingResidentOrganization(tokenReqMessageContext.getAuthorizedUser())) { + /* + When user is not accessing the resident organization and if the user is not accessing an application in + the organization level, resolve the application id from the shared app table. + */ + if (!AuthzUtil.isUserAccessingResidentOrganization(tokenReqMessageContext.getAuthorizedUser()) && + StringUtils.isEmpty(PrivilegedCarbonContext.getThreadLocalCarbonContext(). + getApplicationResidentOrganizationId())) { String orgId = tokenReqMessageContext.getAuthorizedUser().getAccessingOrganization(); String appResideOrgId = resolveOrgIdByTenantDomain(tenantDomain); appId = SharedAppResolveDAO.resolveSharedApplication(appResideOrgId, appId, orgId); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java index fabb785dbba..6666c068d0d 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java @@ -27,6 +27,7 @@ import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty; import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.central.log.mgt.utils.LogConstants; import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; @@ -50,6 +51,7 @@ import org.wso2.carbon.utils.DiagnosticLog; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -507,6 +509,16 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); accessTokenDO = OAuth2ServiceComponentHolder.getInstance().getTokenProvider() .getVerifiedAccessToken(validationRequest.getAccessToken().getIdentifier(), false); + /* + Check if the OAuth application is a fragment application. If that is not a fragment application, + then getting the tenant domain from the token. + */ + String appTenantDomain = IdentityTenantUtil.getTenantDomain(accessTokenDO.getTenantID()); + ServiceProviderProperty[] serviceProviderProperties = OAuth2Util.getServiceProvider( + accessTokenDO.getConsumerKey(), appTenantDomain).getSpProperties(); + if (!isFragmentApp(serviceProviderProperties)) { + tenantDomain = appTenantDomain; + } boolean isCrossTenantTokenIntrospectionAllowed = OAuthServerConfiguration.getInstance().isCrossTenantTokenIntrospectionAllowed(); if (!isCrossTenantTokenIntrospectionAllowed && accessTokenDO != null && @@ -684,6 +696,25 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation return introResp; } + private boolean isFragmentApp(ServiceProviderProperty[] serviceProviderProperties) { + + if (serviceProviderProperties == null) { + return false; + } + + if (Arrays.stream(serviceProviderProperties). + anyMatch(property -> "isFragmentApp".equals(property.getName()))) { + if (Arrays.stream(serviceProviderProperties). + anyMatch(property -> "isFragmentApp".equals(property.getName()) && + !Boolean.parseBoolean(property.getValue()))) { + return true; + } else { + return false; + } + } + return false; + } + private String getAuthzUser(AccessTokenDO accessTokenDO) throws IdentityOAuth2Exception { AuthenticatedUser user = accessTokenDO.getAuthzUser(); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultIDTokenBuilder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultIDTokenBuilder.java index 614539abd96..52e9b779c48 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultIDTokenBuilder.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultIDTokenBuilder.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.AuthenticationMethodNameTranslator; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache; @@ -121,7 +122,7 @@ public String buildIDToken(OAuthTokenReqMessageContext tokenReqMsgCtxt, // Initialize OAuthAppDO using the client ID. OAuthAppDO oAuthAppDO; try { - oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId); + oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId, spTenantDomain); } catch (InvalidOAuthClientException e) { String error = "Error occurred while getting app information for client_id: " + clientId; throw new IdentityOAuth2Exception(error, e); @@ -421,7 +422,16 @@ private JWTClaimsSet handleOIDCCustomClaims(OAuthTokenReqMessageContext tokReqMs private String getSigningTenantDomain(OAuthTokenReqMessageContext tokReqMsgCtx) { boolean isJWTSignedWithSPKey = OAuthServerConfiguration.getInstance().isJWTSignedWithSPKey(); - if (isJWTSignedWithSPKey) { + String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getApplicationResidentOrganizationId(); + /* + If applicationResidentOrgId is not empty, then the request comes for an application which is + registered directly in the organization of the applicationResidentOrgId. In this case, the tenant domain + that needs to be signing the token should be the root tenant of the organization in applicationResidentOrgId. + */ + if (StringUtils.isNotEmpty(applicationResidentOrgId)) { + return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + } else if (isJWTSignedWithSPKey) { return (String) tokReqMsgCtx.getProperty(MultitenantConstants.TENANT_DOMAIN); } else { return tokReqMsgCtx.getAuthorizedUser().getTenantDomain();