From 4e56039986b624e5c03d38c5454f28d816454d01 Mon Sep 17 00:00:00 2001 From: Madhavi Gayathri Date: Fri, 23 Aug 2024 15:40:18 +0530 Subject: [PATCH 1/3] Use application tenant domain to retrieve client app. --- .../validators/TokenValidationHandler.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java index ae0c6d9d0f..749f1a69f7 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java @@ -31,15 +31,13 @@ import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl; 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; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth.dto.OAuthConsumerAppDTO; -import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth.tokenprocessor.TokenProvider; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException; import org.wso2.carbon.identity.oauth2.OAuth2Constants; import org.wso2.carbon.identity.oauth2.authcontext.AuthorizationContextTokenGenerator; import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; @@ -575,7 +573,7 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation .isRemoveUsernameFromIntrospectionResponseForAppTokensEnabled(); boolean isAppTokenType = StringUtils.equals(OAuthConstants.UserType.APPLICATION, tokenType); boolean removeUsernameFromAppTokenEnabledAppConfig = - isOmitUsernameInIntrospectionRespForAppTokens(accessTokenDO, tenantDomain); + isOmitUsernameInIntrospectionRespForAppTokens(accessTokenDO); // should be in seconds introResp.setIat(accessTokenDO.getIssuedTime().getTime() / 1000); @@ -678,16 +676,23 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation return introResp; } - private static boolean isOmitUsernameInIntrospectionRespForAppTokens(AccessTokenDO accessTokenDO, - String tenantDomain) + private static boolean isOmitUsernameInIntrospectionRespForAppTokens(AccessTokenDO accessTokenDO) throws IdentityOAuth2Exception { - OAuthAdminServiceImpl oAuthAdminService = OAuthComponentServiceHolder.getInstance().getoAuthAdminService(); boolean omitUsernameInIntrospectionRespForAppTokens; try { - OAuthConsumerAppDTO oAuthApp = oAuthAdminService.getOAuthApplicationData(accessTokenDO.getConsumerKey(), - tenantDomain); - omitUsernameInIntrospectionRespForAppTokens = oAuthApp.isOmitUsernameInIntrospectionRespForAppTokens(); + String appResidentTenantDomain = null; + int appResidentTenantId = accessTokenDO.getAppResidentTenantId(); + if (appResidentTenantId != MultitenantConstants.INVALID_TENANT_ID) { + appResidentTenantDomain = IdentityTenantUtil.getTenantDomain(appResidentTenantId); + OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey(), + appResidentTenantDomain); + omitUsernameInIntrospectionRespForAppTokens = oAuthAppDO + .isOmitUsernameInIntrospectionRespForAppTokens(); + } else { + throw new IdentityOAuth2ServerException("Invalid tenant domain found in access token issue for" + + " client id: " + accessTokenDO.getConsumerKey()); + } } catch (Exception e) { throw new IdentityOAuth2Exception("Error occurred while retrieving OAuth2 application data for client id:" + accessTokenDO.getConsumerKey(), e); From 87dc56a1986bb4ef739118a26bb3c6339aaf8fea Mon Sep 17 00:00:00 2001 From: Madhavi Gayathri Date: Fri, 23 Aug 2024 16:46:55 +0530 Subject: [PATCH 2/3] Fix unit tests. --- .../validators/TokenValidationHandler.java | 4 +- .../TokenValidationHandlerTest.java | 73 ++++++++----------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java index 749f1a69f7..7581628f1f 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java @@ -687,8 +687,8 @@ private static boolean isOmitUsernameInIntrospectionRespForAppTokens(AccessToken appResidentTenantDomain = IdentityTenantUtil.getTenantDomain(appResidentTenantId); OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey(), appResidentTenantDomain); - omitUsernameInIntrospectionRespForAppTokens = oAuthAppDO - .isOmitUsernameInIntrospectionRespForAppTokens(); + omitUsernameInIntrospectionRespForAppTokens = Boolean.TRUE.equals(oAuthAppDO + .isOmitUsernameInIntrospectionRespForAppTokens()); } else { throw new IdentityOAuth2ServerException("Invalid tenant domain found in access token issue for" + " client id: " + accessTokenDO.getConsumerKey()); diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandlerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandlerTest.java index fb5b69cf90..97c74b7020 100644 --- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandlerTest.java +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandlerTest.java @@ -44,11 +44,9 @@ import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl; import org.wso2.carbon.identity.oauth.cache.AppInfoCache; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth.dto.OAuthConsumerAppDTO; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor; import org.wso2.carbon.identity.oauth.tokenprocessor.TokenProvider; @@ -142,12 +140,6 @@ public class TokenValidationHandlerTest { private IdentityProvider identityProvider; @Mock private FederatedAuthenticatorConfig federatedAuthenticatorConfig = new FederatedAuthenticatorConfig(); - @Mock - OAuthComponentServiceHolder mockOAuthComponentServiceHolder; - @Mock - OAuthConsumerAppDTO mockedOAuthConsumerAppDTO; - @Mock - OAuthAdminServiceImpl mockedOAuthAdminService; private MockedStatic loggerUtils; @BeforeMethod @@ -308,6 +300,7 @@ public void testBuildIntrospectionResponse(boolean isIDPIdColumnEnabled, String tokenBinding.setBindingReference("test_binding_reference"); tokenBinding.setBindingValue("R4Hj_0nNdIzVvPdCdsWlxNKm6a74cszp4Za4M1iE8P9"); accessTokenDO.setTokenBinding(tokenBinding); + accessTokenDO.setAppResidentTenantId(-1234); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain("carbon.super"); TokenProvider tokenProvider = Mockito.mock(TokenProvider.class); @@ -327,46 +320,38 @@ public void testBuildIntrospectionResponse(boolean isIDPIdColumnEnabled, String OAuthAppDO oAuthAppDO = new OAuthAppDO(); oAuthAppDO.setTokenType("Default"); oAuthAppDO.setApplicationName("testApp"); + oAuthAppDO.setOmitUsernameInIntrospectionRespForAppTokens(omitUsernameInIntrospectionRespAppConfig); AppInfoCache appInfoCache = AppInfoCache.getInstance(); appInfoCache.addToCache("testConsumerKey", oAuthAppDO); oAuth2TokenValidationRequestDTO.setAccessToken(accessToken); - try (MockedStatic oAuthComponentServiceHolder = - mockStatic(OAuthComponentServiceHolder.class)) { - when(OAuthComponentServiceHolder.getInstance()).thenReturn(mockOAuthComponentServiceHolder); - lenient().when(mockOAuthComponentServiceHolder.getoAuthAdminService()) - .thenReturn(mockedOAuthAdminService); - lenient().when(mockedOAuthAdminService.getOAuthApplicationData(anyString(), anyString())) - .thenReturn(mockedOAuthConsumerAppDTO); - lenient().when(mockedOAuthConsumerAppDTO.isOmitUsernameInIntrospectionRespForAppTokens()) - .thenReturn(omitUsernameInIntrospectionRespAppConfig); - - // Mock server level config value. - when(OAuthServerConfiguration.getInstance()).thenReturn(mockOAuthServerConfiguration); - lenient().when(mockOAuthServerConfiguration - .isRemoveUsernameFromIntrospectionResponseForAppTokensEnabled()) - .thenReturn(omitUsernameInIntrospectionRespServerConfig); - - oAuth2Util.when(OAuth2Util::getPersistenceProcessor) - .thenReturn(new PlainTextPersistenceProcessor()); - oAuth2Util.when(() -> OAuth2Util.getAppInformationByAccessTokenDO(any())).thenReturn(oAuthAppDO); - oAuth2Util.when(() -> OAuth2Util.getAccessTokenExpireMillis(any(), Mockito.anyBoolean())) - .thenReturn(1000L); - - OAuth2IntrospectionResponseDTO oAuth2IntrospectionResponseDTO = tokenValidationHandler - .buildIntrospectionResponse(oAuth2TokenValidationRequestDTO); - assertNotNull(oAuth2IntrospectionResponseDTO); - assertEquals(oAuth2IntrospectionResponseDTO.getBindingType(), - OAuth2Constants.TokenBinderType.CERTIFICATE_BASED_TOKEN_BINDER); - assertEquals(oAuth2IntrospectionResponseDTO.getBindingReference(), "test_binding_reference"); - assertEquals(oAuth2IntrospectionResponseDTO.getCnfBindingValue(), - "R4Hj_0nNdIzVvPdCdsWlxNKm6a74cszp4Za4M1iE8P9"); - if (omitUsernameInIntrospectionRespAppConfig && omitUsernameInIntrospectionRespServerConfig && - Objects.equals(tokenTypeData, "APPLICATION")) { - assertNull(oAuth2IntrospectionResponseDTO.getUsername()); - } else { - assertEquals(oAuth2IntrospectionResponseDTO.getUsername(), authzUser.getUserName()); - } + oAuth2Util.when(() -> OAuth2Util.getAppInformationByClientId(anyString(), anyString())) + .thenReturn(oAuthAppDO); + // Mock server level config value. + when(OAuthServerConfiguration.getInstance()).thenReturn(mockOAuthServerConfiguration); + lenient().when(mockOAuthServerConfiguration + .isRemoveUsernameFromIntrospectionResponseForAppTokensEnabled()) + .thenReturn(omitUsernameInIntrospectionRespServerConfig); + + oAuth2Util.when(OAuth2Util::getPersistenceProcessor) + .thenReturn(new PlainTextPersistenceProcessor()); + oAuth2Util.when(() -> OAuth2Util.getAppInformationByAccessTokenDO(any())).thenReturn(oAuthAppDO); + oAuth2Util.when(() -> OAuth2Util.getAccessTokenExpireMillis(any(), Mockito.anyBoolean())) + .thenReturn(1000L); + + OAuth2IntrospectionResponseDTO oAuth2IntrospectionResponseDTO = tokenValidationHandler + .buildIntrospectionResponse(oAuth2TokenValidationRequestDTO); + assertNotNull(oAuth2IntrospectionResponseDTO); + assertEquals(oAuth2IntrospectionResponseDTO.getBindingType(), + OAuth2Constants.TokenBinderType.CERTIFICATE_BASED_TOKEN_BINDER); + assertEquals(oAuth2IntrospectionResponseDTO.getBindingReference(), "test_binding_reference"); + assertEquals(oAuth2IntrospectionResponseDTO.getCnfBindingValue(), + "R4Hj_0nNdIzVvPdCdsWlxNKm6a74cszp4Za4M1iE8P9"); + if (omitUsernameInIntrospectionRespAppConfig && omitUsernameInIntrospectionRespServerConfig && + Objects.equals(tokenTypeData, "APPLICATION")) { + assertNull(oAuth2IntrospectionResponseDTO.getUsername()); + } else { + assertEquals(oAuth2IntrospectionResponseDTO.getUsername(), authzUser.getUserName()); } } } From 1b2aa8c9912646da087514626067bb7e4cb17921 Mon Sep 17 00:00:00 2001 From: Madhavi Gayathri Date: Sat, 24 Aug 2024 01:50:20 +0530 Subject: [PATCH 3/3] Handle invalid app tenant with user tenant. --- .../validators/TokenValidationHandler.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java index 7581628f1f..83077bfa35 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/TokenValidationHandler.java @@ -37,7 +37,6 @@ import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.oauth.tokenprocessor.TokenProvider; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException; import org.wso2.carbon.identity.oauth2.OAuth2Constants; import org.wso2.carbon.identity.oauth2.authcontext.AuthorizationContextTokenGenerator; import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; @@ -573,7 +572,7 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation .isRemoveUsernameFromIntrospectionResponseForAppTokensEnabled(); boolean isAppTokenType = StringUtils.equals(OAuthConstants.UserType.APPLICATION, tokenType); boolean removeUsernameFromAppTokenEnabledAppConfig = - isOmitUsernameInIntrospectionRespForAppTokens(accessTokenDO); + isOmitUsernameInIntrospectionRespForAppTokens(accessTokenDO, tenantDomain); // should be in seconds introResp.setIat(accessTokenDO.getIssuedTime().getTime() / 1000); @@ -676,28 +675,24 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation return introResp; } - private static boolean isOmitUsernameInIntrospectionRespForAppTokens(AccessTokenDO accessTokenDO) + private static boolean isOmitUsernameInIntrospectionRespForAppTokens(AccessTokenDO accessTokenDO, + String tenantDomain) throws IdentityOAuth2Exception { - boolean omitUsernameInIntrospectionRespForAppTokens; try { - String appResidentTenantDomain = null; int appResidentTenantId = accessTokenDO.getAppResidentTenantId(); if (appResidentTenantId != MultitenantConstants.INVALID_TENANT_ID) { - appResidentTenantDomain = IdentityTenantUtil.getTenantDomain(appResidentTenantId); - OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey(), - appResidentTenantDomain); - omitUsernameInIntrospectionRespForAppTokens = Boolean.TRUE.equals(oAuthAppDO - .isOmitUsernameInIntrospectionRespForAppTokens()); - } else { - throw new IdentityOAuth2ServerException("Invalid tenant domain found in access token issue for" - + " client id: " + accessTokenDO.getConsumerKey()); + tenantDomain = IdentityTenantUtil.getTenantDomain(appResidentTenantId); } + OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(accessTokenDO.getConsumerKey(), + tenantDomain); + + return Boolean.TRUE.equals(oAuthAppDO.isOmitUsernameInIntrospectionRespForAppTokens()); + } catch (Exception e) { throw new IdentityOAuth2Exception("Error occurred while retrieving OAuth2 application data for client id:" + accessTokenDO.getConsumerKey(), e); } - return omitUsernameInIntrospectionRespForAppTokens; } private String getAuthzUser(AccessTokenDO accessTokenDO) throws IdentityOAuth2Exception {