Skip to content

Commit

Permalink
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
  • Loading branch information
ShanChathusanda93 committed Jan 20, 2025
1 parent 32cb723 commit 5b0bb86
Show file tree
Hide file tree
Showing 15 changed files with 309 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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()) {
Expand Down
Loading

0 comments on commit 5b0bb86

Please sign in to comment.