Skip to content

Commit 2c5efd0

Browse files
Merge pull request #2698 from HasiniSama/fix-secret-regenerate-cache-issue
Clear token cache for each persistence processor type
2 parents 61afdb3 + ae8136c commit 2c5efd0

File tree

2 files changed

+121
-12
lines changed

2 files changed

+121
-12
lines changed

components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImpl.java

+18-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
/*
2-
* Copyright (c) 2019-2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
2+
* Copyright (c) 2019-2025, WSO2 LLC. (https://www.wso2.com).
33
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
67
* You may obtain a copy of the License at
78
*
89
* http://www.apache.org/licenses/LICENSE-2.0
910
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
1517
*/
1618

1719
package org.wso2.carbon.identity.oauth;
@@ -2826,7 +2828,14 @@ private static void clearTokenCacheEntry(String consumerKey, Set<AccessTokenDO>
28262828
throws IdentityOAuthAdminException {
28272829

28282830
for (AccessTokenDO detailToken : activeDetailedTokens) {
2829-
clearTokensFromCache(consumerKey, detailToken, detailToken.getAccessToken());
2831+
String accessToken = detailToken.getAccessToken();
2832+
try {
2833+
accessToken = OAuth2Util.getPersistenceProcessor().getPreprocessedAccessTokenIdentifier(accessToken);
2834+
} catch (IdentityOAuth2Exception e) {
2835+
throw handleError("Failed to retrieve the pre-processed access token for consumer key: "
2836+
+ consumerKey, e);
2837+
}
2838+
clearTokensFromCache(consumerKey, detailToken, accessToken);
28302839
}
28312840
}
28322841

components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImplTest.java

+103-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
2-
* Copyright (c) 2017-2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
2+
* Copyright (c) 2017-2025, WSO2 LLC. (https://www.wso2.com).
33
*
4-
* WSO2 Inc. licenses this file to you under the Apache License,
4+
* WSO2 LLC. licenses this file to you under the Apache License,
55
* Version 2.0 (the "License"); you may not use this file except
66
* in compliance with the License.
77
* You may obtain a copy of the License at
@@ -11,7 +11,7 @@
1111
* Unless required by applicable law or agreed to in writing,
1212
* software distributed under the License is distributed on an
1313
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14-
* KIND, either express or implied. See the License for the
14+
* KIND, either express or implied. See the License for the
1515
* specific language governing permissions and limitations
1616
* under the License.
1717
*/
@@ -34,6 +34,8 @@
3434
import org.testng.annotations.DataProvider;
3535
import org.testng.annotations.Test;
3636
import org.wso2.carbon.context.PrivilegedCarbonContext;
37+
import org.wso2.carbon.core.util.CryptoException;
38+
import org.wso2.carbon.core.util.CryptoUtil;
3739
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
3840
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
3941
import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
@@ -54,11 +56,17 @@
5456
import org.wso2.carbon.identity.oauth.dto.OAuthRevocationResponseDTO;
5557
import org.wso2.carbon.identity.oauth.dto.ScopeDTO;
5658
import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
59+
import org.wso2.carbon.identity.oauth.tokenprocessor.EncryptionDecryptionPersistenceProcessor;
60+
import org.wso2.carbon.identity.oauth.tokenprocessor.HashingPersistenceProcessor;
61+
import org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor;
62+
import org.wso2.carbon.identity.oauth.tokenprocessor.TokenPersistenceProcessor;
5763
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
5864
import org.wso2.carbon.identity.oauth2.TestConstants;
5965
import org.wso2.carbon.identity.oauth2.dao.AccessTokenDAO;
6066
import org.wso2.carbon.identity.oauth2.dao.AccessTokenDAOImpl;
67+
import org.wso2.carbon.identity.oauth2.dao.AuthorizationCodeDAO;
6168
import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
69+
import org.wso2.carbon.identity.oauth2.dao.TokenManagementDAO;
6270
import org.wso2.carbon.identity.oauth2.dao.TokenManagementDAOImpl;
6371
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
6472
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
@@ -98,6 +106,7 @@
98106
import static org.mockito.Mockito.lenient;
99107
import static org.mockito.Mockito.mock;
100108
import static org.mockito.Mockito.mockStatic;
109+
import static org.mockito.Mockito.never;
101110
import static org.mockito.Mockito.spy;
102111
import static org.mockito.Mockito.times;
103112
import static org.mockito.Mockito.verify;
@@ -116,6 +125,8 @@ public class OAuthAdminServiceImplTest {
116125
private static final String CONSUMER_SECRET = "consumer:secret";
117126
private static final String UPDATED_CONSUMER_SECRET = "updated:consumer:secret";
118127
private static final String INBOUND_AUTH2_TYPE = "oauth2";
128+
private static final String ACCESS_TOKEN = "access:token";
129+
private static final String USER_ID = "user:id";
119130

120131
@Mock
121132
private RealmConfiguration realmConfiguration;
@@ -141,6 +152,12 @@ public class OAuthAdminServiceImplTest {
141152
ServiceProvider mockServiceProvider;
142153
@Mock
143154
OAuthServerConfiguration mockOAuthServerConfiguration;
155+
@Mock
156+
AccessTokenDAO mockAccessTokenDAO;
157+
@Mock
158+
AuthorizationCodeDAO mockAuthorizationCodeDAO;
159+
@Mock
160+
TokenManagementDAO mockTokenManagementDAO;
144161

145162
private MockedStatic<IdentityTenantUtil> identityTenantUtil;
146163

@@ -757,6 +774,89 @@ public void testUpdateOauthSecretKeyWithException() throws Exception {
757774
}
758775
}
759776

777+
@DataProvider(name = "persistenceProcessorDataProvider")
778+
public Object[][] persistenceProcessorDataProvider() {
779+
780+
return new Object[][]{
781+
{new EncryptionDecryptionPersistenceProcessor(), false},
782+
{new EncryptionDecryptionPersistenceProcessor(), true},
783+
{new HashingPersistenceProcessor(), false},
784+
{new PlainTextPersistenceProcessor(), false}
785+
};
786+
}
787+
788+
@Test(dataProvider = "persistenceProcessorDataProvider")
789+
public void testClearTokenCacheForEachPersistenceProcessor(
790+
TokenPersistenceProcessor tokenPersistenceProcessor, boolean expectException) throws Exception {
791+
792+
try (MockedStatic<OAuthTokenPersistenceFactory> mockedOAuthTokenPersistenceFactory =
793+
mockStatic(OAuthTokenPersistenceFactory.class);
794+
MockedStatic<OAuth2Util> oAuth2Util = mockStatic(OAuth2Util.class);
795+
MockedStatic<CryptoUtil> mockedCryptoUtil = mockStatic(CryptoUtil.class);
796+
MockedStatic<IdentityUtil> identityUtil = mockStatic(IdentityUtil.class);
797+
MockedStatic<OAuthUtil> oAuthUtil = mockStatic(OAuthUtil.class)) {
798+
799+
Set<AccessTokenDO> activeTokens = getDetailedTokens();
800+
OAuthAdminServiceImpl oAuthAdminServiceImpl = new OAuthAdminServiceImpl();
801+
802+
OAuthTokenPersistenceFactory mockTokenPersistenceFactory = mock(OAuthTokenPersistenceFactory.class);
803+
mockedOAuthTokenPersistenceFactory.when(OAuthTokenPersistenceFactory::getInstance)
804+
.thenReturn(mockTokenPersistenceFactory);
805+
when(mockTokenPersistenceFactory.getAccessTokenDAO()).thenReturn(mockAccessTokenDAO);
806+
when(mockTokenPersistenceFactory.getAuthorizationCodeDAO()).thenReturn(mockAuthorizationCodeDAO);
807+
when(mockTokenPersistenceFactory.getTokenManagementDAO()).thenReturn(mockTokenManagementDAO);
808+
when(mockAccessTokenDAO.getActiveAcessTokenDataByConsumerKey(CONSUMER_KEY)).thenReturn(activeTokens);
809+
810+
CryptoUtil mockCryptoUtilInstance = mock(CryptoUtil.class);
811+
mockedCryptoUtil.when(CryptoUtil::getDefaultCryptoUtil).thenReturn(mockCryptoUtilInstance);
812+
oAuth2Util.when(OAuth2Util::getPersistenceProcessor).thenReturn(tokenPersistenceProcessor);
813+
814+
if (expectException) {
815+
when(mockCryptoUtilInstance.base64DecodeAndDecrypt(anyString())).thenThrow(new CryptoException());
816+
oAuthUtil.when(() -> OAuthUtil.handleError(anyString(), any(Exception.class)))
817+
.thenAnswer(invocation -> {
818+
String msg = invocation.getArgument(0);
819+
Exception ex = invocation.getArgument(1);
820+
return new IdentityOAuthAdminException(msg, ex);
821+
});
822+
try {
823+
oAuthAdminServiceImpl.updateAppAndRevokeTokensAndAuthzCodes(CONSUMER_KEY, new Properties());
824+
Assert.fail("Expected IdentityOAuthAdminException to be thrown.");
825+
} catch (IdentityOAuthAdminException e) {
826+
Assert.assertTrue(e.getMessage().contains(
827+
"Failed to retrieve the pre-processed access token for consumer key"));
828+
verify(mockCryptoUtilInstance, times(1)).base64DecodeAndDecrypt(anyString());
829+
}
830+
} else {
831+
byte[] mockDecryptedData = CONSUMER_KEY.getBytes();
832+
when(mockCryptoUtilInstance.base64DecodeAndDecrypt(anyString())).thenReturn(mockDecryptedData);
833+
oAuthAdminServiceImpl.updateAppAndRevokeTokensAndAuthzCodes(CONSUMER_KEY, new Properties());
834+
835+
if (tokenPersistenceProcessor instanceof EncryptionDecryptionPersistenceProcessor) {
836+
verify(mockCryptoUtilInstance, times(2)).base64DecodeAndDecrypt(anyString());
837+
} else {
838+
verify(mockCryptoUtilInstance, never()).base64DecodeAndDecrypt(anyString());
839+
}
840+
}
841+
}
842+
}
843+
844+
private static Set<AccessTokenDO> getDetailedTokens() {
845+
846+
Set<AccessTokenDO> activeDetailedTokens = new HashSet<>();
847+
AccessTokenDO accessTokenDO1 = new AccessTokenDO();
848+
AccessTokenDO accessTokenDO2 = new AccessTokenDO();
849+
accessTokenDO1.setAccessToken(ACCESS_TOKEN);
850+
accessTokenDO2.setAccessToken(ACCESS_TOKEN);
851+
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
852+
authenticatedUser.setUserId(USER_ID);
853+
accessTokenDO1.setAuthzUser(authenticatedUser);
854+
accessTokenDO2.setAuthzUser(authenticatedUser);
855+
activeDetailedTokens.add(accessTokenDO1);
856+
activeDetailedTokens.add(accessTokenDO2);
857+
return activeDetailedTokens;
858+
}
859+
760860
@Test
761861
public void testGetSupportedTokens() throws Exception {
762862

0 commit comments

Comments
 (0)