diff --git a/components/org.wso2.carbon.identity.api.server.dcr/pom.xml b/components/org.wso2.carbon.identity.api.server.dcr/pom.xml index 70a01bd8b76..3c0eb922778 100644 --- a/components/org.wso2.carbon.identity.api.server.dcr/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.dcr/pom.xml @@ -23,12 +23,12 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../../pom.xml org.wso2.carbon.identity.api.server.dcr - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT WSO2 Carbon - User DCR Rest API WSO2 Carbon - User DCR Rest API diff --git a/components/org.wso2.carbon.identity.api.server.oauth.scope/pom.xml b/components/org.wso2.carbon.identity.api.server.oauth.scope/pom.xml index a7a7136e9ba..d6780dfc826 100644 --- a/components/org.wso2.carbon.identity.api.server.oauth.scope/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.oauth.scope/pom.xml @@ -23,12 +23,12 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../.. org.wso2.carbon.identity.api.server.oauth.scope - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT WSO2 Carbon - Identity OAuth 2.0 Scope Rest APIs Rest APIs for OAuth 2.0 Scope Handling diff --git a/components/org.wso2.carbon.identity.client.attestation.filter/pom.xml b/components/org.wso2.carbon.identity.client.attestation.filter/pom.xml index cab9f0f474c..ff3dfa37ff8 100644 --- a/components/org.wso2.carbon.identity.client.attestation.filter/pom.xml +++ b/components/org.wso2.carbon.identity.client.attestation.filter/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml index f74ac89c8ed..a356be41fbf 100644 --- a/components/org.wso2.carbon.identity.discovery/pom.xml +++ b/components/org.wso2.carbon.identity.discovery/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.ciba/pom.xml b/components/org.wso2.carbon.identity.oauth.ciba/pom.xml index 6dfcf4459d9..ce0183489fb 100644 --- a/components/org.wso2.carbon.identity.oauth.ciba/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.ciba/pom.xml @@ -20,7 +20,7 @@ identity-inbound-auth-oauth org.wso2.carbon.identity.inbound.auth.oauth2 - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.oauth.client.authn.filter/pom.xml b/components/org.wso2.carbon.identity.oauth.client.authn.filter/pom.xml index 401416ce19c..3435c8c572f 100644 --- a/components/org.wso2.carbon.identity.oauth.client.authn.filter/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.client.authn.filter/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.common/pom.xml b/components/org.wso2.carbon.identity.oauth.common/pom.xml index b99ba570b3f..dc75c53f52c 100644 --- a/components/org.wso2.carbon.identity.oauth.common/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.common/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java b/components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java index 2984f0bd82d..7ee3e18fa16 100644 --- a/components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java +++ b/components/org.wso2.carbon.identity.oauth.common/src/main/java/org/wso2/carbon/identity/oauth/common/OAuthConstants.java @@ -643,8 +643,6 @@ public static class OIDCConfigProperties { public static final String IS_SUBJECT_TOKEN_ENABLED = "isSubjectTokenEnabled"; public static final String SUBJECT_TOKEN_EXPIRY_TIME = "subjectTokenExpiryTime"; public static final int SUBJECT_TOKEN_EXPIRY_TIME_VALUE = 180; - public static final String IS_ACCESS_TOKEN_CLAIMS_SEPARATION_ENABLED = - "isAccessTokenClaimsSeparationEnabled"; public static final String PREVENT_TOKEN_REUSE = "PreventTokenReuse"; public static final boolean DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE = true; // Name of the {@code JWTClientAuthenticatorConfig} resource type in the Configuration Management API. diff --git a/components/org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml index a81156df286..b263c7d1dc0 100644 --- a/components/org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml @@ -6,7 +6,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.dcr/pom.xml b/components/org.wso2.carbon.identity.oauth.dcr/pom.xml index e4ba42821ec..dec9f22a22f 100644 --- a/components/org.wso2.carbon.identity.oauth.dcr/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.dcr/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml index 4d1a3f134e8..5cd7f776458 100644 --- a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.extension/pom.xml b/components/org.wso2.carbon.identity.oauth.extension/pom.xml index e096d1cffaa..7a113ef31f8 100644 --- a/components/org.wso2.carbon.identity.oauth.extension/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.extension/pom.xml @@ -19,7 +19,7 @@ identity-inbound-auth-oauth org.wso2.carbon.identity.inbound.auth.oauth2 - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.par/pom.xml b/components/org.wso2.carbon.identity.oauth.par/pom.xml index fffff4ec316..923fa0291a5 100644 --- a/components/org.wso2.carbon.identity.oauth.par/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.par/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml index c5b7d4a77b9..9fe29c50961 100644 --- a/components/org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.stub/pom.xml b/components/org.wso2.carbon.identity.oauth.stub/pom.xml index e5ed87247b2..6e8223f38c0 100644 --- a/components/org.wso2.carbon.identity.oauth.stub/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.stub/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth.stub/src/main/resources/OAuthAdminService.wsdl b/components/org.wso2.carbon.identity.oauth.stub/src/main/resources/OAuthAdminService.wsdl index 60767786e08..89f6009d954 100755 --- a/components/org.wso2.carbon.identity.oauth.stub/src/main/resources/OAuthAdminService.wsdl +++ b/components/org.wso2.carbon.identity.oauth.stub/src/main/resources/OAuthAdminService.wsdl @@ -395,7 +395,6 @@ - diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml index 39a1dbde62b..ef501192029 100644 --- a/components/org.wso2.carbon.identity.oauth.ui/pom.xml +++ b/components/org.wso2.carbon.identity.oauth.ui/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml index 0986688ea5e..3a2cb073b16 100644 --- a/components/org.wso2.carbon.identity.oauth/pom.xml +++ b/components/org.wso2.carbon.identity.oauth/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImpl.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImpl.java index 578bb3213a4..8e948585549 100755 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImpl.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImpl.java @@ -234,7 +234,7 @@ public OAuthConsumerAppDTO getOAuthApplicationData(String consumerKey, String te OAuthAppDO app = getOAuthApp(consumerKey, tenantDomain); if (app != null) { if (isAccessTokenClaimsSeparationFeatureEnabled() && - !app.isAccessTokenClaimsSeparationEnabled()) { + !isAccessTokenClaimsSeparationEnabledForApp(consumerKey, tenantDomain)) { // Add requested claims as access token claims if the app is not in the new access token // claims feature. addAccessTokenClaims(app, tenantDomain); @@ -538,7 +538,6 @@ OAuthConsumerAppDTO registerAndRetrieveOAuthApplicationData(OAuthConsumerAppDTO if (isAccessTokenClaimsSeparationFeatureEnabled()) { validateAccessTokenClaims(application, tenantDomain); app.setAccessTokenClaims(application.getAccessTokenClaims()); - app.setAccessTokenClaimsSeparationEnabled(true); } } dao.addOAuthApplication(app); @@ -979,27 +978,32 @@ void updateConsumerApplication(OAuthConsumerAppDTO consumerAppDTO, boolean enabl if (isAccessTokenClaimsSeparationFeatureEnabled()) { // We check if the AT claims separation enabled at server level and // the app level. If both are enabled, we validate the claims and update the app. - if (oAuthAppDO.isAccessTokenClaimsSeparationEnabled()) { - validateAccessTokenClaims(consumerAppDTO, tenantDomain); - oAuthAppDO.setAccessTokenClaims(consumerAppDTO.getAccessTokenClaims()); + try { + if (isAccessTokenClaimsSeparationEnabledForApp(oAuthAppDO.getOauthConsumerKey(), tenantDomain)) { + validateAccessTokenClaims(consumerAppDTO, tenantDomain); + oAuthAppDO.setAccessTokenClaims(consumerAppDTO.getAccessTokenClaims()); + } + } catch (IdentityOAuth2Exception e) { + throw new IdentityOAuthAdminException("Error while updating existing OAuth application to " + + "the new JWT access token OIDC claims separation model. Application : " + + oAuthAppDO.getApplicationName() + " Tenant : " + tenantDomain, e); } // We only trigger the access token claims migration if the following conditions are met. // 1. The AT claims separation is enabled at server level. // 2. The AT claims separation is not enabled at app level. - // 3. User tries to enable AT claims separation at app level with update app. - if (!oAuthAppDO.isAccessTokenClaimsSeparationEnabled() && - consumerAppDTO.isAccessTokenClaimsSeparationEnabled()) { - // Add requested claims as access token claims. - try { + // 3. The access token claims are empty. + try { + if (!isAccessTokenClaimsSeparationEnabledForApp(oAuthAppDO.getOauthConsumerKey(), + tenantDomain) && oAuthAppDO.getAccessTokenClaims().length == 0) { + // Add requested claims as access token claims. addAccessTokenClaims(oAuthAppDO, tenantDomain); - } catch (IdentityOAuth2Exception e) { - throw new IdentityOAuthAdminException("Error while updating existing OAuth application to " + - "the new JWT access token OIDC claims separation model. Application : " + - oAuthAppDO.getApplicationName() + " Tenant : " + tenantDomain, e); } + + } catch (IdentityOAuth2Exception e) { + throw new IdentityOAuthAdminException("Error while updating existing OAuth application to " + + "the new JWT access token OIDC claims separation model. Application : " + + oAuthAppDO.getApplicationName() + " Tenant : " + tenantDomain, e); } - oAuthAppDO.setAccessTokenClaimsSeparationEnabled(consumerAppDTO - .isAccessTokenClaimsSeparationEnabled()); } } dao.updateConsumerApplication(oAuthAppDO); @@ -2898,4 +2902,12 @@ private boolean isAccessTokenClaimsSeparationFeatureEnabled() { return Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN)); } + + private boolean isAccessTokenClaimsSeparationEnabledForApp(String consumerKey, String tenantDomain) + throws IdentityOAuth2Exception { + + ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(consumerKey, tenantDomain); + return OAuth2Util.isAppVersionAllowed(serviceProvider.getApplicationVersion(), + ApplicationConstants.ApplicationVersion.APP_VERSION_V2); + } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthUtil.java index 521d1300c4a..4cf88072dcf 100755 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthUtil.java @@ -94,6 +94,7 @@ import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.CURRENT_SESSION_IDENTIFIER; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.CURRENT_TOKEN_IDENTIFIER; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.PRESERVE_LOGGED_IN_SESSION_AT_PASSWORD_UPDATE; +import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.OAUTH2; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ORGANIZATION_LOGIN_HOME_REALM_IDENTIFIER; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.ENABLE_TOKEN_REUSE; @@ -562,7 +563,6 @@ public static OAuthConsumerAppDTO buildConsumerAppDTO(OAuthAppDO appDO) { dto.setSubjectTokenEnabled(appDO.isSubjectTokenEnabled()); dto.setSubjectTokenExpiryTime(appDO.getSubjectTokenExpiryTime()); dto.setAccessTokenClaims(appDO.getAccessTokenClaims()); - dto.setAccessTokenClaimsSeparationEnabled(appDO.isAccessTokenClaimsSeparationEnabled()); return dto; } @@ -822,6 +822,27 @@ private static Set getClientIdsOfAssociatedApplications(Role role, Authe return clientIds; } + private static Set filterClientIdsWithOrganizationAudience(List clientIds, String tenantDomain) { + + Set clientIdsWithOrganizationAudience = new HashSet<>(); + ApplicationManagementService applicationManagementService = + OAuthComponentServiceHolder.getInstance().getApplicationManagementService(); + for (String clientId : clientIds) { + try { + String applicationId = applicationManagementService.getApplicationResourceIDByInboundKey(clientId, + OAUTH2, tenantDomain); + String audience = applicationManagementService.getAllowedAudienceForRoleAssociation(applicationId, + tenantDomain); + if (RoleConstants.ORGANIZATION.equalsIgnoreCase(audience)) { + clientIdsWithOrganizationAudience.add(clientId); + } + } catch (IdentityApplicationManagementException e) { + LOG.error("Error occurred while retrieving application information for client id: " + clientId, e); + } + } + return clientIdsWithOrganizationAudience; + } + /** * This method will retrieve the role details of the given role id. * @param roleId Role Id. @@ -991,7 +1012,7 @@ public static boolean revokeTokens(String username, UserStoreManager userStoreMa // Get details about the role to identify the audience and associated applications. Set clientIds = null; - Role role; + Role role = null; boolean getClientIdsFromUser = false; if (roleId != null) { role = getRole(roleId, IdentityTenantUtil.getTenantDomain(userStoreManager.getTenantId())); @@ -1009,6 +1030,7 @@ public static boolean revokeTokens(String username, UserStoreManager userStoreMa "an organization role: " + role.getName()); } getClientIdsFromUser = true; + } } else { // Get all the distinct client Ids authorized by this user since no role is specified. @@ -1022,7 +1044,12 @@ public static boolean revokeTokens(String username, UserStoreManager userStoreMa } try { clientIds = OAuthTokenPersistenceFactory.getInstance() - .getTokenManagementDAO().getAllTimeAuthorizedClientIds(authenticatedUser); + .getTokenManagementDAO().getAllTimeAuthorizedClientIds(authenticatedUser); + + if (role != null && RoleConstants.ORGANIZATION.equals(role.getAudience())) { + clientIds = filterClientIdsWithOrganizationAudience(new ArrayList<>(clientIds), tenantDomain); + } + } catch (IdentityOAuth2Exception e) { LOG.error("Error occurred while retrieving apps authorized by User ID : " + authenticatedUser, e); throw new UserStoreException(e); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilder.java old mode 100644 new mode 100755 diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenResponseProcessor.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenResponseProcessor.java index c174599c8c6..f56fa00b26b 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenResponseProcessor.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenResponseProcessor.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.action.execution.ActionExecutionLogConstants; import org.wso2.carbon.identity.action.execution.ActionExecutionResponseProcessor; import org.wso2.carbon.identity.action.execution.exception.ActionExecutionResponseProcessorException; import org.wso2.carbon.identity.action.execution.model.ActionExecutionStatus; @@ -31,11 +32,13 @@ import org.wso2.carbon.identity.action.execution.model.ActionType; import org.wso2.carbon.identity.action.execution.model.Event; import org.wso2.carbon.identity.action.execution.model.PerformableOperation; +import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; import org.wso2.carbon.identity.oauth.action.model.AccessToken; import org.wso2.carbon.identity.oauth.action.model.ClaimPathInfo; import org.wso2.carbon.identity.oauth.action.model.OperationExecutionResult; import org.wso2.carbon.identity.oauth.action.model.PreIssueAccessTokenEvent; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; +import org.wso2.carbon.utils.DiagnosticLog; import java.util.ArrayList; import java.util.Collections; @@ -113,7 +116,29 @@ public ActionExecutionStatus processSuccessResponse(Map eventCon private void logOperationExecutionResults(ActionType actionType, List operationExecutionResultList) { - //todo: need to add to diagnostic logs + if (LoggerUtils.isDiagnosticLogsEnabled()) { + + List> operationDetailsList = new ArrayList<>(); + operationExecutionResultList.forEach(performedOperation -> { + operationDetailsList.add(Map.of( + "operation", performedOperation.getOperation().getOp() + " path: " + + performedOperation.getOperation().getPath(), + "status", performedOperation.getStatus().toString(), + "message", performedOperation.getMessage() + )); + }); + + DiagnosticLog.DiagnosticLogBuilder diagLogBuilder = new DiagnosticLog.DiagnosticLogBuilder( + ActionExecutionLogConstants.ACTION_EXECUTION_COMPONENT_ID, + ActionExecutionLogConstants.ActionIDs.EXECUTE_ACTION_OPERATIONS); + diagLogBuilder + .inputParam("executed operations", operationDetailsList.isEmpty() ? "empty" : operationDetailsList) + .resultMessage("Allowed operations are executed for " + actionType.getDisplayName() + " action.") + .logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION) + .resultStatus(DiagnosticLog.ResultStatus.SUCCESS) + .build(); + LoggerUtils.triggerDiagnosticLogEvent(diagLogBuilder); + } if (LOG.isDebugEnabled()) { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java index f11815a74a4..bfd3b2b64a0 100755 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java @@ -85,7 +85,6 @@ import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.ID_TOKEN_ENCRYPTION_ALGORITHM; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.ID_TOKEN_ENCRYPTION_METHOD; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.ID_TOKEN_SIGNATURE_ALGORITHM; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.IS_ACCESS_TOKEN_CLAIMS_SEPARATION_ENABLED; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.IS_CERTIFICATE_BOUND_ACCESS_TOKEN; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.IS_FAPI_CONFORMANT_APP; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.IS_PUSH_AUTH; @@ -1044,13 +1043,6 @@ private void addOrUpdateOIDCSpProperty(OAuthAppDO oauthAppDO, SUBJECT_TOKEN_EXPIRY_TIME, String.valueOf(oauthAppDO.getSubjectTokenExpiryTime()), prepStatementForPropertyAdd, preparedStatementForPropertyUpdate); - if (isAccessTokenClaimsSeparationFeatureEnabled()) { - addOrUpdateOIDCSpProperty(preprocessedClientId, spTenantId, spOIDCProperties, - IS_ACCESS_TOKEN_CLAIMS_SEPARATION_ENABLED, - String.valueOf(oauthAppDO.isAccessTokenClaimsSeparationEnabled()), - prepStatementForPropertyAdd, preparedStatementForPropertyUpdate); - } - addOrUpdateOIDCSpProperty(preprocessedClientId, spTenantId, spOIDCProperties, HYBRID_FLOW_ENABLED, String.valueOf(oauthAppDO.isHybridFlowEnabled()), prepStatementForPropertyAdd, preparedStatementForPropertyUpdate); @@ -1779,12 +1771,6 @@ private void addServiceProviderOIDCProperties(Connection connection, addToBatchForOIDCPropertyAdd(processedClientId, spTenantId, prepStmtAddOIDCProperty, SUBJECT_TOKEN_EXPIRY_TIME, String.valueOf(consumerAppDO.getSubjectTokenExpiryTime())); - if (isAccessTokenClaimsSeparationFeatureEnabled()) { - addToBatchForOIDCPropertyAdd(processedClientId, spTenantId, prepStmtAddOIDCProperty, - IS_ACCESS_TOKEN_CLAIMS_SEPARATION_ENABLED, - String.valueOf(consumerAppDO.isAccessTokenClaimsSeparationEnabled())); - } - addToBatchForOIDCPropertyAdd(processedClientId, spTenantId, prepStmtAddOIDCProperty, HYBRID_FLOW_ENABLED, String.valueOf(consumerAppDO.isHybridFlowEnabled())); @@ -1965,13 +1951,6 @@ private void setSpOIDCProperties(Map> spOIDCProperties, OAu oauthApp.setSubjectTokenExpiryTime(Integer.parseInt(subjectTokenExpiryTime)); } - String isAccessTokenClaimsSeparationEnabled = getFirstPropertyValue(spOIDCProperties, - IS_ACCESS_TOKEN_CLAIMS_SEPARATION_ENABLED); - if (isAccessTokenClaimsSeparationEnabled != null) { - oauthApp.setAccessTokenClaimsSeparationEnabled( - Boolean.parseBoolean(isAccessTokenClaimsSeparationEnabled)); - } - boolean hybridFlowEnabled = Boolean.parseBoolean(getFirstPropertyValue(spOIDCProperties, HYBRID_FLOW_ENABLED)); oauthApp.setHybridFlowEnabled(hybridFlowEnabled); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDO.java index 773c8b484f0..1d676bee02d 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDO.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDO.java @@ -96,7 +96,6 @@ public class OAuthAppDO extends InboundConfigurationProtocol implements Serializ private boolean subjectTokenEnabled; private int subjectTokenExpiryTime; private String[] accessTokenClaims; - private boolean accessTokenClaimsSeparationEnabled; public AuthenticatedUser getAppOwner() { @@ -535,14 +534,4 @@ public void setAccessTokenClaims(String[] accessTokenClaims) { this.accessTokenClaims = accessTokenClaims; } - - public boolean isAccessTokenClaimsSeparationEnabled() { - - return accessTokenClaimsSeparationEnabled; - } - - public void setAccessTokenClaimsSeparationEnabled(boolean accessTokenClaimsSeparationEnabled) { - - this.accessTokenClaimsSeparationEnabled = accessTokenClaimsSeparationEnabled; - } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dto/OAuthConsumerAppDTO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dto/OAuthConsumerAppDTO.java index fb4e4f2d795..4784b822ad1 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dto/OAuthConsumerAppDTO.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dto/OAuthConsumerAppDTO.java @@ -81,7 +81,6 @@ public class OAuthConsumerAppDTO implements InboundProtocolConfigurationDTO { private boolean subjectTokenEnabled; private int subjectTokenExpiryTime; private String[] accessTokenClaims; - private boolean accessTokenClaimsSeparationEnabled; // CORS origin related properties. This will be used by the CORS management service @IgnoreNullElement @@ -540,15 +539,5 @@ public void setAccessTokenClaims(String[] accessTokenClaims) { this.accessTokenClaims = accessTokenClaims; } - - public boolean isAccessTokenClaimsSeparationEnabled() { - - return accessTokenClaimsSeparationEnabled; - } - - public void setAccessTokenClaimsSeparationEnabled(boolean accessTokenClaimsSeparationEnabled) { - - this.accessTokenClaimsSeparationEnabled = accessTokenClaimsSeparationEnabled; - } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/errorcodes/DeviceErrorCodes.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/errorcodes/DeviceErrorCodes.java index 277e1a92c93..64180640fa4 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/errorcodes/DeviceErrorCodes.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/errorcodes/DeviceErrorCodes.java @@ -50,6 +50,7 @@ public static class SubDeviceErrorCodesDescriptions { public static final String SLOW_DOWN = "Forbidden"; public static final String AUTHORIZATION_PENDING = "Precondition required"; public static final String EXPIRED_TOKEN = "Forbidden"; + public static final String NOT_EXIST = "The provided device code is not registered or is invalid."; } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/grant/DeviceFlowGrant.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/grant/DeviceFlowGrant.java index 4d780bf57e2..c1439c4c747 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/grant/DeviceFlowGrant.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/device/grant/DeviceFlowGrant.java @@ -100,7 +100,8 @@ private void handleInvalidRequests(String deviceStatus, DeviceFlowDO deviceFlowD Date date = new Date(); if (Constants.NOT_EXIST.equals(deviceStatus)) { - throw new IdentityOAuth2Exception(DeviceErrorCodes.INVALID_REQUEST, DeviceErrorCodes.INVALID_REQUEST); + throw new IdentityOAuth2Exception(DeviceErrorCodes.INVALID_REQUEST, + DeviceErrorCodes.SubDeviceErrorCodesDescriptions.NOT_EXIST); } else if (Constants.EXPIRED.equals(deviceStatus) || isExpiredDeviceCode(deviceFlowDO, date)) { throw new IdentityOAuth2Exception(DeviceErrorCodes.SubDeviceErrorCodes.EXPIRED_TOKEN, DeviceErrorCodes.SubDeviceErrorCodesDescriptions.EXPIRED_TOKEN); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java index c77aa705989..16f539f4ec4 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java @@ -34,6 +34,7 @@ import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty; import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.base.IdentityConstants; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.central.log.mgt.utils.LogConstants; @@ -459,8 +460,9 @@ private OAuth2AccessTokenRespDTO validateGrantAndIssueToken(OAuth2AccessTokenReq ServiceProvider serviceProvider = getServiceProvider(tokReqMsgCtx.getOauth2AccessTokenReqDTO()); boolean useClientIdAsSubClaimForAppTokensEnabledServerConfig = OAuthServerConfiguration.getInstance() .isUseClientIdAsSubClaimForAppTokensEnabled(); - boolean useClientIdAsSubClaimForAppTokensEnabled = OAuth2Util - .isAllowedToStopUsingAppOwnerForTokenIdentification(serviceProvider.getApplicationVersion()); + boolean useClientIdAsSubClaimForAppTokensEnabled = + OAuth2Util.isAppVersionAllowed(serviceProvider.getApplicationVersion(), + ApplicationConstants.ApplicationVersion.APP_VERSION_V1); if (authorizedUser.getAuthenticatedSubjectIdentifier() == null) { if ((!isOfTypeApplicationUser && (useClientIdAsSubClaimForAppTokensEnabled || useClientIdAsSubClaimForAppTokensEnabledServerConfig))) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java index 5e26cd61be8..08982d55aa5 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java @@ -396,8 +396,6 @@ public class OAuth2Util { ApplicationConstants.MY_ACCOUNT_APPLICATION_CLIENT_ID, ApplicationConstants.CONSOLE_APPLICATION_CLIENT_ID); - public static final String ALLOWED_VERSION_TO_STOP_USING_APP_OWNER_FOR_TOKEN_IDENTIFICATION = "v1.0.0"; - private OAuth2Util() { } @@ -5645,16 +5643,15 @@ public static boolean isPairwiseSubEnabledForAccessTokens() { } /** - * Compare the app version with allowed minimum version. + * Compare the app version with allowed minimum app version. * * @param appVersion App version. - * @return True if the app version is greater than or equal to the allowed minimum version. + * @return True if the app version is greater than or equal to the allowed minimum app version. */ - public static boolean isAllowedToStopUsingAppOwnerForTokenIdentification(String appVersion) { + public static boolean isAppVersionAllowed(String appVersion, String allowedAppVersion) { String[] appVersionDigits = appVersion.substring(1).split("\\."); - String[] allowedVersionDigits = ALLOWED_VERSION_TO_STOP_USING_APP_OWNER_FOR_TOKEN_IDENTIFICATION.substring(1) - .split("\\."); + String[] allowedVersionDigits = allowedAppVersion.substring(1).split("\\."); for (int i = 0; i < appVersionDigits.length; i++) { if (appVersionDigits[i].equals(allowedVersionDigits[i])) { 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 1915185e210..fabb785dbba 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 @@ -27,6 +27,7 @@ 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; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.central.log.mgt.utils.LogConstants; import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; @@ -578,7 +579,8 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation String consumerKey = accessTokenDO.getConsumerKey(); ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(consumerKey, appResidentTenantDomain); boolean removeUsernameFromAppTokenEnabled = OAuth2Util - .isAllowedToStopUsingAppOwnerForTokenIdentification(serviceProvider.getApplicationVersion()); + .isAppVersionAllowed(serviceProvider.getApplicationVersion(), + ApplicationConstants.ApplicationVersion.APP_VERSION_V1); boolean isAppTokenType = StringUtils.equals(OAuthConstants.UserType.APPLICATION, tokenType); // should be in seconds diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtil.java index 04285362668..2f2eab51d09 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtil.java @@ -18,9 +18,14 @@ package org.wso2.carbon.identity.openidconnect.util; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.oauth2.util.OAuth2Util; import org.wso2.carbon.identity.openidconnect.CustomClaimsCallbackHandler; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN; @@ -30,11 +35,21 @@ */ public class ClaimHandlerUtil { - public static CustomClaimsCallbackHandler getClaimsCallbackHandler(OAuthAppDO oAuthAppDO) { + /** + * Get the claims callback handler based on the application configuration. + * + * @param oAuthAppDO OAuth application data object. + * @return CustomClaimsCallbackHandler. + */ + public static CustomClaimsCallbackHandler getClaimsCallbackHandler(OAuthAppDO oAuthAppDO) + throws IdentityOAuth2Exception { // If JWT access token OIDC claims separation is enabled and the application is configured to separate OIDC // claims, use the JWTAccessTokenOIDCClaimsHandler to handle custom claims. - if (isAccessTokenClaimsSeparationFeatureEnabled() && oAuthAppDO.isAccessTokenClaimsSeparationEnabled()) { + int appTenantId = IdentityTenantUtil.getLoginTenantId(); + String tenantDomain = IdentityTenantUtil.getTenantDomain(appTenantId); + if (isAccessTokenClaimsSeparationFeatureEnabled() && + isAccessTokenClaimsSeparationEnabledForApp(oAuthAppDO, tenantDomain)) { return OAuthServerConfiguration.getInstance().getJWTAccessTokenOIDCClaimsHandler(); } return OAuthServerConfiguration.getInstance().getOpenIDConnectCustomClaimsCallbackHandler(); @@ -44,4 +59,13 @@ private static boolean isAccessTokenClaimsSeparationFeatureEnabled() { return Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN)); } + + private static boolean isAccessTokenClaimsSeparationEnabledForApp(OAuthAppDO oAuthAppDO, String tenantDomain) + throws IdentityOAuth2Exception { + + ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(oAuthAppDO.getOauthConsumerKey(), tenantDomain); + String appVersion = serviceProvider.getApplicationVersion(); + + return OAuth2Util.isAppVersionAllowed(appVersion, ApplicationConstants.ApplicationVersion.APP_VERSION_V2); + } } diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImplTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImplTest.java index 9a9907c4738..0aa49b363f1 100755 --- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImplTest.java +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/OAuthAdminServiceImplTest.java @@ -35,6 +35,7 @@ import org.testng.annotations.Test; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException; @@ -45,6 +46,7 @@ import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; 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.OAuthAppDAO; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.oauth.dto.OAuthAppRevocationRequestDTO; @@ -61,6 +63,7 @@ import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; import org.wso2.carbon.identity.openidconnect.dao.ScopeClaimMappingDAO; +import org.wso2.carbon.identity.oauth2.util.OAuth2Util; import org.wso2.carbon.user.api.RealmConfiguration; import org.wso2.carbon.user.api.Tenant; import org.wso2.carbon.user.api.UserRealm; @@ -92,6 +95,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.spy; @@ -103,6 +107,7 @@ import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDC_DIALECT; import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_ID; +import static org.wso2.carbon.identity.oauth.common.OAuthConstants.ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN; public class OAuthAdminServiceImplTest { @@ -131,9 +136,10 @@ public class OAuthAdminServiceImplTest { AbstractUserStoreManager mockAbstractUserStoreManager; @Mock OAuthComponentServiceHolder mockOAuthComponentServiceHolder; - @Mock - ObjectMapper objectMapper; + ServiceProvider mockServiceProvider; + @Mock + OAuthServerConfiguration mockOAuthServerConfiguration; private MockedStatic identityTenantUtil; @@ -346,23 +352,65 @@ public void testGetAllOAuthApplicationDataException() throws Exception { } } - @Test - public void testGetOAuthApplicationData() throws Exception { + @DataProvider(name = "setAccessTokenClaims") + public Object[][] getOAuthApplicationData() { - String consumerKey = "some-consumer-key"; - Mockito.when(tenantManager.getTenantId(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) - .thenReturn(MultitenantConstants.SUPER_TENANT_ID); + return new Object[][] { + { "v0.0.0", true }, + { "v1.0.0", true }, + { "v2.0.0", true }, + { "v0.0.0", false }, + { "v1.0.0", false }, + { "v2.0.0", false } + }; + } - OAuthAppDO app = buildDummyOAuthAppDO("some-user-name"); - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(OAuthAppDAO.class, - (mock, context) -> { - when(mock.getAppInformation(consumerKey, MultitenantConstants.SUPER_TENANT_ID)).thenReturn(app); - })) { + @Test(dataProvider = "setAccessTokenClaims") + public void testGetOAuthApplicationData(String appVersion, boolean claimSeparationFeatureEnabled) throws Exception { - OAuthAdminServiceImpl oAuthAdminServiceImpl = new OAuthAdminServiceImpl(); - OAuthConsumerAppDTO oAuthConsumerApp = oAuthAdminServiceImpl.getOAuthApplicationData(consumerKey, - MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); - assertAllAttributesOfConsumerAppDTO(oAuthConsumerApp, app); + try (MockedStatic oAuthServerConfigurationMockedStatic = mockStatic( + OAuthServerConfiguration.class);) { + // Mock and initialize the OAuthServerConfiguration. + mockOAuthServerConfiguration = mock(OAuthServerConfiguration.class); + oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance) + .thenReturn(mockOAuthServerConfiguration); + lenient().when(mockOAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(300L); + + try (MockedStatic identityUtil = mockStatic(IdentityUtil.class); + MockedStatic oAuth2Util = mockStatic(OAuth2Util.class);) { + + String consumerKey = "some-consumer-key"; + Mockito.when(tenantManager.getTenantId(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) + .thenReturn(MultitenantConstants.SUPER_TENANT_ID); + + identityUtil.when(() -> IdentityUtil.getProperty(ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN)) + .thenReturn(claimSeparationFeatureEnabled ? "true" : "false"); + + mockServiceProvider = mock(ServiceProvider.class); + oAuth2Util.when(() -> OAuth2Util.getServiceProvider(anyString(), anyString())) + .thenReturn(mockServiceProvider); + when(mockServiceProvider.getApplicationVersion()).thenReturn(appVersion); + + OAuthAppDO app = buildDummyOAuthAppDO("some-user-name"); + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(OAuthAppDAO.class, + (mock, context) -> { + when(mock.getAppInformation(consumerKey, MultitenantConstants.SUPER_TENANT_ID)) + .thenReturn(app); + })) { + + ApplicationManagementService appMgtService = mock(ApplicationManagementService.class); + OAuth2ServiceComponentHolder.setApplicationMgtService(appMgtService); + when(appMgtService.getServiceProvider(consumerKey, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) + .thenReturn(mockServiceProvider); + + OAuthAdminServiceImpl oAuthAdminServiceImpl = new OAuthAdminServiceImpl(); + OAuthConsumerAppDTO oAuthConsumerApp = oAuthAdminServiceImpl.getOAuthApplicationData(consumerKey, + MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + oAuthConsumerApp.setUsername(app.getUser().toString()); + + assertAllAttributesOfConsumerAppDTO(oAuthConsumerApp, app); + } + } } } @@ -517,10 +565,16 @@ public Object[][] getUpdateConsumerAppTestData() { return new Object[][]{ // Logged In user , App Owner in Request , App Owner in request exists, Excepted App Owner after update - {"admin@carbon.super", "H2/new-app-owner@carbon.super", false, "original-app-owner@wso2.com"}, - {"admin@carbon.super", "H2/new-app-owner@carbon.super", true, "H2/new-app-owner@carbon.super"}, - {"admin@wso2.com", "H2/new-app-owner@wso2.com", false, "original-app-owner@wso2.com"}, - {"admin@wso2.com", "H2/new-app-owner@wso2.com", true, "H2/new-app-owner@wso2.com"} + {"admin@carbon.super", "H2/new-app-owner@carbon.super", false, "original-app-owner@wso2.com", + true, "v2.0.0"}, + {"admin@carbon.super", "H2/new-app-owner@carbon.super", true, "H2/new-app-owner@carbon.super", + true, "v2.0.0"}, + {"admin@wso2.com", "H2/new-app-owner@wso2.com", false, "original-app-owner@wso2.com", + true, "v2.0.0"}, + {"admin@wso2.com", "H2/new-app-owner@wso2.com", true, "H2/new-app-owner@wso2.com", + true, "v2.0.0"}, + {"admin@carbon.super", "H2/new-app-owner@carbon.super", false, "original-app-owner@wso2.com", + false, "v2.0.0"}, }; } @@ -543,80 +597,108 @@ private AuthenticatedUser buildUser(String fullQualifiedUsername) { public void testUpdateConsumerApplication(String loggedInUsername, String appOwnerInRequest, boolean appOwnerInRequestExists, - String expectedAppOwnerAfterUpdate) throws Exception { - - try (MockedStatic identityUtil = mockStatic(IdentityUtil.class); - MockedStatic oAuthComponentServiceHolder = - mockStatic(OAuthComponentServiceHolder.class);) { - - AuthenticatedUser loggedInUser = buildUser(loggedInUsername); - identityUtil.when(() -> IdentityUtil.isUserStoreCaseSensitive(anyString(), anyInt())).thenReturn(true); - identityUtil.when(() -> IdentityUtil.addDomainToName(anyString(), anyString())).thenCallRealMethod(); - - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(loggedInUser.getTenantDomain()); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId( - IdentityTenantUtil.getTenantId(loggedInUser.getTenantDomain())); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(loggedInUser.getUserName()); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUserRealm(userRealm); - - AuthenticatedUser appOwner = buildUser(appOwnerInRequest); - String tenantAwareUsernameOfAppOwner = - MultitenantUtils.getTenantAwareUsername(appOwner.toFullQualifiedUsername()); - - when(userStoreManager.isExistingUser(tenantAwareUsernameOfAppOwner)).thenReturn(appOwnerInRequestExists); - - String consumerKey = UUID.randomUUID().toString(); - OAuthAppDO app = buildDummyOAuthAppDO("original-app-owner"); - AuthenticatedUser originalOwner = app.getAppOwner(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(OAuthAppDAO.class, - (mock, context) -> { - when(mock.getAppInformation(consumerKey, - IdentityTenantUtil.getTenantId(loggedInUser.getTenantDomain()))) - .thenReturn(app); - })) { + String expectedAppOwnerAfterUpdate, + boolean claimSeparationFeatureEnabled, String appVersion) + throws Exception { - OAuthAdminServiceImpl oAuthAdminServiceImpl = new OAuthAdminServiceImpl(); - OAuthConsumerAppDTO consumerAppDTO = new OAuthConsumerAppDTO(); - consumerAppDTO.setApplicationName("new-application-name"); - consumerAppDTO.setCallbackUrl("http://new-call-back-url.com"); - consumerAppDTO.setOauthConsumerKey(consumerKey); - consumerAppDTO.setOauthConsumerSecret("some-consumer-secret"); - consumerAppDTO.setOAuthVersion("new-oauth-version"); - consumerAppDTO.setUsername(appOwner.toFullQualifiedUsername()); - - mockOAuthComponentServiceHolder(oAuthComponentServiceHolder); - - String tenantDomain = MultitenantUtils.getTenantDomain(appOwnerInRequest); - String userStoreDomain = UserCoreUtil.extractDomainFromName(appOwnerInRequest); - String domainFreeName = UserCoreUtil.removeDomainFromName(appOwnerInRequest); - String username = MultitenantUtils.getTenantAwareUsername(domainFreeName); - - org.wso2.carbon.user.core.common.User user = new org.wso2.carbon.user.core.common.User(); - user.setUsername(username); - user.setTenantDomain(tenantDomain); - user.setUserStoreDomain(userStoreDomain); - Mockito.when(mockAbstractUserStoreManager.getUser(any(), anyString())).thenReturn(user); - Mockito.when(mockAbstractUserStoreManager.isExistingUser(anyString())) - .thenReturn(appOwnerInRequestExists); - - oAuthAdminServiceImpl.updateConsumerApplication(consumerAppDTO); - OAuthConsumerAppDTO updatedOAuthConsumerApp = oAuthAdminServiceImpl.getOAuthApplicationData(consumerKey, - tenantDomain); - Assert.assertEquals(updatedOAuthConsumerApp.getApplicationName(), consumerAppDTO.getApplicationName(), - "Updated Application name should be same as the application name in consumerAppDTO " + - "data object."); - Assert.assertEquals(updatedOAuthConsumerApp.getCallbackUrl(), consumerAppDTO.getCallbackUrl(), - "Updated Application callbackUrl should be same as the callbackUrl in consumerAppDTO " + - "data object."); - - if (appOwnerInRequestExists) { - // Application update should change the app owner if the app owner sent in the request is a - // valid user. - Assert.assertNotEquals(updatedOAuthConsumerApp.getUsername(), - originalOwner.toFullQualifiedUsername()); + try (MockedStatic oAuthServerConfigurationMockedStatic = mockStatic( + OAuthServerConfiguration.class);) { + // Mock and initialize the OAuthServerConfiguration. + mockOAuthServerConfiguration = mock(OAuthServerConfiguration.class); + oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance) + .thenReturn(mockOAuthServerConfiguration); + lenient().when(mockOAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(300L); + + try (MockedStatic identityUtil = mockStatic(IdentityUtil.class); + MockedStatic oAuthComponentServiceHolder = + mockStatic(OAuthComponentServiceHolder.class); + MockedStatic oAuth2Util = mockStatic(OAuth2Util.class)) { + + identityUtil.when(() -> IdentityUtil.getProperty(ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN)) + .thenReturn(claimSeparationFeatureEnabled ? "true" : "false"); + + oAuth2Util.when(() -> OAuth2Util.getServiceProvider(anyString(), anyString())) + .thenReturn(mockServiceProvider); + when(mockServiceProvider.getApplicationVersion()).thenReturn(appVersion); + + AuthenticatedUser loggedInUser = buildUser(loggedInUsername); + identityUtil.when(() -> IdentityUtil.isUserStoreCaseSensitive(anyString(), anyInt())).thenReturn(true); + identityUtil.when(() -> IdentityUtil.addDomainToName(anyString(), anyString())).thenCallRealMethod(); + + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(loggedInUser.getTenantDomain()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId( + IdentityTenantUtil.getTenantId(loggedInUser.getTenantDomain())); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(loggedInUser.getUserName()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUserRealm(userRealm); + + AuthenticatedUser appOwner = buildUser(appOwnerInRequest); + String tenantAwareUsernameOfAppOwner = + MultitenantUtils.getTenantAwareUsername(appOwner.toFullQualifiedUsername()); + + when(userStoreManager.isExistingUser(tenantAwareUsernameOfAppOwner)).thenReturn( + appOwnerInRequestExists); + + String consumerKey = UUID.randomUUID().toString(); + OAuthAppDO app = buildDummyOAuthAppDO("original-app-owner"); + AuthenticatedUser originalOwner = app.getAppOwner(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(OAuthAppDAO.class, + (mock, context) -> { + when(mock.getAppInformation(consumerKey, + IdentityTenantUtil.getTenantId(loggedInUser.getTenantDomain()))) + .thenReturn(app); + })) { + + ApplicationManagementService appMgtService = mock(ApplicationManagementService.class); + OAuth2ServiceComponentHolder.setApplicationMgtService(appMgtService); + when(appMgtService.getServiceProvider(consumerKey, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) + .thenReturn(mockServiceProvider); + + OAuthAdminServiceImpl oAuthAdminServiceImpl = new OAuthAdminServiceImpl(); + OAuthConsumerAppDTO consumerAppDTO = new OAuthConsumerAppDTO(); + consumerAppDTO.setApplicationName("new-application-name"); + consumerAppDTO.setCallbackUrl("http://new-call-back-url.com"); + consumerAppDTO.setOauthConsumerKey(consumerKey); + consumerAppDTO.setOauthConsumerSecret("some-consumer-secret"); + consumerAppDTO.setOAuthVersion("new-oauth-version"); + consumerAppDTO.setUsername(appOwner.toFullQualifiedUsername()); + + mockOAuthComponentServiceHolder(oAuthComponentServiceHolder); + + String tenantDomain = MultitenantUtils.getTenantDomain(appOwnerInRequest); + String userStoreDomain = UserCoreUtil.extractDomainFromName(appOwnerInRequest); + String domainFreeName = UserCoreUtil.removeDomainFromName(appOwnerInRequest); + String username = MultitenantUtils.getTenantAwareUsername(domainFreeName); + + org.wso2.carbon.user.core.common.User user = new org.wso2.carbon.user.core.common.User(); + user.setUsername(username); + user.setTenantDomain(tenantDomain); + user.setUserStoreDomain(userStoreDomain); + Mockito.when(mockAbstractUserStoreManager.getUser(any(), anyString())).thenReturn(user); + Mockito.when(mockAbstractUserStoreManager.isExistingUser(anyString())) + .thenReturn(appOwnerInRequestExists); + + oAuthAdminServiceImpl.updateConsumerApplication(consumerAppDTO); + OAuthConsumerAppDTO updatedOAuthConsumerApp = + oAuthAdminServiceImpl.getOAuthApplicationData(consumerKey, + tenantDomain); + Assert.assertEquals(updatedOAuthConsumerApp.getApplicationName(), + consumerAppDTO.getApplicationName(), + "Updated Application name should be same as the application name in consumerAppDTO " + + "data object."); + Assert.assertEquals(updatedOAuthConsumerApp.getCallbackUrl(), consumerAppDTO.getCallbackUrl(), + "Updated Application callbackUrl should be same as the callbackUrl in consumerAppDTO " + + "data object."); + + if (appOwnerInRequestExists) { + // Application update should change the app owner if the app owner sent in the request is a + // valid user. + Assert.assertNotEquals(updatedOAuthConsumerApp.getUsername(), + originalOwner.toFullQualifiedUsername()); + } + Assert.assertEquals(updatedOAuthConsumerApp.getUsername(), expectedAppOwnerAfterUpdate); } - Assert.assertEquals(updatedOAuthConsumerApp.getUsername(), expectedAppOwnerAfterUpdate); } } } diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilderTest.java index 559c7a25994..ff9f8bfc0bb 100644 --- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilderTest.java +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/action/PreIssueAccessTokenRequestBuilderTest.java @@ -34,6 +34,7 @@ import org.wso2.carbon.identity.action.execution.model.Param; import org.wso2.carbon.identity.action.execution.model.Tenant; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.oauth.action.model.AccessToken; import org.wso2.carbon.identity.oauth.action.model.PreIssueAccessTokenEvent; @@ -72,6 +73,7 @@ public class PreIssueAccessTokenRequestBuilderTest { private MockedStatic oAuthServerConfiguration; private MockedStatic identityTenantUtilMockedStatic; private MockedStatic oAuth2UtilMockedStatic; + private MockedStatic loggerUtils; private static final String CLIENT_ID_TEST = "test-client-id"; private static final String CLIENT_SECRET_TEST = "test-client-secret"; @@ -115,6 +117,9 @@ public void setUp() { identityTenantUtilMockedStatic.when(() -> IdentityTenantUtil.getTenantId(TENANT_DOMAIN_TEST)) .thenReturn(TENANT_ID_TEST); + loggerUtils = mockStatic(LoggerUtils.class); + loggerUtils.when(() -> LoggerUtils.isDiagnosticLogsEnabled()).thenReturn(true); + AuthorizationGrantHandler authorizationGrantHandler = mock(AuthorizationGrantHandler.class); Map mockGrantTypesMap = new HashMap<>(); mockGrantTypesMap.put(GRANT_TYPE_TEST, authorizationGrantHandler); @@ -131,6 +136,7 @@ public void tearDown() { oAuthServerConfiguration.close(); claimHandlerUtilMockedStatic.close(); identityTenantUtilMockedStatic.close(); + loggerUtils.close(); } @Test diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2UtilTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2UtilTest.java index 196ee2d431b..16b1a61d69c 100644 --- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2UtilTest.java +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2UtilTest.java @@ -2948,6 +2948,25 @@ public Object[][] initiateOIDCScopesDataProvider() { }; } + @DataProvider(name = "isAppVersionAllowedDataProvider") + public Object[][] isAppVersionAllowedDataProvider() { + + return new Object[][]{ + {"v0.0.0", "v1.0.0", false}, + {"v1.0.0", "v1.0.0", true}, + {"v2.0.0", "v1.0.0", true}, + {"v0.0.0", "v2.0.0", false}, + {"v1.0.0", "v2.0.0", false}, + {"v2.0.0", "v2.0.0", true}, + }; + } + + @Test(dataProvider = "isAppVersionAllowedDataProvider") + public void testIsAppVersionAllowed(String appVersion, String allowedVersions, boolean expected) { + + assertEquals(OAuth2Util.isAppVersionAllowed(appVersion, allowedVersions), expected); + } + private void setPrivateField(Object object, String fieldName, Object value) throws Exception { Field field = object.getClass().getDeclaredField(fieldName); diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtilTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtilTest.java new file mode 100755 index 00000000000..0102094ae85 --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/openidconnect/util/ClaimHandlerUtilTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024, 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.openidconnect.util; + +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; +import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.oauth2.util.OAuth2Util; +import org.wso2.carbon.identity.openidconnect.CustomClaimsCallbackHandler; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.testng.AssertJUnit.assertEquals; +import static org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; +import static org.wso2.carbon.identity.oauth.common.OAuthConstants.ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN; + +@Listeners(MockitoTestNGListener.class) +public class ClaimHandlerUtilTest { + + @Mock + private OAuthAppDO mockOAuthAppDO; + @Mock + private CustomClaimsCallbackHandler mockJWTAccessTokenOIDCClaimsHandler; + @Mock + private CustomClaimsCallbackHandler mockOpenIDConnectCustomClaimsCallbackHandler; + @Mock + private OAuthServerConfiguration mockOAuthServerConfiguration; + + MockedStatic oAuthServerConfigurationMockedStatic; + MockedStatic identityTenantUtilMockedStatic; + MockedStatic identityUtilMockedStatic; + MockedStatic oAuth2UtilMockedStatic; + + private final String openIDConnectIDTokenCustomClaimsHandlerClassName = "SAMLAssertionClaimsCallback"; + private final String jwtAccessTokenOIDCClaimsHandlerClassName = "JWTAccessTokenOIDCClaimsHandler"; + + @BeforeMethod + public void setUp() throws Exception { + + // Mock and initialize the OAuthServerConfiguration. + oAuthServerConfigurationMockedStatic = mockStatic(OAuthServerConfiguration.class); + mockOAuthServerConfiguration = mock(OAuthServerConfiguration.class); + oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance) + .thenReturn(mockOAuthServerConfiguration); + lenient().when(mockOAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(300L); + + // Initialize the static mocks. + identityTenantUtilMockedStatic = mockStatic(IdentityTenantUtil.class); + identityUtilMockedStatic = mockStatic(IdentityUtil.class); + oAuth2UtilMockedStatic = mockStatic(OAuth2Util.class); + + // Initialize the mocks. + String openIDConnectIDTokenPackageName = "org.wso2.carbon.identity.openidconnect."; + mockOAuthAppDO = mock(OAuthAppDO.class); + mockJWTAccessTokenOIDCClaimsHandler = mock(openIDConnectIDTokenPackageName + + jwtAccessTokenOIDCClaimsHandlerClassName); + mockOpenIDConnectCustomClaimsCallbackHandler = mock(openIDConnectIDTokenPackageName + + openIDConnectIDTokenCustomClaimsHandlerClassName); + + // Mock login tenant utils. + identityTenantUtilMockedStatic.when(IdentityTenantUtil::getLoginTenantId) + .thenReturn(MultitenantConstants.SUPER_TENANT_ID); + identityTenantUtilMockedStatic.when(() -> IdentityTenantUtil.getTenantDomain(-1234)) + .thenReturn(SUPER_TENANT_DOMAIN_NAME); + + // Mock the JWTAccessTokenOIDCClaimsHandler and OpenIDConnectCustomClaimsCallbackHandler. + lenient().when(mockOAuthServerConfiguration.getJWTAccessTokenOIDCClaimsHandler()) + .thenReturn(mockJWTAccessTokenOIDCClaimsHandler); + lenient().when(mockOAuthServerConfiguration.getOpenIDConnectCustomClaimsCallbackHandler()) + .thenReturn(mockOpenIDConnectCustomClaimsCallbackHandler); + } + + @AfterMethod + public void tearDown() { + + oAuthServerConfigurationMockedStatic.close(); + identityTenantUtilMockedStatic.close(); + identityUtilMockedStatic.close(); + oAuth2UtilMockedStatic.close(); + } + + @DataProvider(name = "getClaimsCallbackHandlerDataProvider") + public Object[][] getClaimsCallbackHandlerDataProvider() { + + return new Object[][] { + {true, "v0.0.0", openIDConnectIDTokenCustomClaimsHandlerClassName, false}, + {true, "v1.0.0", openIDConnectIDTokenCustomClaimsHandlerClassName, false}, + {true, "v2.0.0", jwtAccessTokenOIDCClaimsHandlerClassName, true}, + {false, "v0.0.0", openIDConnectIDTokenCustomClaimsHandlerClassName, false}, + {false, "v1.0.0", openIDConnectIDTokenCustomClaimsHandlerClassName, false}, + {false, "v2.0.0", openIDConnectIDTokenCustomClaimsHandlerClassName, true} + }; + } + + @Test(dataProvider = "getClaimsCallbackHandlerDataProvider") + public void testGetClaimsCallbackHandler(boolean isServerConfigEnabled, String appVersion, String className, + boolean isAllowed) + throws IdentityOAuth2Exception { + + // Mock the configuration for claims separation enabled on demand. + identityUtilMockedStatic.when(() -> IdentityUtil.getProperty(ENABLE_CLAIMS_SEPARATION_FOR_ACCESS_TOKEN)) + .thenReturn(isServerConfigEnabled ? "true" : "false"); + + // Mock the service provider and app version. + lenient().when(mockOAuthAppDO.getOauthConsumerKey()).thenReturn("testConsumerKey"); + ServiceProvider serviceProvider = new ServiceProvider(); + serviceProvider.setApplicationVersion(appVersion); + oAuth2UtilMockedStatic.when(() -> OAuth2Util.getServiceProvider(anyString(), anyString())) + .thenReturn(serviceProvider); + oAuth2UtilMockedStatic.when(() -> OAuth2Util.isAppVersionAllowed( + appVersion, ApplicationConstants.ApplicationVersion.APP_VERSION_V2)) + .thenReturn(isAllowed); + + CustomClaimsCallbackHandler result = ClaimHandlerUtil.getClaimsCallbackHandler(mockOAuthAppDO); + String extractedClassName = extractClassName(result.toString()); + assertEquals(extractedClassName, className); + } + + private String extractClassName(String mockClassName) { + + if (mockClassName == null || mockClassName.isEmpty()) { + return ""; + } + int lastDotIndex = mockClassName.lastIndexOf('.'); + if (lastDotIndex != -1) { + mockClassName = mockClassName.substring(lastDotIndex + 1); + } + int dollarIndex = mockClassName.indexOf('$'); + if (dollarIndex != -1) { + return mockClassName.substring(0, dollarIndex); + } + return mockClassName; + } +} diff --git a/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml old mode 100644 new mode 100755 index a0d2df47c2e..91398cee77b --- a/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml +++ b/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml @@ -108,7 +108,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -197,6 +197,7 @@ + diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml index 4314658b651..f6687a148a6 100644 --- a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml +++ b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.oidc.session/pom.xml b/components/org.wso2.carbon.identity.oidc.session/pom.xml index 0effdc07055..3014b38ada3 100644 --- a/components/org.wso2.carbon.identity.oidc.session/pom.xml +++ b/components/org.wso2.carbon.identity.oidc.session/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/components/org.wso2.carbon.identity.webfinger/pom.xml b/components/org.wso2.carbon.identity.webfinger/pom.xml index 2abee385489..536d03b873b 100644 --- a/components/org.wso2.carbon.identity.webfinger/pom.xml +++ b/components/org.wso2.carbon.identity.webfinger/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/features/org.wso2.carbon.identity.oauth.common.feature/pom.xml b/features/org.wso2.carbon.identity.oauth.common.feature/pom.xml index 5a6de9854c1..b5f2926578d 100644 --- a/features/org.wso2.carbon.identity.oauth.common.feature/pom.xml +++ b/features/org.wso2.carbon.identity.oauth.common.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/features/org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml b/features/org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml index 0b909007299..376809fe91e 100644 --- a/features/org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/features/org.wso2.carbon.identity.oauth.feature/pom.xml b/features/org.wso2.carbon.identity.oauth.feature/pom.xml index 9dbdc1c5029..5e4b91affa4 100644 --- a/features/org.wso2.carbon.identity.oauth.feature/pom.xml +++ b/features/org.wso2.carbon.identity.oauth.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml b/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml index af38afe98fb..489d009d6c8 100644 --- a/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml b/features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml index 27256f8868a..5b4ed6d19b2 100644 --- a/features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml +++ b/features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index b797a5ab7a5..264f6907ae1 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 4.0.0 org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT pom WSO2 Carbon OAuth module http://wso2.org @@ -939,7 +939,7 @@ [1.0.1, 2.0.0) - 7.5.71 + 7.5.86 [5.25.234, 8.0.0) diff --git a/service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml b/service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml index ab07fd0cecf..f15a112adbb 100644 --- a/service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml +++ b/service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT ../../pom.xml diff --git a/test-utils/org.wso2.carbon.identity.oauth.common.testng/pom.xml b/test-utils/org.wso2.carbon.identity.oauth.common.testng/pom.xml index a89e6db1563..68978fceeb8 100644 --- a/test-utils/org.wso2.carbon.identity.oauth.common.testng/pom.xml +++ b/test-utils/org.wso2.carbon.identity.oauth.common.testng/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.inbound.auth.oauth2 identity-inbound-auth-oauth ../../pom.xml - 7.0.172-SNAPSHOT + 7.0.176-SNAPSHOT 4.0.0