Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow sub organization applications to issue tokens to access the res…
Browse files Browse the repository at this point in the history
…ources in sub organizations
ShanChathusanda93 committed Jan 25, 2025
1 parent 72b70c8 commit cd494b5
Showing 21 changed files with 405 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2013-2025, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2018-2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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<String, List>
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);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2018-2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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<OAuthClientAuthenticator> 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<String> configuredClientAuthMethods = new ArrayList<>();
try {
OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId, tenantDomain);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2024, WSO2 LLC. (http://www.wso2.com).
* Copyright (c) 2017-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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()));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2023, WSO2 LLC. (http://www.wso2.com).
* Copyright (c) 2017-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2024, WSO2 LLC. (http://www.wso2.com).
* Copyright (c) 2017-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@@ -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;
@@ -316,6 +317,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);
}
@@ -1398,7 +1409,23 @@ 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()) {
Loading

0 comments on commit cd494b5

Please sign in to comment.