Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix OAuth caching for client ID tenant unification #2217

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,7 @@ public void testGetServiceProvider(String clientId, Exception e) throws Exceptio
mockStatic(IdentityTenantUtil.class);
when(IdentityTenantUtil.getTenantDomain(anyInt())).thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
when(IdentityTenantUtil.getTenantId(anyString())).thenReturn(MultitenantConstants.SUPER_TENANT_ID);
when(IdentityTenantUtil.getLoginTenantId()).thenReturn(MultitenantConstants.SUPER_TENANT_ID);

try (Connection connection = getConnection()) {
mockStatic(IdentityDatabaseUtil.class);
Expand Down Expand Up @@ -1968,6 +1969,7 @@ public void testHandleOAuthAuthorizationRequest1(boolean showDisplayName, Object
mockStatic(IdentityTenantUtil.class);
when(IdentityTenantUtil.getTenantDomain(anyInt())).thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
when(IdentityTenantUtil.getTenantId(anyString())).thenReturn(MultitenantConstants.SUPER_TENANT_ID);
when(IdentityTenantUtil.getLoginTenantId()).thenReturn(MultitenantConstants.SUPER_TENANT_ID);
mockStatic(LoggerUtils.class);
when(LoggerUtils.isDiagnosticLogsEnabled()).thenReturn(diagnosticLogsEnabled);
IdentityEventService eventServiceMock = mock(IdentityEventService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.oauth.cache.AppInfoCache;
import org.wso2.carbon.identity.oauth.cache.AppInfoCacheKey;
import org.wso2.carbon.identity.oauth.cache.OAuthCache;
import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey;
import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes;
Expand Down Expand Up @@ -360,7 +361,8 @@ public OAuthConsumerAppDTO registerAndRetrieveOAuthApplicationData(OAuthConsumer
application.getTlsClientCertificateBoundAccessTokens());
}
dao.addOAuthApplication(app);
AppInfoCache.getInstance().addToCache(app.getOauthConsumerKey(), app);
AppInfoCache.getInstance().addToCache(new AppInfoCacheKey(
app.getOauthConsumerKey(), IdentityTenantUtil.getTenantId(tenantDomain)), app);
if (LOG.isDebugEnabled()) {
LOG.debug("Oauth Application registration success : " + application.getApplicationName() +
" in tenant domain: " + tenantDomain);
Expand Down Expand Up @@ -651,7 +653,8 @@ public void updateConsumerApplication(OAuthConsumerAppDTO consumerAppDTO) throws
consumerAppDTO.getTlsClientCertificateBoundAccessTokens());
}
dao.updateConsumerApplication(oauthappdo);
AppInfoCache.getInstance().addToCache(oauthappdo.getOauthConsumerKey(), oauthappdo);
AppInfoCache.getInstance().addToCache(new AppInfoCacheKey(
oauthappdo.getOauthConsumerKey(), IdentityTenantUtil.getLoginTenantId()), oauthappdo);
if (LOG.isDebugEnabled()) {
LOG.debug("Oauth Application update success : " + consumerAppDTO.getApplicationName() + " in " +
"tenant domain: " + tenantDomain);
Expand Down Expand Up @@ -946,7 +949,8 @@ public void updateConsumerAppState(String consumerKey, String newState) throws I
properties.setProperty(OAuthConstants.OAUTH_APP_NEW_STATE, newState);
properties.setProperty(OAuthConstants.ACTION_PROPERTY_KEY, OAuthConstants.ACTION_REVOKE);

AppInfoCache.getInstance().clearCacheEntry(consumerKey);
AppInfoCache.getInstance().clearCacheEntry(
new AppInfoCacheKey(consumerKey, IdentityTenantUtil.getLoginTenantId()));
updateAppAndRevokeTokensAndAuthzCodes(consumerKey, properties);
handleInternalTokenRevocation(consumerKey, properties);

Expand Down Expand Up @@ -1014,7 +1018,8 @@ public OAuthConsumerAppDTO updateAndRetrieveOauthSecretKey(String consumerKey) t
properties.setProperty(OAuthConstants.ACTION_PROPERTY_KEY, OAuthConstants.ACTION_REGENERATE);
properties.setProperty(OAuthConstants.OAUTH_APP_NEW_STATE, APP_STATE_ACTIVE);

AppInfoCache.getInstance().clearCacheEntry(consumerKey);
AppInfoCache.getInstance().clearCacheEntry(
new AppInfoCacheKey(consumerKey, IdentityTenantUtil.getLoginTenantId()));
updateAppAndRevokeTokensAndAuthzCodes(consumerKey, properties);
handleInternalTokenRevocation(consumerKey, properties);
if (LOG.isDebugEnabled()) {
Expand Down Expand Up @@ -1153,7 +1158,8 @@ public void removeOAuthApplicationData(String consumerKey) throws IdentityOAuthA
}
// Remove client credentials from cache.
OAuthCache.getInstance().clearCacheEntry(new OAuthCacheKey(consumerKey));
AppInfoCache.getInstance().clearCacheEntry(consumerKey);
AppInfoCache.getInstance().clearCacheEntry(
new AppInfoCacheKey(consumerKey, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()));
if (LOG.isDebugEnabled()) {
LOG.debug("Client credentials are removed from the cache for OAuth App with consumerKey: " + consumerKey);
}
Expand Down Expand Up @@ -1933,7 +1939,8 @@ OAuth2Service getOAuth2Service() {

OAuthAppDO getOAuthApp(String consumerKey) throws InvalidOAuthClientException, IdentityOAuth2Exception {

OAuthAppDO oauthApp = AppInfoCache.getInstance().getValueFromCache(consumerKey);
OAuthAppDO oauthApp = AppInfoCache.getInstance().getValueFromCache(
new AppInfoCacheKey(consumerKey, IdentityTenantUtil.getLoginTenantId()));
if (oauthApp != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("OAuth app with consumerKey: " + consumerKey + " retrieved from AppInfoCache.");
Expand All @@ -1947,7 +1954,8 @@ OAuthAppDO getOAuthApp(String consumerKey) throws InvalidOAuthClientException, I
if (LOG.isDebugEnabled()) {
LOG.debug("OAuth app with consumerKey: " + consumerKey + " retrieved from database.");
}
AppInfoCache.getInstance().addToCache(consumerKey, oauthApp);
AppInfoCache.getInstance().addToCache(
new AppInfoCacheKey(consumerKey, IdentityTenantUtil.getLoginTenantId()), oauthApp);
}

return oauthApp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/**
* AppInfoCache is used to cache oauth application information.
*/
public class AppInfoCache extends AuthenticationBaseCache<String, OAuthAppDO> {
public class AppInfoCache extends AuthenticationBaseCache<AppInfoCacheKey, OAuthAppDO> {

private static final String OAUTH_APP_INFO_CACHE_NAME = "AppInfoCache";

Expand All @@ -36,7 +36,7 @@ private AppInfoCache() {
}

/**
* Returns AppInfoCache instance
* Returns AppInfoCache instance.
*
* @return instance of OAuthAppInfoCache
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2023, 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
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.oauth.cache;

import org.apache.commons.lang.StringUtils;

/**
* Cache key for AppInfoCache.
*/
public class AppInfoCacheKey extends CacheKey {

private static final long serialVersionUID = 4278123242830651680L;
private final String consumerKey;
private final int tenantId;

public AppInfoCacheKey(String consumerKey, int tenantId) {

this.consumerKey = consumerKey;
this.tenantId = tenantId;
}

/**
* Get the consumer key of the cache key.
* @return Consumer key.
*/
public String getConsumerKey() {

return consumerKey;
}

/**
* Get the tenant id of the cache key.
* @return Tenant id.
*/
public int getTenantId() {

return tenantId;
}

@Override
public boolean equals(Object o) {

if (!(o instanceof AppInfoCacheKey)) {
return false;
}
return StringUtils.equals(consumerKey, ((AppInfoCacheKey) o).getConsumerKey()) &&
tenantId == ((AppInfoCacheKey) o).getTenantId();
}

@Override
public int hashCode() {

int result = consumerKey != null ? consumerKey.hashCode() : 0;
return 31 * result + tenantId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.oauth.IdentityOAuthAdminException;
import org.wso2.carbon.identity.oauth.cache.AppInfoCache;
import org.wso2.carbon.identity.oauth.cache.AppInfoCacheKey;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
Expand Down Expand Up @@ -607,18 +608,22 @@ private boolean isInvalidResponseType(OAuth2AuthorizeReqDTO authzReqDTO, OAuth2A

private OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
InvalidOAuthClientException {
OAuthAppDO oAuthAppDO = AppInfoCache.getInstance().getValueFromCache(authzReqDTO.getConsumerKey());

int tenantId;
if (StringUtils.isNotEmpty(authzReqDTO.getTenantDomain())) {
tenantId = IdentityTenantUtil.getTenantId(authzReqDTO.getTenantDomain());
} else {
tenantId = IdentityTenantUtil.getLoginTenantId();
}

OAuthAppDO oAuthAppDO = AppInfoCache.getInstance().getValueFromCache(
new AppInfoCacheKey(authzReqDTO.getConsumerKey(), tenantId));
if (oAuthAppDO != null) {
return oAuthAppDO;
} else {
String tenantDomain = authzReqDTO.getTenantDomain();
if (StringUtils.isNotEmpty(tenantDomain)) {
oAuthAppDO = new OAuthAppDAO().getAppInformation(
authzReqDTO.getConsumerKey(), IdentityTenantUtil.getTenantId(tenantDomain));
} else {
oAuthAppDO = new OAuthAppDAO().getAppInformation(authzReqDTO.getConsumerKey());
}
AppInfoCache.getInstance().addToCache(authzReqDTO.getConsumerKey(), oAuthAppDO);
oAuthAppDO = new OAuthAppDAO().getAppInformation(authzReqDTO.getConsumerKey(), tenantId);
AppInfoCache.getInstance().addToCache(
new AppInfoCacheKey(authzReqDTO.getConsumerKey(), tenantId), oAuthAppDO);
return oAuthAppDO;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,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.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.StandardInboundProtocols;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException;
Expand All @@ -44,6 +45,7 @@
import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl;
import org.wso2.carbon.identity.oauth.OAuthUtil;
import org.wso2.carbon.identity.oauth.cache.AppInfoCache;
import org.wso2.carbon.identity.oauth.cache.AppInfoCacheKey;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey;
import org.wso2.carbon.identity.oauth.cache.CacheEntry;
Expand Down Expand Up @@ -454,7 +456,8 @@ private void updateAuthApplication(ServiceProvider serviceProvider)
OAuthAppDAO dao = new OAuthAppDAO();
try {
dao.updateOAuthConsumerApp(serviceProvider, authenticationRequestConfigConfig.getInboundAuthKey());
AppInfoCache.getInstance().clearCacheEntry(authenticationRequestConfigConfig.getInboundAuthKey());
AppInfoCache.getInstance().clearCacheEntry(new AppInfoCacheKey(
authenticationRequestConfigConfig.getInboundAuthKey(), IdentityTenantUtil.getLoginTenantId()));
} catch (IdentityOAuthAdminException e) {
throw new IdentityApplicationManagementException("Error occurred while updating oauth consumer app for "
+ authenticationRequestConfigConfig.getInboundAuthKey(), e);
Expand All @@ -463,8 +466,6 @@ private void updateAuthApplication(ServiceProvider serviceProvider)

private void removeEntriesFromCache(Set<String> consumerKeys) throws IdentityOAuth2Exception {



if (isNotEmpty(consumerKeys)) {
Set<AccessTokenDO> accessTokenDOSet = new HashSet<>();
Set<AuthzCodeDO> authzCodeDOSet = new HashSet<>();
Expand All @@ -476,7 +477,8 @@ private void removeEntriesFromCache(Set<String> consumerKeys) throws IdentityOAu
authzCodeDOSet.addAll(OAuthTokenPersistenceFactory.getInstance()
.getAuthorizationCodeDAO().getAuthorizationCodeDOSetByConsumerKeyForOpenidScope(oauthKey));
// Remove client credential from AppInfoCache
appInfoCache.clearCacheEntry(oauthKey);
appInfoCache.clearCacheEntry(new AppInfoCacheKey(
oauthKey, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()));
OAuthCache.getInstance().clearCacheEntry(new OAuthCacheKey(oauthKey));
}

Expand Down
Loading