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 08e2154
Show file tree
Hide file tree
Showing 15 changed files with 254 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 @@ -167,7 +168,7 @@ public static AccessTokenIssuer getInstance() throws IdentityOAuth2Exception {
public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO)
throws IdentityException {

String grantType = tokenReqDTO.getGrantType();
String grantType = tokenReqDTO.getGrantType(); // This is the place that we need to check the authorized user.
OAuth2AccessTokenRespDTO tokenRespDTO = null;

AuthorizationGrantHandler authzGrantHandler = authzGrantHandlers.get(grantType);
Expand Down Expand Up @@ -308,6 +309,11 @@ 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 (StringUtils.isNotEmpty(applicationResidentOrgId)) {
tokReqMsgCtx.getAuthorizedUser().setAccessingOrganization(applicationResidentOrgId);
}
} else {
tokReqMsgCtx.addProperty(OAuthConstants.UserType.USER_TYPE, OAuthConstants.UserType.APPLICATION_USER);
}
Expand Down Expand Up @@ -1361,7 +1367,19 @@ 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 (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 08e2154

Please sign in to comment.