Skip to content

Commit

Permalink
Add support to access organization resources in tenant perspective
Browse files Browse the repository at this point in the history
  • Loading branch information
ShanChathusanda93 committed Nov 30, 2024
1 parent 9eb3d13 commit e308fa5
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants;
import org.wso2.carbon.identity.application.common.model.ProvisioningServiceProviderType;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty;
import org.wso2.carbon.identity.application.common.model.ThreadLocalProvisioningServiceProvider;
import org.wso2.carbon.identity.application.common.model.User;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil;
Expand All @@ -57,6 +58,7 @@
import org.wso2.carbon.identity.oauth2.validators.RefreshTokenValidator;

import java.text.ParseException;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -173,8 +175,23 @@ protected AuthenticationResult doAuthenticate(MessageContext messageContext) {
ServiceProvider serviceProvider = null;
String serviceProviderName = null;
String serviceProviderUUID = null;
boolean isSubOrgApp = false;
try {
serviceProvider = OAuth2Util.getServiceProvider(oAuth2IntrospectionResponseDTO.getClientId());
if (authorizedUser != null) {
ServiceProviderProperty[] serviceProviderProperties = OAuth2Util.getServiceProvider(
oAuth2IntrospectionResponseDTO.getClientId(), authorizedUser.getTenantDomain()).
getSpProperties();
if (serviceProviderProperties != null && Arrays.stream(serviceProviderProperties)
.anyMatch(property -> "isSubOrgApp".equals(property.getName())
&& Boolean.parseBoolean(property.getValue()))) {
isSubOrgApp = true;
authenticationContext.addParameter("isSubOrgApp", true);
serviceProvider = OAuth2Util.getServiceProvider(oAuth2IntrospectionResponseDTO.getClientId(),
authorizedUser.getTenantDomain());
}
} else {
serviceProvider = OAuth2Util.getServiceProvider(oAuth2IntrospectionResponseDTO.getClientId());
}
if (serviceProvider != null) {
serviceProviderName = serviceProvider.getApplicationName();
serviceProviderUUID = serviceProvider.getApplicationResourceId();
Expand All @@ -193,8 +210,12 @@ protected AuthenticationResult doAuthenticate(MessageContext messageContext) {

String serviceProviderTenantDomain = null;
try {
serviceProviderTenantDomain =
OAuth2Util.getTenantDomainOfOauthApp(oAuth2IntrospectionResponseDTO.getClientId());
if (serviceProvider != null && isSubOrgApp) {
serviceProviderTenantDomain = serviceProvider.getTenantDomain();
} else {
serviceProviderTenantDomain = OAuth2Util.getTenantDomainOfOauthApp(
oAuth2IntrospectionResponseDTO.getClientId());
}
} catch (InvalidOAuthClientException | IdentityOAuth2Exception e) {
if (log.isDebugEnabled()) {
log.debug("Error occurred while getting the OAuth App tenantDomain by Consumer key: "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ private AuthorizationResult authorizeInOrganizationLevel(Request request, Respon
private boolean isRequestValidForTenant(AuthenticationContext authenticationContext,
AuthorizationContext authorizationContext, Request request) {

return (Utils.isUserBelongsToRequestedTenant(authenticationContext, request) ||
boolean isSubOrgApp = false;
if (authenticationContext.getParameter("isSubOrgApp") != null) {
isSubOrgApp = Boolean.parseBoolean(authenticationContext.getParameter("isSubOrgApp").toString());
}
return (Utils.isUserBelongsToRequestedTenant(authenticationContext, request) || isSubOrgApp ||
(authorizationContext.isCrossTenantAllowed()) &&
Utils.isTenantBelongsToAllowedCrossTenant(authenticationContext, authorizationContext));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.MDC;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.base.IdentityRuntimeException;
import org.wso2.carbon.identity.context.rewrite.bean.OrganizationRewriteContext;
import org.wso2.carbon.identity.context.rewrite.bean.RewriteContext;
import org.wso2.carbon.identity.context.rewrite.internal.ContextRewriteValveServiceComponentHolder;
import org.wso2.carbon.identity.core.util.IdentityConfigParser;
Expand All @@ -41,8 +43,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
Expand All @@ -59,6 +63,7 @@
public class TenantContextRewriteValve extends ValveBase {

private static List<RewriteContext> contextsToRewrite;
private static List<OrganizationRewriteContext> contextsToRewriteInTenantPerspective;
private static List<String> contextListToOverwriteDispatch;
private static List<String> ignorePathListForOverwriteDispatch;
private static List<String> organizationRoutingOnlySupportedAPIPaths;
Expand All @@ -73,6 +78,7 @@ protected synchronized void startInternal() throws LifecycleException {
super.startInternal();
// Initialize the tenant context rewrite valve.
contextsToRewrite = getContextsToRewrite();
contextsToRewriteInTenantPerspective = getContextsToRewriteInTenantPerspective();
contextListToOverwriteDispatch = getContextListToOverwriteDispatchLocation();
ignorePathListForOverwriteDispatch = getIgnorePathListForOverwriteDispatch();
isTenantQualifiedUrlsEnabled = isTenantQualifiedUrlsEnabled();
Expand Down Expand Up @@ -110,6 +116,26 @@ public void invoke(Request request, Response response) throws IOException, Servl
}
}

outerLoop:
for (OrganizationRewriteContext context : contextsToRewriteInTenantPerspective) {
Pattern patternTenantPerspective = Pattern.compile("^/t/[^/]+/o/[a-f0-9\\-]+?" + context.getContext());
if (patternTenantPerspective.matcher(requestURI).find() && CollectionUtils.isNotEmpty(context.getSubPaths())) {
for (Pattern subPath : context.getSubPaths()) {
if (subPath.matcher(requestURI).find()) {
isContextRewrite = true;
isWebApp = context.isWebApp();
contextToForward = context.getContext();
int startIndex = requestURI.indexOf("/o/") + 3;
int endIndex = requestURI.indexOf("/", startIndex);
String appOrgId = requestURI.substring(startIndex, endIndex);
PrivilegedCarbonContext.getThreadLocalCarbonContext().
setApplicationResidentOrganizationId(appOrgId);
break outerLoop;
}
}
}
}

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
try {
MDC.put(TENANT_DOMAIN, tenantDomain);
Expand All @@ -135,7 +161,8 @@ public void invoke(Request request, Response response) throws IOException, Servl
Ex-: Request: /t/<tenant-domain>/o/api/server/v1/applications --> /o/server/v1/applications
*/
if (!requestURI.startsWith(ORGANIZATION_PATH_PARAM) &&
requestURI.contains(ORGANIZATION_PATH_PARAM)) {
requestURI.contains(ORGANIZATION_PATH_PARAM) &&
!isOrganizationIdAvailableInTenantPerspective(requestURI)) {
dispatchLocation = "/o" + dispatchLocation;
}
if (contextListToOverwriteDispatch.contains(contextToForward) && !isIgnorePath(dispatchLocation)) {
Expand All @@ -151,7 +178,10 @@ public void invoke(Request request, Response response) throws IOException, Servl
requestURI = requestURI.replace(carbonWebContext + "/", "");
}
//Servlet
requestURI = requestURI.replace("/t/" + tenantDomain, "");
if (StringUtils.isEmpty(PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getApplicationResidentOrganizationId())) {
requestURI = requestURI.replace("/t/" + tenantDomain, "");
}
request.getRequestDispatcher(requestURI).forward(request, response);
}
}
Expand All @@ -176,6 +206,11 @@ public void invoke(Request request, Response response) throws IOException, Servl
}
}

private boolean isOrganizationIdAvailableInTenantPerspective(String requestURI) {

return Pattern.compile("^/t/[^/]+/o/[a-f0-9\\-]+?").matcher(requestURI).find();
}

private void unsetMDCThreadLocals() {

MDC.remove(TENANT_DOMAIN);
Expand Down Expand Up @@ -217,6 +252,51 @@ private List<RewriteContext> getContextsToRewrite() {
return rewriteContexts;
}

private List<OrganizationRewriteContext> getContextsToRewriteInTenantPerspective() {

List<OrganizationRewriteContext> organizationRewriteContexts = new ArrayList<>();
Map<String, Object> configuration = IdentityConfigParser.getInstance().getConfiguration();
Object webAppBasePathContexts = configuration.get("OrgContextsToRewriteInTenantPerspective.WebApp.Context." +
"BasePath");
setOrganizationRewriteContexts(organizationRewriteContexts, webAppBasePathContexts, true);

Object webAppSubPathContexts = configuration.get("OrgContextsToRewriteInTenantPerspective.WebApp.Context." +
"SubPaths.Path");
setSubPathContexts(organizationRewriteContexts, webAppSubPathContexts);

return organizationRewriteContexts;
}

private void setOrganizationRewriteContexts(List<OrganizationRewriteContext> organizationRewriteContexts,
Object basePathContexts, boolean isWebApp) {

if (basePathContexts != null) {
if (basePathContexts instanceof ArrayList) {
for (String context : (ArrayList<String>) basePathContexts) {
organizationRewriteContexts.add(new OrganizationRewriteContext(isWebApp, context));
}
} else {
organizationRewriteContexts.add(new OrganizationRewriteContext(isWebApp,
basePathContexts.toString()));
}
}
}

private void setSubPathContexts(List<OrganizationRewriteContext> organizationRewriteContexts,
Object subPathContexts) {

if (subPathContexts instanceof ArrayList) {
for (String subPath : (ArrayList<String>) subPathContexts) {
Optional<OrganizationRewriteContext> maybeOrgRewriteContext = organizationRewriteContexts.stream()
.filter(rewriteContext -> subPath.startsWith(rewriteContext.getContext()))
.max(Comparator.comparingInt(rewriteContext -> rewriteContext.getContext().length()));
maybeOrgRewriteContext.ifPresent(
organizationRewriteContext -> organizationRewriteContext.addSubPath(
Pattern.compile("^/t/[^/]+/o/[a-f0-9\\-]+" + subPath)));
}
}
}

/**
* Get context list to overwrite dispatch location.
*
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,8 @@
<osgi.util.tracker.imp.pkg.version.range>[1.5.1, 2.0.0)</osgi.util.tracker.imp.pkg.version.range>

<!-- Carbon Kernel version -->
<carbon.kernel.version>4.9.17</carbon.kernel.version>
<carbon.kernel.feature.version>4.9.0</carbon.kernel.feature.version>
<carbon.kernel.version>4.10.25</carbon.kernel.version>
<carbon.kernel.feature.version>4.10.0</carbon.kernel.feature.version>
<carbon.kernel.imp.pkg.version.range>[4.5.0, 5.0.0)</carbon.kernel.imp.pkg.version.range>

<!--Carbon Component version-->
Expand Down

0 comments on commit e308fa5

Please sign in to comment.