From c8d568e5fae03a37e16a0de383cb48fe771fc0c0 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Tue, 2 Jul 2024 16:18:54 +0530
Subject: [PATCH 01/28] accept and persist authorization_details of authorize
request - Accept 'authorization_details' field in the authorization request.
- Persist code and consent authorization details in the database. - Add
support for oauth.rar and oauth.rar.common modules. - Read custom
implementations of AuthorizationDetailsProvider from SPI. - Display rich
authorization details in the consent UI.
---
.../pom.xml | 5 +
.../endpoint/authz/OAuth2AuthzEndpoint.java | 101 +++++-
.../oauth/endpoint/util/EndpointUtil.java | 8 +
.../authz/OAuth2AuthzEndpointTest.java | 10 +
.../pom.xml | 60 ++++
.../common/dao/AuthorizationDetailsDAO.java | 69 ++++
.../dao/AuthorizationDetailsDAOImpl.java | 189 +++++++++++
.../oauth2/rar/common/dao/SQLQueries.java | 68 ++++
.../dto/AuthorizationDetailsCodeDTO.java | 22 ++
.../dto/AuthorizationDetailsConsentDTO.java | 38 +++
.../common/dto/AuthorizationDetailsDTO.java | 53 ++++
.../rar/common/model/AuthorizationDetail.java | 298 ++++++++++++++++++
.../common/model/AuthorizationDetails.java | 126 ++++++++
.../util/AuthorizationDetailsCommonUtils.java | 149 +++++++++
.../util/AuthorizationDetailsConstants.java | 37 +++
.../pom.xml | 108 +++++++
.../rar/AuthorizationDetailsService.java | 278 ++++++++++++++++
.../rar/AuthorizationDetailsValidator.java | 171 ++++++++++
.../core/AuthorizationDetailsProvider.java | 108 +++++++
.../AuthorizationDetailsProviderFactory.java | 133 ++++++++
...thorizationDetailsProcessingException.java | 30 ++
.../RARAccessTokenResponseHandler.java | 61 ++++
.../AuthorizationDetailsDataHolder.java | 94 ++++++
.../AuthorizationDetailsServiceComponent.java | 69 ++++
.../model/AuthorizationDetailsContext.java | 98 ++++++
.../oauth2/rar/model/ValidationResult.java | 134 ++++++++
.../rar/util/AuthorizationDetailsUtils.java | 56 ++++
.../org.wso2.carbon.identity.oauth/pom.xml | 5 +
...tityOAuth2AuthorizationDetailsService.java | 134 ++++++++
.../authz/AuthorizationHandlerManager.java | 2 +-
.../authz/OAuthAuthzReqMessageContext.java | 25 ++
.../handlers/AbstractResponseTypeHandler.java | 3 +
.../handlers/CodeResponseTypeHandler.java | 2 +
.../dao/OAuthTokenPersistenceFactory.java | 17 +
.../oauth2/model/OAuth2Parameters.java | 25 ++
pom.xml | 18 ++
36 files changed, 2802 insertions(+), 2 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsCommonUtils.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsConstants.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/pom.xml
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProvider.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/ValidationResult.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/IdentityOAuth2AuthorizationDetailsService.java
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
index 82b7cdb973..564cacdef7 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
@@ -176,6 +176,11 @@
jackson-core
provided
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar
+ provided
+
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
index af69213459..47f2f21f5b 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
@@ -119,6 +119,7 @@
import org.wso2.carbon.identity.oauth2.IdentityOAuth2UnauthorizedScopeException;
import org.wso2.carbon.identity.oauth2.OAuth2Service;
import org.wso2.carbon.identity.oauth2.RequestObjectException;
+import org.wso2.carbon.identity.oauth2.authz.AuthorizationHandlerManager;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext;
import org.wso2.carbon.identity.oauth2.device.api.DeviceAuthService;
@@ -134,6 +135,12 @@
import org.wso2.carbon.identity.oauth2.model.FederatedTokenDO;
import org.wso2.carbon.identity.oauth2.model.HttpRequestHeaderHandler;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsValidator;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.responsemode.provider.AuthorizationResponseDTO;
import org.wso2.carbon.identity.oauth2.responsemode.provider.ResponseModeProvider;
import org.wso2.carbon.identity.oauth2.scopeservice.ScopeMetadataService;
@@ -280,6 +287,9 @@ public class OAuth2AuthzEndpoint {
private static ScopeMetadataService scopeMetadataService;
private static DeviceAuthService deviceAuthService;
+
+ private static AuthorizationDetailsService authorizationDetailsService;
+
private static final String AUTH_SERVICE_RESPONSE = "authServiceResponse";
private static final String IS_API_BASED_AUTH_HANDLED = "isApiBasedAuthHandled";
private static final ApiAuthnHandler API_AUTHN_HANDLER = new ApiAuthnHandler();
@@ -304,6 +314,16 @@ public static void setScopeMetadataService(ScopeMetadataService scopeMetadataSer
OAuth2AuthzEndpoint.scopeMetadataService = scopeMetadataService;
}
+ public static AuthorizationDetailsService getAuthorizationDetailsService() {
+
+ return authorizationDetailsService;
+ }
+
+ public static void setAuthorizationDetailsService(AuthorizationDetailsService authorizationDetailsService) {
+
+ OAuth2AuthzEndpoint.authorizationDetailsService = authorizationDetailsService;
+ }
+
private static Class extends OAuthAuthzRequest> oAuthAuthzRequestClass;
@GET
@@ -1697,10 +1717,18 @@ private void storeUserConsent(OAuthMessage oAuthMessage, String consent) throws
if (approvedAlways) {
OpenIDConnectUserRPStore.getInstance().putUserRPToStore(loggedInUser, applicationName,
true, clientId);
+ final AuthorizationDetails userConsentedAuthorizationDetails =
+ authorizationDetailsService.getUserConsentedAuthorizationDetails(
+ oAuthMessage.getRequest().getParameterMap(), oauth2Params);
+
if (hasPromptContainsConsent(oauth2Params)) {
EndpointUtil.storeOAuthScopeConsent(loggedInUser, oauth2Params, true);
+ authorizationDetailsService.storeOrReplaceUserConsentedAuthorizationDetails(loggedInUser,
+ clientId, oauth2Params, userConsentedAuthorizationDetails);
} else {
EndpointUtil.storeOAuthScopeConsent(loggedInUser, oauth2Params, false);
+ authorizationDetailsService.storeUserConsentedAuthorizationDetails(loggedInUser,
+ clientId, oauth2Params, userConsentedAuthorizationDetails);
}
}
}
@@ -2577,6 +2605,12 @@ private String populateOauthParameters(OAuth2Parameters params, OAuthMessage oAu
params.setEssentialClaims(oauthRequest.getParam(CLAIMS));
}
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oauthRequest)) {
+ final String authorizationDetailsJson = oauthRequest
+ .getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS);
+ params.setAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
+ }
+
handleMaxAgeParameter(oauthRequest, params);
Object isMtls = oAuthMessage.getRequest().getAttribute(OAuthConstants.IS_MTLS_REQUEST);
@@ -2980,6 +3014,22 @@ private String doUserAuthorization(OAuthMessage oAuthMessage, String sessionData
return handleAuthorizationFailureBeforeConsent(oAuthMessage, oauth2Params, authorizeRespDTO);
}
+ try {
+ validateAuthorizationDetailsBeforeConsent(oAuthMessage, oauth2Params, authzReqDTO);
+ } catch (AuthorizationDetailsProcessingException e) {
+ log.debug("Error occurred while validating authorization details. Caused by, ", e);
+
+ authorizationResponseDTO.setError(HttpServletResponse.SC_FOUND,
+ AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG,
+ AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_CODE);
+
+ OAuth2AuthorizeRespDTO oAuth2AuthorizeRespDTO = new OAuth2AuthorizeRespDTO();
+ oAuth2AuthorizeRespDTO.setErrorMsg(AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG);
+ oAuth2AuthorizeRespDTO.setErrorCode(AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_CODE);
+ oAuth2AuthorizeRespDTO.setCallbackURI(authzReqDTO.getCallbackUrl());
+ return handleAuthorizationFailureBeforeConsent(oAuthMessage, oauth2Params, oAuth2AuthorizeRespDTO);
+ }
+
boolean hasUserApproved = isUserAlreadyApproved(oauth2Params, authenticatedUser);
if (hasPromptContainsConsent(oauth2Params)) {
@@ -3673,7 +3723,8 @@ private boolean isUserAlreadyApproved(OAuth2Parameters oauth2Params, Authenticat
throws OAuthSystemException {
try {
- return EndpointUtil.isUserAlreadyConsentedForOAuthScopes(user, oauth2Params);
+ return EndpointUtil.isUserAlreadyConsentedForOAuthScopes(user, oauth2Params) &&
+ authorizationDetailsService.isUserAlreadyConsentedForAuthorizationDetails(user, oauth2Params);
} catch (IdentityOAuth2ScopeException | IdentityOAuthAdminException e) {
throw new OAuthSystemException("Error occurred while checking user has already approved the consent " +
"required OAuth scopes.", e);
@@ -4746,4 +4797,52 @@ private Response handleUnsupportedGrantForApiBasedAuth() {
new AuthServiceClientException(AuthServiceConstants.ErrorMessage.ERROR_INVALID_AUTH_REQUEST.code(),
"App native authentication is only supported with code response type."), log);
}
+
+ /**
+ * Validates the authorization details in the provided OAuth message before user consent.
+ *
+ * This method checks if the request is a rich authorization request. If it is, it
+ * retrieves and validates the authorization details, updating the parameters and context
+ * accordingly. If any validation errors occur, it logs the issue and throws an appropriate
+ * exception.
+ *
+ * @param oAuthMessage The {@link OAuthMessage} containing the authorization request details.
+ * @param oAuth2Parameters The {@link OAuth2Parameters} object holding the parameters of the OAuth request.
+ * @param oAuth2AuthorizeReqDTO The {@link OAuth2AuthorizeReqDTO} object containing the authorization request.
+ * @throws OAuthSystemException If there is an error during the validation process.
+ * @throws AuthorizationDetailsProcessingException If there is an error processing the authorization details.
+ */
+ private void validateAuthorizationDetailsBeforeConsent(final OAuthMessage oAuthMessage,
+ final OAuth2Parameters oAuth2Parameters,
+ final OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO)
+ throws OAuthSystemException, AuthorizationDetailsProcessingException {
+
+ if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2Parameters)) {
+ log.debug("Authorization request is not a rich authorization request. Skipping validation.");
+ return;
+ }
+
+ try {
+ final OAuthAppDO oAuthAppDO = AuthorizationHandlerManager.getInstance()
+ .getAppInformation(oAuth2AuthorizeReqDTO);
+ // Validate the authorization details
+ final AuthorizationDetails validatedAuthorizationDetails = new AuthorizationDetailsValidator()
+ .getValidatedAuthorizationDetails(oAuth2Parameters, oAuthAppDO, oAuth2AuthorizeReqDTO.getUser());
+
+ if (log.isDebugEnabled()) {
+ log.debug("Authorization details validated successfully for user: "
+ + oAuth2AuthorizeReqDTO.getUser().getLoggableMaskedUserId());
+ }
+ // update oAuth2Parameters with validated authorization details
+ oAuth2Parameters.setAuthorizationDetails(validatedAuthorizationDetails);
+
+ // Update the authorization message context with validated authorization details
+ OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext =
+ oAuthMessage.getSessionDataCacheEntry().getAuthzReqMsgCtx();
+ oAuthAuthzReqMessageContext.setAuthorizationDetails(validatedAuthorizationDetails);
+ } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) {
+ log.error("Error occurred while validating authorization details. Caused by, ", e);
+ throw new OAuthSystemException("Error occurred while validating requested authorization details", e);
+ }
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
index 616870d296..4129b752b7 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
@@ -103,6 +103,8 @@
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthAuthzRequest;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.model.OAuth2ScopeConsentResponse;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.scopeservice.OAuth2Resource;
import org.wso2.carbon.identity.oauth2.scopeservice.ScopeMetadataService;
import org.wso2.carbon.identity.oauth2.util.AuthzUtil;
@@ -868,6 +870,12 @@ public static String getUserConsentURL(OAuth2Parameters params, String loggedInU
(consentRequiredScopes, UTF_8) + "&" + OAuthConstants.SESSION_DATA_KEY_CONSENT
+ "=" + URLEncoder.encode(sessionDataKeyConsent, UTF_8) + "&" + "&spQueryParams=" + queryString;
+ // Append authorization details to consent page url
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(params)) {
+ consentPageUrl = consentPageUrl + "&" + AuthorizationDetailsConstants.AUTHORIZATION_DETAILS + "="
+ + URLEncoder.encode(params.getAuthorizationDetails().toJsonString(), UTF_8);
+ }
+
// Append scope metadata to additionalQueryParams.
String scopeMetadataQueryParam = getScopeMetadataQueryParam(params.getConsentRequiredScopes(),
params.getTenantDomain());
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
index 3448987379..9f990810f4 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
@@ -112,6 +112,7 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientValidationResponseDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
import org.wso2.carbon.identity.oauth2.responsemode.provider.ResponseModeProvider;
import org.wso2.carbon.identity.oauth2.responsemode.provider.impl.DefaultResponseModeProvider;
import org.wso2.carbon.identity.oauth2.responsemode.provider.impl.FormPostResponseModeProvider;
@@ -284,6 +285,9 @@ public class OAuth2AuthzEndpointTest extends TestOAuthEndpointBase {
@Mock
private CentralLogMgtServiceComponentHolder centralLogMgtServiceComponentHolderMock;
+ @Mock
+ private AuthorizationDetailsService authorizationDetailsService;
+
private static final String ERROR_PAGE_URL = "https://localhost:9443/authenticationendpoint/oauth2_error.do";
private static final String LOGIN_PAGE_URL = "https://localhost:9443/authenticationendpoint/login.do";
private static final String USER_CONSENT_URL =
@@ -803,6 +807,10 @@ public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, bo
when(oAuth2ScopeService.hasUserProvidedConsentForAllRequestedScopes(
anyString(), isNull(), anyInt(), anyList())).thenReturn(true);
+ when(authorizationDetailsService.isUserAlreadyConsentedForAuthorizationDetails(
+ any(AuthenticatedUser.class), any(OAuth2Parameters.class))).thenReturn(true);
+ OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsService);
+
mockServiceURLBuilder(serviceURLBuilder);
setSupportedResponseModes();
Response response = oAuth2AuthzEndpoint.authorize(httpServletRequest, httpServletResponse);
@@ -1644,6 +1652,8 @@ public void testHandleUserConsent(boolean isRespDTONull, String consent, boolean
OAuthAuthzReqMessageContext authzReqMsgCtx = new OAuthAuthzReqMessageContext(authorizeReqDTO);
when(consentCacheEntry.getAuthzReqMsgCtx()).thenReturn(authzReqMsgCtx);
+ OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsService);
+
Response response;
try {
setSupportedResponseModes();
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml b/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
new file mode 100644
index 0000000000..1ac995d59f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
@@ -0,0 +1,60 @@
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ identity-inbound-auth-oauth
+ 7.0.107-SNAPSHOT
+ ../../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.identity.oauth.rar.common
+ jar
+ WSO2 Carbon - Rich Authorization Requests Common
+ http://wso2.org
+
+
+ UTF-8
+
+
+
+
+ org.wso2.carbon.identity.framework
+ org.wso2.carbon.identity.core
+ provided
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ provided
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+
+ High
+ 2048
+
+
+
+
+
+
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
new file mode 100644
index 0000000000..a21b68b4d7
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.dao;
+
+import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Provides methods to interact with the database to manage authorization details.
+ */
+public interface AuthorizationDetailsDAO {
+
+ /**
+ * Adds authorization details against a given OAuth2 code.
+ *
+ * @param authorizationCodeID The ID of the authorization code.
+ * @param authorizationDetails The authorization details to store.
+ * @param tenantId The tenant ID.
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] addOAuth2CodeAuthorizationDetails(String authorizationCodeID, AuthorizationDetails authorizationDetails,
+ int tenantId) throws SQLException;
+
+ /**
+ * Adds user consented authorization details.
+ *
+ * @param authorizationDetailsConsentDTOs List of user consented authorization details DTOs.
+ * {@link AuthorizationDetailsConsentDTO }
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] addUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
+ throws SQLException;
+
+ int deleteUserConsentedAuthorizationDetails(String consentId, int tenantId)
+ throws SQLException;
+
+ // add a todo and mention to move this to consent module
+ String getConsentIdByUserIdAndAppId(String userId, String appId, int tenantId) throws SQLException;
+
+ Set getUserConsentedAuthorizationDetails(String consentId, int tenantId)
+ throws SQLException;
+
+ int[] updateUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
+ throws SQLException;
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java
new file mode 100644
index 0000000000..839f23c464
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.dao;
+
+import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
+import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation of {@link AuthorizationDetailsDAO}.
+ * This class provides methods to add authorization details to the database.
+ */
+public class AuthorizationDetailsDAOImpl implements AuthorizationDetailsDAO {
+
+ /**
+ * Stores authorization details against the provided OAuth2 authorization code.
+ *
+ * @param authorizationCodeID The ID of the authorization code.
+ * @param authorizationDetails The details to be added.
+ * @param tenantId The tenant ID.
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ @Override
+ public int[] addOAuth2CodeAuthorizationDetails(final String authorizationCodeID,
+ final AuthorizationDetails authorizationDetails,
+ final int tenantId) throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetail authorizationDetail : authorizationDetails.getDetails()) {
+ ps.setString(1, authorizationCodeID);
+ ps.setString(2, authorizationDetail.getType());
+ ps.setInt(3, tenantId);
+ ps.setString(4, authorizationDetail.toJsonString());
+ ps.setInt(5, tenantId);
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
+ /**
+ * Stores user consented authorization details.
+ *
+ * @param authorizationDetailsConsentDTOs The user consented authorization details DTOs
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ @Override
+ public int[] addUserConsentedAuthorizationDetails(
+ final List authorizationDetailsConsentDTOs) throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
+ ps.setString(1, consentDTO.getConsentId());
+ ps.setString(2, consentDTO.getAuthorizationDetail().getType());
+ ps.setInt(3, consentDTO.getTenantId());
+ ps.setString(4, consentDTO.getAuthorizationDetail().toJsonString());
+ ps.setBoolean(5, consentDTO.isConsentActive());
+ ps.setInt(6, consentDTO.getTenantId());
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
+ @Override
+ public int[] updateUserConsentedAuthorizationDetails(
+ final List authorizationDetailsConsentDTOs) throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
+ ps.setString(1, consentDTO.getAuthorizationDetail().toJsonString());
+ ps.setBoolean(2, consentDTO.isConsentActive());
+ ps.setString(3, consentDTO.getConsentId());
+ ps.setInt(4, consentDTO.getTenantId());
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
+ @Override
+ public int deleteUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
+ throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.DELETE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ ps.setString(1, consentId);
+ ps.setInt(2, tenantId);
+ return ps.executeUpdate();
+ }
+ }
+
+ @Override
+ public Set getUserConsentedAuthorizationDetails(final String consentId,
+ final int tenantId)
+ throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ ps.setString(1, consentId);
+ ps.setInt(2, tenantId);
+ try (ResultSet rs = ps.executeQuery()) {
+
+ final Set authorizationDetailsConsentDTOs = new HashSet<>();
+ while (rs.next()) {
+ final String id = rs.getString(1);
+ final int typeId = rs.getInt(2);
+ final String authorizationDetail = rs.getString(3);
+ final boolean isConsentActive = rs.getBoolean(4);
+
+ authorizationDetailsConsentDTOs.add(new AuthorizationDetailsConsentDTO(id, consentId, typeId,
+ authorizationDetail, isConsentActive, tenantId));
+ }
+ return authorizationDetailsConsentDTOs;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the first consent ID for a given user ID and application ID.
+ *
+ * @param userId The ID of the user.
+ * @param appId The ID of the application.
+ * @param tenantId The tenant ID.
+ * @return The first consent ID found, or null if no consent ID is found.
+ * @throws SQLException If a database access error occurs.
+ */
+ @Override
+ public String getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
+ throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.GET_IDN_OAUTH2_USER_CONSENT_CONSENT_ID)) {
+
+ ps.setString(1, userId);
+ ps.setString(2, appId);
+ ps.setInt(3, tenantId);
+ try (ResultSet rs = ps.executeQuery()) {
+ if (rs.next()) {
+ return rs.getString(1);
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java
new file mode 100644
index 0000000000..79faa31c9e
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.dao;
+
+/**
+ * The {@code SQLQueries} class contains SQL query constants used for performing
+ * database operations related to OAuth2 Rich Authorization Requests.
+ */
+public class SQLQueries {
+
+ private SQLQueries() {
+ // Private constructor to prevent instantiation
+ }
+
+ public static final String ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS =
+ "INSERT INTO IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS " +
+ "(CODE_ID, TYPE_ID, AUTHORIZATION_DETAILS, TENANT_ID) VALUES " +
+ "(?, (SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), " +
+ "? FORMAT JSON, ?)";
+
+ public static final String GET_OAUTH2_CODE_AUTHORIZATION_DETAILS =
+ "SELECT IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.AUTHORIZATION_DETAILS " +
+ "FROM IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS " +
+ "INNER JOIN IDN_OAUTH2_AUTHORIZATION_CODE " +
+ "ON IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.CODE_ID = IDN_OAUTH2_AUTHORIZATION_CODE.CODE_ID " +
+ "WHERE IDN_OAUTH2_AUTHORIZATION_CODE.AUTHORIZATION_CODE=? " +
+ "AND IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.TENANT_ID=?";
+
+ public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
+ "INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
+ "(CONSENT_ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT, TENANT_ID) VALUES " +
+ "(?,(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), " +
+ "? FORMAT JSON, ?, ?)";
+
+ public static final String UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
+ "UPDATE IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
+ "SET AUTHORIZATION_DETAILS=? CONSENT=? WHERE CONSENT_ID=? AND TENANT_ID=?";
+
+ public static final String GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
+ "SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
+ "WHERE CONSENT_ID=? AND TENANT_ID=?";
+
+ public static final String DELETE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
+ "DELETE FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS WHERE CONSENT_ID=? AND TENANT_ID=?";
+
+ public static final String CREATE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
+ "INSERT INTO IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
+ "(AUTHORIZATION_DETAILS_TYPE, AUTHORIZATION_DETAILS, TOKEN_ID, TENANT_ID) VALUES (?, ?, ?, ?)";
+
+ public static final String GET_IDN_OAUTH2_USER_CONSENT_CONSENT_ID =
+ "SELECT CONSENT_ID FROM IDN_OAUTH2_USER_CONSENT WHERE USER_ID=? AND APP_ID=? AND TENANT_ID=?";
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
new file mode 100644
index 0000000000..bc143a9325
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
@@ -0,0 +1,22 @@
+package org.wso2.carbon.identity.oauth2.rar.common.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+
+/**
+ *
+ */
+public class AuthorizationDetailsCodeDTO extends AuthorizationDetailsDTO {
+
+ final String codeId;
+
+ public AuthorizationDetailsCodeDTO(final String id, final String codeId, final int typeId,
+ final AuthorizationDetail authorizationDetail, final int tenantId) {
+
+ super(id, typeId, authorizationDetail, tenantId);
+ this.codeId = codeId;
+ }
+
+ public String getCodeId() {
+ return codeId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
new file mode 100644
index 0000000000..0cf61dc230
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
@@ -0,0 +1,38 @@
+package org.wso2.carbon.identity.oauth2.rar.common.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+
+/**
+ *
+ */
+public class AuthorizationDetailsConsentDTO extends AuthorizationDetailsDTO {
+
+ final String consentId;
+ final boolean isConsentActive;
+
+ public AuthorizationDetailsConsentDTO(final String id, final String consentId, final int typeId,
+ final String authorizationDetail,
+ final boolean isConsentActive, final int tenantId) {
+
+ super(id, typeId, authorizationDetail, tenantId);
+ this.consentId = consentId;
+ this.isConsentActive = isConsentActive;
+ }
+
+ public AuthorizationDetailsConsentDTO(final String consentId,
+ final AuthorizationDetail authorizationDetail,
+ final boolean isConsentActive, final int tenantId) {
+
+ super(authorizationDetail, tenantId);
+ this.consentId = consentId;
+ this.isConsentActive = isConsentActive;
+ }
+
+ public boolean isConsentActive() {
+ return isConsentActive;
+ }
+
+ public String getConsentId() {
+ return consentId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
new file mode 100644
index 0000000000..fa73865c8b
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
@@ -0,0 +1,53 @@
+package org.wso2.carbon.identity.oauth2.rar.common.dto;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
+
+/**
+ *
+ */
+public class AuthorizationDetailsDTO {
+
+ final String id;
+ final int typeId;
+ final AuthorizationDetail authorizationDetail;
+ final int tenantId;
+
+ public AuthorizationDetailsDTO(final String id, final int typeId, final AuthorizationDetail authorizationDetail,
+ final int tenantId) {
+
+ this.id = id;
+ this.typeId = typeId;
+ this.authorizationDetail = authorizationDetail;
+ this.tenantId = tenantId;
+ }
+
+ public AuthorizationDetailsDTO(final String id, final int typeId, final String authorizationDetailJson,
+ final int tenantId) {
+
+ this(id, typeId, AuthorizationDetailsCommonUtils
+ .fromJSON(authorizationDetailJson, AuthorizationDetail.class, new ObjectMapper()), tenantId);
+ }
+
+ public AuthorizationDetailsDTO(final AuthorizationDetail authorizationDetail, final int tenantId) {
+
+ this(null, 0, authorizationDetail, tenantId);
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public int getTypeId() {
+ return this.typeId;
+ }
+
+ public AuthorizationDetail getAuthorizationDetail() {
+ return this.authorizationDetail;
+ }
+
+ public int getTenantId() {
+ return this.tenantId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java
new file mode 100644
index 0000000000..96194b3485
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.model;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang.StringUtils;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Function;
+
+/**
+ * Represents an individual authorization details object which specifies the authorization requirements for a
+ * specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
+ * (as defined in RFC 9396: OAuth 2.0 Rich Authorization
+ * Requests).
+ *
+ * This class encapsulates the various attributes and their corresponding values that can be included within an
+ * authorization details object. The mandatory {@code type} field identifies the resource type or access requirement
+ * being described.
+ *
+ * Here is an example of {@code authorization_details} with
+ * Common Data Fields.
+ *
{@code
+ * [
+ * {
+ * "type": "customer_information",
+ * "locations": [
+ * "https://example.com/customers"
+ * ],
+ * "actions": [
+ * "read",
+ * "write"
+ * ],
+ * "datatypes": [
+ * "contacts",
+ * "photos"
+ * ],
+ * "identifier":"account-14-32-32-3",
+ * "privileges": [
+ * "admin"
+ * ]
+ * }
+ * ]
+ * }
+ *
+ * Refer to
+ * OAuth 2.0 Rich Authorization Requests for detailed information on the Authorization Details structure.
+ *
+ * @since 7.0.26.9
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AuthorizationDetail implements Serializable {
+
+ private static final long serialVersionUID = -3928636285264078857L;
+
+ @JsonIgnore
+ private String id;
+ private String type;
+ private List locations;
+ private List actions;
+ @JsonProperty("datatypes")
+ private List dataTypes;
+ private String identifier;
+ private List privileges;
+ private Map details;
+ private String consentDescription;
+
+ public AuthorizationDetail() {
+ this.setId(UUID.randomUUID().toString());
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ @JsonProperty("_id")
+ public void setId(final String id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the value of the type field associated with the authorization details object.
+ *
+ * {@code type} is a unique identifier for the authorization details type as a string. The value of the type
+ * field determines the allowable contents of the object that contains it.
+ *
+ * @return The String value of the type field
+ * @see
+ * Authorization Details Types
+ */
+ public String getType() {
+ return this.type;
+ }
+
+ public void setType(final String type) {
+ this.type = type;
+ }
+
+ /**
+ * Gets the optional list of locations associated with the authorization details object.
+ *
+ * {@code locations} is an array of strings representing the location of the resource or RS. These strings are
+ * typically URIs identifying the location of the RS. This field can allow a client to specify a particular RS.
+ *
+ * @return A list of locations or {@code null} if the {@code locations} field is not present.
+ */
+ public List getLocations() {
+ return this.locations;
+ }
+
+ public void setLocations(final List locations) {
+ this.locations = locations;
+ }
+
+ /**
+ * Gets the optional list of actions associated with the authorization details object.
+ *
+ * {@code actions} is an array of strings representing the kinds of actions to be taken at the resource.
+ *
+ * @return A list of actions or {@code null} if the {@code actions} field is not present.
+ */
+ public List getActions() {
+ return this.actions;
+ }
+
+ public void setActions(final List actions) {
+ this.actions = actions;
+ }
+
+ /**
+ * Gets the optional list of data types associated with the authorization details object.
+ *
+ * {@code datatypes} is an array of strings representing what kinds of data being requested from the resource.
+ *
+ * @return A list of datatypes or {@code null} if the {@code datatypes} field is not present.
+ */
+ public List getDataTypes() {
+ return this.dataTypes;
+ }
+
+ public void setDataTypes(final List dataTypes) {
+ this.dataTypes = dataTypes;
+ }
+
+ /**
+ * Gets the optional String identifier associated with the authorization details object.
+ *
+ * {@code identifier} is a string identifier indicating a specific resource available at the API.
+ *
+ * @return The String value of the identifier or {@code null} if the {@code identifier} field is not present.
+ */
+ public String getIdentifier() {
+ return this.identifier;
+ }
+
+ public void setIdentifier(final String identifier) {
+ this.identifier = identifier;
+ }
+
+ /**
+ * Gets the optional list of privileges associated with the authorization details object.
+ *
+ *
{@code privileges} is an array of strings representing the types or levels of privilege being requested
+ * at the resource.
+ *
+ * @return The String value of the privileges or {@code null} if the {@code privileges} field is not present.
+ */
+ public List getPrivileges() {
+ return this.privileges;
+ }
+
+ public void setPrivileges(final List privileges) {
+ this.privileges = privileges;
+ }
+
+ /**
+ * Gets a map containing API-specific fields from the authorization details object. The presence and structure
+ * of these fields can vary depending on the specific API being accessed.
+ *
+ * @return A map containing API-specific fields or {@code null} if no fields are present.
+ */
+ @JsonAnyGetter
+ public Map getDetails() {
+ return this.details;
+ }
+
+ public void setDetails(final Map details) {
+ this.details = details;
+ }
+
+ @JsonAnySetter
+ public void setDetail(final String key, final Object value) {
+ if (this.details == null) {
+ setDetails(new HashMap<>());
+ }
+ this.details.put(key, value);
+ }
+
+ /**
+ * Returns the consent description of an {@link AuthorizationDetail} instance.
+ * This value is only available after the enrichment process. The consent description provides a human-readable
+ * representation of the {@code authorization_details}, typically in the form of a sentence derived from the
+ * JSON object.
+ *
+ * @return A string representing the consent description of the {@code authorization_details}.
+ */
+ public String getConsentDescription() {
+ return this.consentDescription;
+ }
+
+ /**
+ * Sets a human-readable sentence that describes the {@code authorization_details}. This sentence is used to
+ * display to the user and obtain their consent for the current {@link AuthorizationDetail AuthorizationDetail}.
+ *
+ * @param consentDescription A string representing the description of the authorization detail.
+ * This description should be clear and understandable to the user,
+ * explaining what they are consenting to.
+ */
+ public void setConsentDescription(final String consentDescription) {
+ this.consentDescription = consentDescription;
+ }
+
+ /**
+ * Returns the consent description if present; otherwise, returns a value supplied by the provided {@link Function}.
+ * Example usage:
+ * {@code
+ * // Example 1: Using a simple default function that returns the "type", if description is missing
+ * AuthorizationDetail detail = new AuthorizationDetail();
+ * detail.setType("user_information");
+ * detail.setConsentDescription(""); // Empty description
+ * String result = detail.getConsentDescriptionOrDefault(authDetail -> authDetail.getType());
+ * // result will be "user_information"
+ *
+ * // Example 2: Consent description is already set and not empty
+ * AuthorizationDetail detail = new AuthorizationDetail();
+ * detail.setType("user_information");
+ * detail.setConsentDescription("User consented to data usage");
+ * String result = detail.getConsentDescriptionOrDefault(authDetail -> "Default Description");
+ * // result will be "User consented to data usage"
+ * }
+ *
+ * @param defaultFunction the Function that provides a default value if the consent description is not present
+ * @return the consent description if present, otherwise the value from the Function
+ */
+ public String getConsentDescriptionOrDefault(Function defaultFunction) {
+ return StringUtils.isNotEmpty(this.getConsentDescription()) ?
+ this.getConsentDescription() : defaultFunction.apply(this);
+ }
+
+ /**
+ * Converts the current authorization detail instance to a JSON string.
+ *
+ * @return The JSON representation of the authorization detail.
+ */
+ public String toJsonString() {
+ return AuthorizationDetailsCommonUtils.toJSON(this, new ObjectMapper());
+ }
+
+ @Override
+ public String toString() {
+ return "AuthorizationDetails {" +
+ "type='" + this.type + '\'' +
+ ", locations=" + this.locations +
+ ", actions=" + this.actions +
+ ", datatypes=" + this.dataTypes +
+ ", identifier=" + this.identifier +
+ ", privileges=" + this.privileges +
+ ", details=" + this.details +
+ ", consentDescription=" + this.consentDescription +
+ '}';
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java
new file mode 100644
index 0000000000..0befab02b1
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.model;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang.StringUtils;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Represents a set of {@link AuthorizationDetail} objects which specifies the authorization requirements for a
+ * specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
+ * (as defined in RFC 9396: OAuth 2.0 Rich Authorization
+ * Requests).
+ *
+ * Refer to
+ * OAuth 2.0 Rich Authorization Requests for detailed information on the Authorization Details structure.
+ *
+ * @see AuthorizationDetail
+ */
+public class AuthorizationDetails implements Serializable {
+
+ private static final long serialVersionUID = -663187547075070618L;
+
+ private final Set authorizationDetails;
+
+ /**
+ * Constructs an empty set of {@link AuthorizationDetail}.
+ */
+ public AuthorizationDetails() {
+ this(Collections.emptySet());
+ }
+
+ /**
+ * Constructs an immutable set of {@link AuthorizationDetail}.
+ *
+ * @param authorizationDetails The set of authorization details. If null, an empty set is assigned.
+ */
+ public AuthorizationDetails(final Set authorizationDetails) {
+ this.authorizationDetails = Optional.ofNullable(authorizationDetails)
+ .map(Collections::unmodifiableSet)
+ .orElse(Collections.emptySet());
+ }
+
+ /**
+ * Constructs an immutable set of {@link AuthorizationDetail} from a JSON string.
+ *
+ * @param authorizationDetailsJson The JSON string representing the authorization details.
+ */
+ public AuthorizationDetails(final String authorizationDetailsJson) {
+ this(AuthorizationDetailsCommonUtils.fromJSONArray(
+ authorizationDetailsJson, AuthorizationDetail.class, new ObjectMapper()));
+ }
+
+ /**
+ * Returns a set of the {@code authorization_details}.
+ *
+ * @return A set of {@link AuthorizationDetail}.
+ */
+ public Set getDetails() {
+ return this.authorizationDetails;
+ }
+
+ /**
+ * Returns a set of the {@code authorization_details} filtered by provided type.
+ *
+ * @return A set of {@link AuthorizationDetail}.
+ */
+ public Set getDetailsByType(final String type) {
+ return this.stream()
+ .filter(Objects::nonNull)
+ .filter(authorizationDetail -> StringUtils.equals(authorizationDetail.getType(), type))
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Converts the current set of authorization details to a JSON string.
+ *
+ * @return The JSON representation of the authorization details.
+ */
+ public String toJsonString() {
+ return AuthorizationDetailsCommonUtils.toJSON(this.getDetails(), new ObjectMapper());
+ }
+
+ /**
+ * Converts the set of authorization details to a human-readable string.
+ * Each detail's consent description is obtained or the type if the description is unavailable.
+ *
+ * @return A string representing the authorization details in a human-readable format.
+ */
+ public String toReadableText() {
+
+ return this.stream()
+ .map(authorizationDetail ->
+ authorizationDetail.getConsentDescriptionOrDefault(AuthorizationDetail::getType))
+ .collect(Collectors.joining(AuthorizationDetailsConstants.PARAM_SEPARATOR));
+ }
+
+ public Stream stream() {
+ return this.getDetails().stream();
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsCommonUtils.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsCommonUtils.java
new file mode 100644
index 0000000000..c908656d18
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsCommonUtils.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Utility class for handling OAuth2 Rich Authorization Requests.
+ */
+public class AuthorizationDetailsCommonUtils {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsCommonUtils.class);
+ private static final String empty_json = "{}";
+ private static final String empty_json_array = "[]";
+
+ private AuthorizationDetailsCommonUtils() {
+ // Private constructor to prevent instantiation
+ }
+
+ /**
+ * Parses the given JSON array string into a set of {@link AuthorizationDetail} objects.
+ *
+ * @param authorizationDetailsJson A JSON string containing authorization details which comes in the
+ * OAuth 2.0 authorization request or token request
+ * @param objectMapper A Jackson {@link ObjectMapper} used for parsing
+ * @param clazz A Class that extends {@link AuthorizationDetail} to be parsed
+ * @param the type parameter extending {@code AuthorizationDetail}
+ * @return an immutable set of {@link AuthorizationDetail} objects parsed from the given JSON string,
+ * or an empty set if parsing fails
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails
+ */
+ public static Set fromJSONArray(
+ final String authorizationDetailsJson, final Class clazz, final ObjectMapper objectMapper) {
+
+ try {
+ if (StringUtils.isNotEmpty(authorizationDetailsJson)) {
+ return objectMapper.readValue(authorizationDetailsJson,
+ objectMapper.getTypeFactory().constructCollectionType(Set.class, clazz));
+ }
+ } catch (JsonProcessingException e) {
+ log.debug("Error occurred while parsing String to AuthorizationDetails. Caused by, ", e);
+ }
+ return new HashSet<>();
+ }
+
+ /**
+ * Parses the given JSON object string into an {@link AuthorizationDetail} object.
+ *
+ * @param authorizationDetailJson A JSON string containing authorization detail object
+ * @param objectMapper A Jackson {@link ObjectMapper} used for parsing
+ * @param clazz A Class that extends {@link AuthorizationDetail} to be parsed
+ * @param the type parameter extending {@code AuthorizationDetail}
+ * @return an {@link AuthorizationDetail} objects parsed from the given JSON string,
+ * or null if parsing fails
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail
+ */
+ public static T fromJSON(
+ final String authorizationDetailJson, final Class clazz, final ObjectMapper objectMapper) {
+
+ try {
+ if (StringUtils.isNotEmpty(authorizationDetailJson)) {
+ return objectMapper.readValue(authorizationDetailJson, clazz);
+ }
+ } catch (JsonProcessingException e) {
+ log.debug("Error occurred while parsing String to AuthorizationDetails. Caused by, ", e);
+ }
+ return null;
+ }
+
+ /**
+ * Converts a set of {@code AuthorizationDetail} objects into a JSON string.
+ *
+ * If the input set is {@code null} or an exception occurs during the conversion,
+ * an empty JSON array ({@code []}) is returned.
+ *
+ *
+ * @param authorizationDetails the set of {@code AuthorizationDetail} objects to convert
+ * @param objectMapper the {@code ObjectMapper} instance to use for serialization
+ * @param the type parameter extending {@code AuthorizationDetail}
+ * @return a JSON string representation of the authorization details set,
+ * or an empty JSON array if null or an error occurs
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails
+ */
+ public static String toJSON(
+ final Set authorizationDetails, final ObjectMapper objectMapper) {
+
+ try {
+ if (authorizationDetails != null) {
+ return objectMapper.writeValueAsString(authorizationDetails);
+ }
+ } catch (JsonProcessingException e) {
+ log.debug("Error occurred while parsing AuthorizationDetails to String. Caused by, ", e);
+ }
+ return empty_json_array;
+ }
+
+ /**
+ * Converts a single {@code AuthorizationDetail} object into a JSON string.
+ *
+ * If the input object is {@code null} or an exception occurs during the conversion,
+ * an empty JSON object ({@code {}}) is returned.
+ *
+ *
+ * @param authorizationDetail the {@code AuthorizationDetail} object to convert
+ * @param objectMapper the {@code ObjectMapper} instance to use for serialization
+ * @param the type parameter extending {@code AuthorizationDetail}
+ * @return a JSON string representation of the authorization detail,
+ * or an empty JSON object if null or an error occurs
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail
+ * @see org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails
+ */
+ public static String toJSON(
+ final T authorizationDetail, final ObjectMapper objectMapper) {
+
+ try {
+ if (authorizationDetail != null) {
+ return objectMapper.writeValueAsString(authorizationDetail);
+ }
+ } catch (JsonProcessingException e) {
+ log.debug("Error occurred while parsing AuthorizationDetail to String. Caused by, ", e);
+ }
+ return empty_json;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsConstants.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsConstants.java
new file mode 100644
index 0000000000..5b1ab3d97f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/util/AuthorizationDetailsConstants.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.common.util;
+
+/**
+ * Stores constants related to OAuth2 Rich Authorization Requests.
+ */
+public final class AuthorizationDetailsConstants {
+
+ private AuthorizationDetailsConstants() {
+ // Private constructor to prevent instantiation
+ }
+
+ public static final String AUTHORIZATION_DETAILS = "authorization_details";
+ public static final String AUTHORIZATION_DETAILS_ID_PREFIX = "authorization_detail_id_";
+ public static final String PARAM_SEPARATOR = "&&";
+
+ public static final String TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT = "%s is not a supported authorization details type";
+ public static final String VALIDATION_FAILED_ERR_MSG = "Authorization details validation failed";
+ public static final String VALIDATION_FAILED_ERR_CODE = "invalid_authorization_details";
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
new file mode 100644
index 0000000000..bb6bc7c861
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ identity-inbound-auth-oauth
+ ../../pom.xml
+ 7.0.107-SNAPSHOT
+
+
+ 4.0.0
+ org.wso2.carbon.identity.oauth.rar
+ bundle
+ WSO2 Carbon - Rich Authorization Requests
+ http://wso2.org
+
+
+ UTF-8
+
+
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth
+ provided
+
+
+
+ com.google.auto.service
+ auto-service
+
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar.common
+
+
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+
+ ${project.artifactId}
+
+
+ org.wso2.carbon.identity.oauth2.rar.internal
+
+
+ org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}",
+ org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}",
+ org.wso2.carbon.identity.oauth2.*; version="${identity.inbound.auth.oauth.exp.pkg.version}",
+
+
+ !org.wso2.carbon.identity.oauth2.rar.internal,
+ org.wso2.carbon.identity.oauth2.rar.*;
+ version="${identity.inbound.auth.oauth.exp.pkg.version}",
+
+ *
+ <_dsannotations>*
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+
+ High
+ 2048
+
+
+
+
+
+
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
new file mode 100644
index 0000000000..00f4c97c96
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
@@ -0,0 +1,278 @@
+package org.wso2.carbon.identity.oauth2.rar;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.application.common.model.ServiceProvider;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.common.dao.AuthorizationDetailsDAO;
+import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS_ID_PREFIX;
+
+/**
+ *
+ */
+public class AuthorizationDetailsService extends IdentityOAuth2AuthorizationDetailsService {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsService.class);
+ private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
+
+ public AuthorizationDetailsService() {
+
+ this(OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO(),
+ AuthorizationDetailsProviderFactory.getInstance());
+ }
+
+ public AuthorizationDetailsService(final AuthorizationDetailsDAO authorizationDetailsDAO,
+ final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory) {
+
+ super(authorizationDetailsDAO);
+ this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
+ }
+
+ public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser, final String clientId,
+ final OAuth2Parameters oAuth2Parameters,
+ final AuthorizationDetails userConsentedAuthorizationDetails)
+ throws OAuthSystemException {
+
+ if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
+ return;
+ }
+
+ try {
+ final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
+ final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
+
+ if (consentId.isPresent()) {
+
+ super.authorizationDetailsDAO.addUserConsentedAuthorizationDetails(
+ generateAuthorizationDetailsConsentDTOs(consentId.get(),
+ userConsentedAuthorizationDetails, tenantId));
+ }
+ } catch (SQLException | IdentityOAuth2Exception e) {
+ log.error("Error occurred while storing user consented authorization details. Caused by, ", e);
+ throw new OAuthSystemException("Error occurred while storing authorization details", e);
+ }
+ }
+
+ public void updateUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
+ final String clientId, final OAuth2Parameters oAuth2Parameters,
+ final AuthorizationDetails userConsentedAuthorizationDetails)
+ throws OAuthSystemException {
+
+ if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
+ return;
+ }
+
+ try {
+ final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
+ final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
+
+ if (consentId.isPresent()) {
+
+ super.authorizationDetailsDAO.updateUserConsentedAuthorizationDetails(
+ generateAuthorizationDetailsConsentDTOs(consentId.get(),
+ userConsentedAuthorizationDetails, tenantId));
+ }
+ } catch (SQLException | IdentityOAuth2Exception e) {
+ log.error("Error occurred while updating user consented authorization details. Caused by, ", e);
+ throw new OAuthSystemException("Error occurred while updating authorization details", e);
+ }
+ }
+
+ public void deleteUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
+ final String clientId, final OAuth2Parameters oAuth2Parameters)
+ throws OAuthSystemException {
+
+ if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
+ return;
+ }
+
+ try {
+ final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
+ final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
+
+ if (consentId.isPresent()) {
+
+ super.authorizationDetailsDAO.deleteUserConsentedAuthorizationDetails(consentId.get(), tenantId);
+ }
+ } catch (SQLException | IdentityOAuth2Exception e) {
+ log.error("Error occurred while deleting user consented authorization details. Caused by, ", e);
+ throw new OAuthSystemException("Error occurred while storing authorization details", e);
+ }
+ }
+
+ public void storeOrReplaceUserConsentedAuthorizationDetails(
+ final AuthenticatedUser authenticatedUser, final String clientId, final OAuth2Parameters oAuth2Parameters,
+ final AuthorizationDetails userConsentedAuthorizationDetails) throws OAuthSystemException {
+
+ this.deleteUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters);
+ this.storeUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters,
+ userConsentedAuthorizationDetails);
+ }
+
+ /**
+ * Check if the user has already given consent to requested authorization details.
+ *
+ * @param authenticatedUser Authenticated user.
+ * @param oAuth2Parameters OAuth2 parameters.
+ * @return True if user has given consent to all the requested authorization details.
+ */
+ public boolean isUserAlreadyConsentedForAuthorizationDetails(final AuthenticatedUser authenticatedUser,
+ final OAuth2Parameters oAuth2Parameters)
+ throws OAuthSystemException {
+
+ try {
+ final String userId = this.getUserId(authenticatedUser);
+ final String appId = this.getApplicationResourceIdFromClientId(oAuth2Parameters.getClientId());
+ final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
+ final Optional consentId = this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
+
+ if (consentId.isPresent()) {
+ final Set consentedAuthorizationDetailsDTOs =
+ super.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId.get(), tenantId);
+
+ final Map> consentedAuthorizationDetailsByType =
+ consentedAuthorizationDetailsDTOs
+ .stream()
+ .filter(AuthorizationDetailsConsentDTO::isConsentActive)
+ .map(AuthorizationDetailsConsentDTO::getAuthorizationDetail)
+ .collect(Collectors.groupingBy(AuthorizationDetail::getType,
+ Collectors.mapping(Function.identity(), Collectors.toSet())));
+
+ for (final AuthorizationDetail requestedAuthorizationDetail :
+ oAuth2Parameters.getAuthorizationDetails().getDetails()) {
+
+ if (consentedAuthorizationDetailsByType.containsKey(requestedAuthorizationDetail.getType())) {
+
+ final Optional provider = authorizationDetailsProviderFactory
+ .getProviderByType(requestedAuthorizationDetail.getType());
+ if (provider.isPresent()) {
+
+ final AuthorizationDetails existingAuthorizationDetails = new AuthorizationDetails(
+ consentedAuthorizationDetailsByType.get(requestedAuthorizationDetail.getType()));
+ if (!provider.get()
+ .isEqualOrSubset(requestedAuthorizationDetail, existingAuthorizationDetails)) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("User has not consented for the requested authorization details type: "
+ + requestedAuthorizationDetail.getType());
+
+ }
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ } catch (IdentityOAuth2Exception | SQLException e) {
+ log.error("Error occurred while extracting user consented authorization details. Caused by, ", e);
+ throw new OAuthSystemException("Error occurred while extracting user consented authorization details", e);
+ }
+ }
+
+ /**
+ * Retrieves the user-consented authorization details based on the provided parameter map and OAuth2 parameters.
+ *
+ * This method is used to extract and return the authorization details that the user has consented to,
+ * filtering them based on a provided authorization details in the parameter map.
+ *
+ *
+ * @param parameterMap A map of query parameters.
+ * @param oAuth2Parameters The OAuth2 parameters that include the details of the authorization request.
+ * @return The {@link AuthorizationDetails} object containing the details the user has consented to.
+ */
+ public AuthorizationDetails getUserConsentedAuthorizationDetails(
+ final Map parameterMap, final OAuth2Parameters oAuth2Parameters) {
+
+ if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ return new AuthorizationDetails();
+ }
+
+ // Extract consented authorization detail IDs from the parameter map
+ final Set consentedAuthorizationDetailIDs = parameterMap.keySet().stream()
+ .filter(parameterName -> parameterName.startsWith(AUTHORIZATION_DETAILS_ID_PREFIX))
+ .map(parameterName -> parameterName.substring(AUTHORIZATION_DETAILS_ID_PREFIX.length()))
+ .collect(Collectors.toSet());
+
+ // Filter and collect the consented authorization details
+ final Set consentedAuthorizationDetails = oAuth2Parameters.getAuthorizationDetails()
+ .stream()
+ .filter(authorizationDetail -> consentedAuthorizationDetailIDs.contains(authorizationDetail.getId()))
+ .collect(Collectors.toSet());
+
+ return new AuthorizationDetails(consentedAuthorizationDetails);
+ }
+
+ public Optional getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
+ throws OAuthSystemException {
+
+ try {
+ return Optional
+ .ofNullable(super.authorizationDetailsDAO.getConsentIdByUserIdAndAppId(userId, appId, tenantId));
+ } catch (SQLException e) {
+ log.error(String.format("Error occurred while retrieving user consent by " +
+ "userId: %s and appId: %s. Caused by, ", userId, appId), e);
+ throw new OAuthSystemException("Error occurred while retrieving user consent", e);
+ }
+ }
+
+ private String getApplicationResourceIdFromClientId(final String clientId) throws IdentityOAuth2Exception {
+
+ final ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(clientId);
+ if (serviceProvider != null) {
+ return serviceProvider.getApplicationResourceId();
+ }
+ throw new IdentityOAuth2Exception("Unable to find a service provider for client Id: " + clientId);
+ }
+
+ private String getUserId(final AuthenticatedUser authenticatedUser) throws OAuthSystemException {
+ try {
+ return authenticatedUser.getUserId();
+ } catch (UserIdNotFoundException e) {
+ log.error("Error occurred while extracting userId from authenticated user. Caused by, ", e);
+ throw new OAuthSystemException(
+ "User id is not found for user: " + authenticatedUser.getLoggableMaskedUserId(), e);
+ }
+ }
+
+ private List generateAuthorizationDetailsConsentDTOs(
+ final String consentId, final AuthorizationDetails userConsentedAuthorizationDetails, final int tenantId) {
+
+ return userConsentedAuthorizationDetails.stream()
+ .map(authorizationDetail ->
+ new AuthorizationDetailsConsentDTO(consentId, authorizationDetail, true, tenantId))
+ .collect(Collectors.toList());
+ }
+
+ private Optional getConsentId(final AuthenticatedUser authenticatedUser, final String clientId,
+ final int tenantId)
+ throws OAuthSystemException, IdentityOAuth2Exception {
+
+ final String userId = this.getUserId(authenticatedUser);
+ final String appId = this.getApplicationResourceIdFromClientId(clientId);
+
+ return this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
new file mode 100644
index 0000000000..6b67f226d8
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
+import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * {@code AuthorizationDetailsValidator} class responsible for managing and validating authorization details.
+ */
+public class AuthorizationDetailsValidator {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsValidator.class);
+ private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
+
+ public AuthorizationDetailsValidator() {
+
+ this(AuthorizationDetailsProviderFactory.getInstance());
+ }
+
+ public AuthorizationDetailsValidator(AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory) {
+
+ this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
+ }
+
+ /**
+ * Retrieves and validates the authorization details for a given OAuth2 parameters context.
+ *
+ * @param oAuth2Parameters The OAuth2 parameters associated with the request.
+ * @param oAuthAppDO The OAuth application details.
+ * @param authenticatedUser The authenticated user information.
+ * @return An {@link AuthorizationDetails} object containing the validated authorization details.
+ */
+ public AuthorizationDetails getValidatedAuthorizationDetails(
+ final OAuth2Parameters oAuth2Parameters, final OAuthAppDO oAuthAppDO,
+ final AuthenticatedUser authenticatedUser) throws AuthorizationDetailsProcessingException {
+
+ final Set validatedAuthorizationDetails = new HashSet<>();
+ final Set authorizedAuthorizationDetailsTypes = this.getAuthorizedAuthorizationDetailsTypes(
+ oAuth2Parameters.getClientId(), oAuth2Parameters.getTenantDomain());
+ for (AuthorizationDetail authorizationDetail : oAuth2Parameters.getAuthorizationDetails().getDetails()) {
+
+ if (!isSupportedAuthorizationDetailType(authorizationDetail.getType())) {
+ throw new AuthorizationDetailsProcessingException(String.format(AuthorizationDetailsConstants
+ .TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT, authorizationDetail.getType()));
+ }
+
+ if (isAuthorizedAuthorizationDetail(authorizationDetail, authorizedAuthorizationDetailsTypes)) {
+
+ final AuthorizationDetailsContext authorizationDetailsContext = new AuthorizationDetailsContext(
+ oAuth2Parameters, oAuthAppDO, authenticatedUser, authorizationDetail);
+
+ if (isValidAuthorizationDetail(authorizationDetailsContext)) {
+ validatedAuthorizationDetails.add(getEnrichedAuthorizationDetail(authorizationDetailsContext));
+ }
+ }
+ }
+
+ return new AuthorizationDetails(validatedAuthorizationDetails);
+ }
+
+ private boolean isAuthorizedAuthorizationDetail(final AuthorizationDetail authorizationDetail,
+ final Set authorizedAuthorizationDetailsTypes) {
+
+ return authorizedAuthorizationDetailsTypes.contains(authorizationDetail.getType());
+ }
+
+ private boolean isSupportedAuthorizationDetailType(final String authorizationDetailType) {
+
+ return this.authorizationDetailsProviderFactory
+ .isSupportedAuthorizationDetailsType(authorizationDetailType);
+ }
+
+ /**
+ * Checks if the provided authorization details context is valid.
+ *
+ * @param authorizationDetailsContext The context containing authorization details.
+ * @return {@code true} if the authorization details are valid; {@code false} otherwise.
+ */
+ private boolean isValidAuthorizationDetail(final AuthorizationDetailsContext authorizationDetailsContext)
+ throws AuthorizationDetailsProcessingException {
+
+ Optional optionalProvider = this.authorizationDetailsProviderFactory
+ .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType());
+
+ if (optionalProvider.isPresent()) {
+
+ final ValidationResult validationResult = optionalProvider.get().validate(authorizationDetailsContext);
+ if (log.isDebugEnabled() && validationResult.isInvalid()) {
+
+ log.debug(String.format("Authorization details validation failed for type %s. Caused by, %s",
+ authorizationDetailsContext.getAuthorizationDetail().getType(), validationResult.getReason()));
+
+ }
+ return validationResult.isValid();
+ }
+ throw new AuthorizationDetailsProcessingException(String.format(
+ AuthorizationDetailsConstants.TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT,
+ authorizationDetailsContext.getAuthorizationDetail().getType()));
+ }
+
+ /**
+ * Enriches the authorization details using the provided context.
+ *
+ * @param authorizationDetailsContext The context containing authorization details.
+ * @return An enriched {@link AuthorizationDetail} object.
+ */
+ private AuthorizationDetail getEnrichedAuthorizationDetail(
+ final AuthorizationDetailsContext authorizationDetailsContext) {
+
+ return this.authorizationDetailsProviderFactory
+ .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType())
+ .map(authorizationDetailsService -> authorizationDetailsService.enrich(authorizationDetailsContext))
+ // If provider is missing, return the original authorization detail instance
+ .orElse(authorizationDetailsContext.getAuthorizationDetail());
+ }
+
+ /**
+ * Retrieves the set of authorized authorization types for the given client and tenant domain.
+ *
+ * @param clientID The client ID.
+ * @param tenantDomain The tenant domain.
+ * @return A set of strings representing the authorized authorization types.
+ */
+ private Set getAuthorizedAuthorizationDetailsTypes(final String clientID, final String tenantDomain) {
+
+// try {
+// final String appId = OAuth2Util
+// .getApplicationResourceIDByClientId(clientID, tenantDomain, this.applicationMgtService);
+//
+//// OAuth2ServiceComponentHolder.getInstance().getAuthorizedAPIManagementService()
+// .getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
+// } catch (IdentityOAuth2Exception e) {
+// throw new RuntimeException(e);
+// }
+ Set authorizedAuthorizationDetailsTypes = new HashSet<>();
+ authorizedAuthorizationDetailsTypes.add("payment_initiation");
+ return authorizedAuthorizationDetailsTypes;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProvider.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProvider.java
new file mode 100644
index 0000000000..aa05dec625
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProvider.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.core;
+
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
+import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
+
+/**
+ * The {@code AuthorizationDetailsProvider} interface defines a contract for implementing
+ * different types of authorization detail providers in a Service Provider Interface (SPI) setup.
+ *
+ * Implementing classes are expected to provide mechanisms to validate, enrich, and identify
+ * authorization details specific to various types.
+ *
+ *
+ * @see Java SPI
+ */
+public interface AuthorizationDetailsProvider {
+
+ /**
+ * Validates the provided authorization details context when a new Rich Authorization Request is received.
+ *
+ * This method is invoked once a new Rich Authorization Request is received to ensure that the
+ * authorization details are valid and meet the required criteria. The validation logic should
+ * be specific to the type of authorization details handled by the implementing class.
+ *
+ *
+ * @param authorizationDetailsContext the context containing the authorization details to be validated.
+ * @return a {@code ValidationResult} indicating the outcome of the validation process. Returns a valid result
+ * if the authorization details are correct and meet the criteria, otherwise returns an invalid result with an
+ * appropriate error message.
+ * @throws AuthorizationDetailsProcessingException if the validation fails and the authorization flow needs
+ * to be interrupted.
+ * @see AuthorizationDetailsContext
+ * @see ValidationResult
+ */
+ ValidationResult validate(AuthorizationDetailsContext authorizationDetailsContext)
+ throws AuthorizationDetailsProcessingException;
+
+ /**
+ * Retrieves the type of authorization details handled by this provider.
+ *
+ * Each implementation should return a unique type identifier that represents the kind of
+ * authorization details it processes. This identifier is used to differentiate between
+ * various providers in a service-oriented architecture.
+ *
+ *
+ * @return a {@code String} representing the type of authorization details managed by this provider
+ * @see AuthorizationDetail#getType()
+ */
+ String getType();
+
+ // The existing authorization detail that was previously accepted by the resource owner.
+ boolean isEqualOrSubset(AuthorizationDetail requestedAuthorizationDetail,
+ AuthorizationDetails existingAuthorizationDetails);
+
+ /**
+ *
+ * This method is invoked prior to presenting the consent UI to the user. Its purpose is to
+ * enhance or augment the authorization details, providing additional context or information
+ * that may be necessary for informed consent. This may include adding more descriptive
+ * information, default values, or other relevant details that are crucial for the user to
+ * understand the authorization request fully.
+ *
+ *
+ * It is also a responsibility of this method to generate a human-readable consent
+ * description from the provided authorization details, which will be displayed to the user for approval.
+ * The consent description should provide a clear, human-readable summary of the {@code authorization_details}
+ * object.
+ *
+ *
+ * This enrichment process aligns with the concepts outlined in
+ * RFC 9396,
+ * which describes the requirements for enriched authorization details to ensure clarity and transparency
+ * in consent management.
+ *
+ *
+ * @param authorizationDetailsContext the context containing the authorization details to be enriched.
+ * @return an enriched {@code AuthorizationDetail} object with additional information or context.
+ * This enriched object is intended to provide users with a clearer understanding of the
+ * authorization request when they are presented with the consent form.
+ * @see AuthorizationDetailsContext
+ * @see AuthorizationDetail
+ * @see AuthorizationDetail#setConsentDescription
+ * @see
+ * Enriched Authorization Details
+ */
+ AuthorizationDetail enrich(AuthorizationDetailsContext authorizationDetailsContext);
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
new file mode 100644
index 0000000000..123e3cc3dd
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.core;
+
+import org.wso2.carbon.identity.oauth2.rar.internal.AuthorizationDetailsDataHolder;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * A factory class to manage and provide instances of {@link AuthorizationDetailsProvider} Service Provider Interface.
+ * This class follows the Singleton pattern to ensure only one instance is created.
+ * It uses {@link ServiceLoader} to dynamically load and manage {@link AuthorizationDetailsProvider} implementations.
+ * Example usage:
+ *
{@code
+ * // Get a specific provider by type
+ * AuthorizationDetailsProviderFactory.getInstance()
+ * .getProviderByType("customer_information")
+ * .ifPresentOrElse(
+ * p -> log.debug("Provider for type " + type + ": " + p.getClass().getName()),
+ * () -> log.debug("No provider found for type " + type)
+ * );
+ * }
+ *
+ * @see AuthorizationDetailsProvider AuthorizationDetailsService
+ * @see
+ * Request Parameter "authorization_details"
+ * @since 7.0.26.9
+ */
+public class AuthorizationDetailsProviderFactory {
+
+ private static volatile AuthorizationDetailsProviderFactory instance;
+ private final Map supportedAuthorizationDetailsTypes;
+
+ /**
+ * Private constructor to initialize the factory.
+ * This constructor is intentionally private to prevent direct instantiation of the
+ * {@code AuthorizationDetailsProviderFactory} class.
+ * Instead, use the {@link #getInstance()} method to obtain the singleton instance.
+ */
+ private AuthorizationDetailsProviderFactory() {
+
+ this.supportedAuthorizationDetailsTypes = this.loadSupportedAuthorizationDetailsTypes();
+ }
+
+ /**
+ * Loads supported authorization details types from the provided {@link ServiceLoader}.
+ *
+ * @return Map of authorization details types with their corresponding services.
+ */
+ private Map loadSupportedAuthorizationDetailsTypes() {
+
+ return AuthorizationDetailsDataHolder.getInstance()
+ .getAuthorizationDetailsProviders()
+ .stream()
+ .collect(Collectors.toMap(AuthorizationDetailsProvider::getType, Function.identity()));
+ }
+
+ /**
+ * Provides the singleton instance of {@code AuthorizationDetailsProviderFactory}.
+ *
+ * @return Singleton instance of {@code AuthorizationDetailsProviderFactory}.
+ */
+ public static AuthorizationDetailsProviderFactory getInstance() {
+
+ if (instance == null) {
+ synchronized (AuthorizationDetailsProviderFactory.class) {
+ if (instance == null) {
+ instance = new AuthorizationDetailsProviderFactory();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Returns the {@link AuthorizationDetailsProvider} provider for the given type.
+ *
+ * @param type A supported authorization details type.
+ * @return {@link Optional} containing the {@link AuthorizationDetailsProvider} if present, otherwise empty.
+ * @see AuthorizationDetailsProvider#getType() getAuthorizationDetailsType
+ */
+ public Optional getProviderByType(final String type) {
+
+ return Optional.ofNullable(this.supportedAuthorizationDetailsTypes.get(type));
+ }
+
+ /**
+ * Checks if a given type has a valid service provider implementation.
+ *
+ * @param type The type to check.
+ * @return {@code true} if the type is supported, {@code false} otherwise.
+ * @see AuthorizationDetailsProvider AuthorizationDetailsService
+ */
+ public boolean isSupportedAuthorizationDetailsType(final String type) {
+
+ return this.supportedAuthorizationDetailsTypes.containsKey(type);
+ }
+
+ /**
+ * Returns a {@link Collections#unmodifiableSet} of all supported authorization details types.
+ * To be included as a supported authorization details type, there must be a custom implementation
+ * of the {@link AuthorizationDetailsProvider} Service Provider Interface (SPI) available in the classpath
+ * for the specified type.
+ *
+ * @return A set of supported authorization details types.
+ */
+ public Set getSupportedAuthorizationDetailTypes() {
+
+ return Collections.unmodifiableSet(this.supportedAuthorizationDetailsTypes.keySet());
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
new file mode 100644
index 0000000000..62a65d9859
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
@@ -0,0 +1,30 @@
+package org.wso2.carbon.identity.oauth2.rar.exception;
+
+/**
+ *
+ */
+public class AuthorizationDetailsProcessingException extends RuntimeException {
+
+ private static final long serialVersionUID = -206212512259482200L;
+
+ /**
+ * Constructs a new exception with an error message.
+ *
+ * @param message The detail message.
+ */
+ public AuthorizationDetailsProcessingException(String message) {
+
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the message and cause.
+ *
+ * @param message The detail message.
+ * @param cause The cause.
+ */
+ public AuthorizationDetailsProcessingException(String message, Throwable cause) {
+
+ super(message, cause);
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
new file mode 100644
index 0000000000..a35e8bd0ae
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
@@ -0,0 +1,61 @@
+package org.wso2.carbon.identity.oauth2.rar.handler;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONArray;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.token.handlers.response.AccessTokenResponseHandler;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class RARAccessTokenResponseHandler implements AccessTokenResponseHandler {
+ private static final ObjectMapper OBJECT_MAPPER = new JsonMapper();
+ private static final Log LOG = LogFactory.getLog(RARAccessTokenResponseHandler.class);
+
+ @Override
+// public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMessageContext tokReqMsgCtx)
+// throws IdentityOAuth2Exception {
+//
+// List authorizationDetails = AuthorizationDetailService.getInstance()
+// .getConsentedAuthorizationDetailsByAuthzCode(tokReqMsgCtx.getOauth2AccessTokenReqDTO()
+// .getAuthorizationCode());
+//
+// Map additionalAttributes = new HashMap<>();
+// if (isNotEmptyList(authorizationDetails)) {
+// additionalAttributes.put(AUTHORIZATION_DETAILS, convertToJsonArray(authorizationDetails));
+// }
+// return additionalAttributes;
+// }
+
+ public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMessageContext tokReqMsgCtx)
+ throws IdentityOAuth2Exception {
+
+ Map additionalAttributes = new HashMap<>();
+
+ return additionalAttributes;
+ }
+
+
+ private boolean isNotEmptyList(List list) {
+ return list != null && !list.isEmpty();
+ }
+
+ private JSONArray convertToJsonArray(List authorizationDetails) {
+ try {
+ return OBJECT_MAPPER.convertValue(OBJECT_MAPPER.writeValueAsString(authorizationDetails), JSONArray.class);
+ } catch (JsonProcessingException e) {
+ LOG.error("Serialization error. Caused by, ", e);
+ }
+ return new JSONArray(authorizationDetails);
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
new file mode 100644
index 0000000000..bd0c92f5f3
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.internal;
+
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Singleton class that holds rich authorization details data.
+ * This class uses the singleton design pattern to ensure there is only one instance
+ * managing the authorization details providers. The instance is lazily initialized
+ * with double-checked locking to ensure thread safety.
+ * The class provides methods to retrieve and set the authorization details data,
+ * which can be used in different parts of the application to manage rich authorization details.
+ */
+public class AuthorizationDetailsDataHolder {
+
+ private static volatile AuthorizationDetailsDataHolder instance;
+ private Set authorizationDetailsProviders;
+
+ /**
+ * Private constructor to prevent instantiation from outside the class.
+ */
+ private AuthorizationDetailsDataHolder() {
+
+ this.authorizationDetailsProviders = new HashSet<>();
+ }
+
+ /**
+ * Returns the singleton instance of {@link AuthorizationDetailsDataHolder}.
+ *
+ * This method uses double-checked locking to ensure that the instance is initialized
+ * only once and in a thread-safe manner. If the instance is not already created, it
+ * will be created and returned; otherwise, the existing instance will be returned.
+ *
+ * @return The singleton instance of {@link AuthorizationDetailsDataHolder}.
+ */
+ public static AuthorizationDetailsDataHolder getInstance() {
+
+ if (instance == null) {
+ synchronized (AuthorizationDetailsDataHolder.class) {
+ if (instance == null) {
+ instance = new AuthorizationDetailsDataHolder();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Returns the current set of {@link AuthorizationDetailsProvider} instances.
+ *
+ * This method provides access to the authorization details providers.
+ * The returned set can be used to query or modify the authorization details providers.
+ *
+ * @return A {@link Set} of {@link AuthorizationDetailsProvider} instances.
+ */
+ public Set getAuthorizationDetailsProviders() {
+
+ return this.authorizationDetailsProviders;
+ }
+
+ /**
+ * Sets the set of {@link AuthorizationDetailsProvider} instances to the provided value.
+ *
+ * This method replaces the current set of authorization details providers with the
+ * provided set. It can be used to update the list of providers that the application
+ * uses to manage authorization details.
+ *
+ * @param authorizationDetailsProviders The new {@link Set} of {@link AuthorizationDetailsProvider} instances.
+ */
+ public void setAuthorizationDetailsProviders(Set authorizationDetailsProviders) {
+
+ this.authorizationDetailsProviders = authorizationDetailsProviders;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
new file mode 100644
index 0000000000..2cd272dc71
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
+
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+/**
+ * Authorization Details OSGI service component.
+ */
+@Component(name = "org.wso2.carbon.identity.oauth.rar.internal.AuthorizationDetailsServiceComponent")
+public class AuthorizationDetailsServiceComponent {
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsServiceComponent.class);
+
+ @Activate
+ protected void activate(ComponentContext context) {
+
+ AuthorizationDetailsDataHolder.getInstance().setAuthorizationDetailsProviders(
+ loadAuthorizationDetailsProviders(ServiceLoader.load(AuthorizationDetailsProvider.class,
+ this.getClass().getClassLoader())));
+
+ log.debug("AuthorizationDetailsServiceComponent is activated");
+ }
+
+ @Deactivate
+ protected void deactivate(ComponentContext context) {
+
+ log.debug("AuthorizationDetailsServiceComponent is deactivated");
+ }
+
+ /**
+ * Loads supported authorization details providers from the provided {@link ServiceLoader}.
+ *
+ * @param serviceLoader {@link ServiceLoader} for {@link AuthorizationDetailsProvider}.
+ * @return Set of authorization details providers.
+ */
+ private Set loadAuthorizationDetailsProviders(
+ final ServiceLoader serviceLoader) {
+
+ return StreamSupport.stream(serviceLoader.spliterator(), false)
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
new file mode 100644
index 0000000000..00cd4de10d
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.model;
+
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
+
+import java.util.Objects;
+
+/**
+ * Represents the context for rich authorization requests in an OAuth2 flow.
+ *
+ * This class holds relevant details such as OAuth2 parameters, application details, the authenticated user,
+ * and specific authorization details. It is immutable to ensure that the context remains consistent throughout its use.
+ *
+ */
+public class AuthorizationDetailsContext {
+
+ private final OAuth2Parameters oAuth2Parameters;
+ private final OAuthAppDO oAuthAppDO;
+ private final AuthenticatedUser authenticatedUser;
+ private final AuthorizationDetail authorizationDetail;
+
+ /**
+ * Constructs a new {@code AuthorizationDetailsContext}.
+ *
+ * This constructor ensures that all necessary details for an authorization context are provided.
+ *
+ *
+ * @param oAuth2Parameters the OAuth2 parameters.
+ * @param oAuthAppDO the OAuth application details.
+ * @param authenticatedUser the authenticated user.
+ * @param authorizationDetail the specific authorization detail.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public AuthorizationDetailsContext(final OAuth2Parameters oAuth2Parameters, final OAuthAppDO oAuthAppDO,
+ final AuthenticatedUser authenticatedUser,
+ final AuthorizationDetail authorizationDetail) {
+ this.oAuth2Parameters = Objects.requireNonNull(oAuth2Parameters, "oAuth2Parameters cannot be null");
+ this.oAuthAppDO = Objects.requireNonNull(oAuthAppDO, "oAuthAppDO cannot be null");
+ this.authenticatedUser = Objects.requireNonNull(authenticatedUser, "authenticatedUser cannot be null");
+ this.authorizationDetail = Objects.requireNonNull(authorizationDetail, "authorizationDetail cannot be null");
+ }
+
+ /**
+ * Returns the {@code AuthorizationDetail} instance.
+ *
+ * @return the {@link AuthorizationDetail} instance.
+ */
+ public AuthorizationDetail getAuthorizationDetail() {
+ return this.authorizationDetail;
+ }
+
+ /**
+ * Returns the OAuth2 parameters.
+ *
+ * @return the {@link OAuth2Parameters} instance.
+ */
+ public OAuth2Parameters getOAuth2Parameters() {
+ return this.oAuth2Parameters;
+ }
+
+ /**
+ * Returns the OAuth application details.
+ *
+ * @return the {@link OAuthAppDO} instance.
+ */
+ public OAuthAppDO getoAuthAppDO() {
+ return this.oAuthAppDO;
+ }
+
+ /**
+ * Returns the authenticated user.
+ *
+ * @return the {@link AuthenticatedUser} instance.
+ */
+ public AuthenticatedUser getAuthenticatedUser() {
+ return this.authenticatedUser;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/ValidationResult.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/ValidationResult.java
new file mode 100644
index 0000000000..5bf5c9ed0c
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/ValidationResult.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.model;
+
+import java.util.Map;
+
+/**
+ * Represents the result of authorization details validation operation, encapsulating the status, reason for failure,
+ * and additional metadata.
+ *
+ * This class provides a way to create validation results that can be either valid or invalid, with
+ * optional metadata for further context.
+ *
+ */
+public class ValidationResult {
+
+ private final boolean status;
+ private final String reason;
+ private final Map meta;
+
+ /**
+ * Constructs a new {@code ValidationResult}.
+ *
+ * @param status whether the validation is successful.
+ * @param reason the reason for validation failure, if applicable.
+ * @param meta additional metadata related to the validation result.
+ */
+ public ValidationResult(final boolean status, final String reason, final Map meta) {
+ this.status = status;
+ this.reason = reason;
+ this.meta = meta;
+ }
+
+ /**
+ * Creates a new {@code ValidationResult} indicating a successful validation.
+ *
+ * This method should be used to indicate that the validation passed without any issues.
+ *
+ *
+ * @return a {@code ValidationResult} indicating a successful validation.
+ */
+ public static ValidationResult valid() {
+ return new ValidationResult(true, null, null);
+ }
+
+ /**
+ * Creates a new {@code ValidationResult} indicating a failed validation with a specified reason.
+ *
+ * This method should be used to indicate that the validation failed and provide a reason for the failure.
+ *
+ *
+ * @param reason the reason why the validation failed.
+ * @return a {@code ValidationResult} indicating a failed validation.
+ */
+ public static ValidationResult invalid(final String reason) {
+ return new ValidationResult(false, reason, null);
+ }
+
+ /**
+ * Creates a new {@code ValidationResult} indicating a failed validation with a specified reason and metadata.
+ *
+ * This method should be used to indicate that the validation failed, provide a reason, and include
+ * additional context or metadata.
+ *
+ *
+ * @param reason the reason why the validation failed.
+ * @param meta additional metadata related to the validation result.
+ * @return a {@code ValidationResult} indicating a failed validation with metadata.
+ */
+ public static ValidationResult invalid(final String reason, final Map meta) {
+ return new ValidationResult(false, reason, meta);
+ }
+
+ /**
+ * Returns whether the validation was successful.
+ *
+ * @return {@code true} if the validation was successful, {@code false} otherwise.
+ */
+ public boolean isValid() {
+ return this.status;
+ }
+
+ /**
+ * Returns whether the validation failed.
+ *
+ * @return {@code true} if the validation failed, {@code false} otherwise.
+ */
+ public boolean isInvalid() {
+ return !this.isValid();
+ }
+
+ /**
+ * Returns the reason for validation failure, if applicable.
+ *
+ * @return the reason for validation failure, or {@code null} if the validation was successful.
+ */
+ public String getReason() {
+ return this.reason;
+ }
+
+ /**
+ * Returns additional metadata related to the validation result.
+ *
+ * @return an unmodifiable map of metadata, or an empty map if no metadata is present.
+ */
+ public Map getMeta() {
+ return this.meta;
+ }
+
+ @Override
+ public String toString() {
+ return "ValidationResult{" +
+ "status=" + status +
+ ", reason='" + reason + '\'' +
+ ", meta=" + meta +
+ '}';
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
new file mode 100644
index 0000000000..34af49529c
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.util;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+
+/**
+ * Utility class for handling and validating authorization details in OAuth2 requests.
+ */
+public class AuthorizationDetailsUtils {
+
+ /**
+ * Determines if the given {@link OAuth2Parameters} object contains
+ * {@link org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails AuthorizationDetails}.
+ *
+ * @param oAuth2Parameters The requested OAuth2 parameters to check.
+ * @return {@code true} if the OAuth2 parameters contain non-empty authorization details array,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Parameters) {
+
+ return oAuth2Parameters.getAuthorizationDetails() != null &&
+ !oAuth2Parameters.getAuthorizationDetails().getDetails().isEmpty();
+ }
+
+ /**
+ * Determines if the given {@link OAuthAuthzRequest} object contains {@code authorization_details}.
+ *
+ * @param oauthRequest The OAuth Authorization Request to check.
+ * @return {@code true} if the OAuth authorization request contains a non-blank authorization details parameter,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuthAuthzRequest oauthRequest) {
+
+ return StringUtils.isNotBlank(oauthRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 68e661c2aa..92f3e93171 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -258,6 +258,11 @@
org.wso2.orbit.javax.xml.bind
jaxb-api
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar.common
+ provided
+
org.testng
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/IdentityOAuth2AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/IdentityOAuth2AuthorizationDetailsService.java
new file mode 100644
index 0000000000..21ac2f67fd
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/IdentityOAuth2AuthorizationDetailsService.java
@@ -0,0 +1,134 @@
+package org.wso2.carbon.identity.oauth2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
+import org.wso2.carbon.identity.oauth2.model.AuthzCodeDO;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.common.dao.AuthorizationDetailsDAO;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+
+import java.sql.SQLException;
+import java.util.Objects;
+
+/**
+ * IdentityOAuth2AuthorizationDetailsService is responsible for managing and handling OAuth2 authorization details,
+ * specifically in the context of rich authorization requests.
+ *
+ * This class integrates with the {@link AuthorizationDetailsDAO} to persist these details in the underlying data store.
+ * It also provides utility methods to check if a request contains rich authorization details.
+ *
+ *
+ * @see AuthorizationDetailsDAO
+ * @see AuthorizationDetails
+ */
+public class IdentityOAuth2AuthorizationDetailsService {
+
+ private static final Log log = LogFactory.getLog(IdentityOAuth2AuthorizationDetailsService.class);
+ protected final AuthorizationDetailsDAO authorizationDetailsDAO;
+
+ /**
+ * Default constructor that initializes the service with the default {@link AuthorizationDetailsDAO}.
+ *
+ * This constructor uses the default DAO provided by the {@link OAuthTokenPersistenceFactory}
+ * to handle the persistence of authorization details.
+ *
+ */
+ public IdentityOAuth2AuthorizationDetailsService() {
+
+ this(OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO());
+ }
+
+ /**
+ * Constructor that initializes the service with a given {@link AuthorizationDetailsDAO}.
+ *
+ * @param authorizationDetailsDAO The {@link AuthorizationDetailsDAO} instance to be used for
+ * handling authorization details persistence. Must not be {@code null}.
+ */
+ public IdentityOAuth2AuthorizationDetailsService(final AuthorizationDetailsDAO authorizationDetailsDAO) {
+
+ this.authorizationDetailsDAO = Objects
+ .requireNonNull(authorizationDetailsDAO, "AuthorizationDetailsDAO must not be null");
+ }
+
+ /**
+ * Determines if the given {@link OAuthAuthzReqMessageContext} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuthAuthzReqMessageContext The requested OAuthAuthzReqMessageContext to check.
+ * @return {@code true} if the OAuthAuthzReqMessageContext contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
+
+ return isRichAuthorizationRequest(oAuthAuthzReqMessageContext.getAuthorizationDetails());
+ }
+
+ /**
+ * Determines if the request is a rich authorization request using provided {@link AuthorizationDetails} object.
+ *
+ * This method checks if the specified {@link AuthorizationDetails} instance is not {@code null}
+ * and has a non-empty details set.
+ *
+ * @param authorizationDetails The {@link AuthorizationDetails} to check.
+ * @return {@code true} if the {@link AuthorizationDetails} is not {@code null} and has a non-empty details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final AuthorizationDetails authorizationDetails) {
+
+ return authorizationDetails != null && !authorizationDetails.getDetails().isEmpty();
+ }
+
+ /**
+ * Determines if the given {@link OAuth2Parameters} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuth2Parameters The requested OAuth2Parameters to check.
+ * @return {@code true} if the OAuth2Parameters contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Parameters) {
+
+ return isRichAuthorizationRequest(oAuth2Parameters.getAuthorizationDetails());
+ }
+
+ /**
+ * Stores the OAuth2 code authorization details if the request is a rich authorization request.
+ *
+ * This method checks whether the given {@link OAuthAuthzReqMessageContext} contains {@link AuthorizationDetails}.
+ * If it does, it retrieves the tenant ID from the request context and stores the authorization
+ * details using the {@link AuthorizationDetailsDAO}.
+ *
+ *
+ * @param authzCodeDO The {@link AuthzCodeDO} object containing the authorization code details.
+ * @param oAuthAuthzReqMessageContext The {@link OAuthAuthzReqMessageContext} containing the request context.
+ * @throws IdentityOAuth2Exception If an error occurs while storing the authorization details.
+ */
+ public void storeOAuth2CodeAuthorizationDetails(final AuthzCodeDO authzCodeDO,
+ final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ if (!isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
+ log.debug("Request is not a rich authorization request. Skipping storage of code authorization details.");
+ return;
+ }
+
+ try {
+ final int tenantID = OAuth2Util.getTenantId(
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain());
+ // Storing the authorization details.
+ this.authorizationDetailsDAO.addOAuth2CodeAuthorizationDetails(
+ authzCodeDO.getAuthzCodeId(),
+ oAuthAuthzReqMessageContext.getAuthorizationDetails(),
+ tenantID);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Successfully stored OAuth2 Code authorization details for code Id: " +
+ authzCodeDO.getAuthzCodeId());
+ }
+ } catch (SQLException e) {
+ log.error("Error occurred while storing OAuth2 Code authorization details. Caused by, ", e);
+ throw new IdentityOAuth2Exception("Error occurred while storing authorization details", e);
+ }
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
index c2c0d44ecf..a654475ddb 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
@@ -676,7 +676,7 @@ private boolean isInvalidResponseType(OAuth2AuthorizeReqDTO authzReqDTO, OAuth2A
return false;
}
- private OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
+ public OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
InvalidOAuthClientException {
OAuthAppDO oAuthAppDO = AppInfoCache.getInstance().getValueFromCache(authzReqDTO.getConsumerKey());
if (oAuthAppDO != null) {
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
index 35d57287f7..2df67714c2 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
@@ -19,6 +19,7 @@
package org.wso2.carbon.identity.oauth2.authz;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
import java.io.Serializable;
import java.util.Properties;
@@ -56,6 +57,8 @@ public class OAuthAuthzReqMessageContext implements Serializable {
private Properties properties = new Properties();
+ private AuthorizationDetails authorizationDetails;
+
public OAuthAuthzReqMessageContext(OAuth2AuthorizeReqDTO authorizationReqDTO) {
this.authorizationReqDTO = authorizationReqDTO;
@@ -212,4 +215,26 @@ public void setSubjectTokenFlow(boolean subjectTokenFlow) {
isSubjectTokenFlow = subjectTokenFlow;
}
+
+ /**
+ * Retrieves the current authorization details.
+ *
+ * @return the {@link AuthorizationDetails} instance representing the current authorization information.
+ * If no authorization details are available, it will return {@code null}.
+ */
+ public AuthorizationDetails getAuthorizationDetails() {
+
+ return this.authorizationDetails;
+ }
+
+ /**
+ * Sets the authorization details.
+ * This method updates the authorization details with the provided {@link AuthorizationDetails} instance.
+ *
+ * @param authorizationDetails the {@link AuthorizationDetails} to set.
+ */
+ public void setAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ this.authorizationDetails = authorizationDetails;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
index bc1b5a78bb..287d2d8b57 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
@@ -32,6 +32,7 @@
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2AuthorizationDetailsService;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
@@ -59,6 +60,7 @@ public abstract class AbstractResponseTypeHandler implements ResponseTypeHandler
protected boolean cacheEnabled;
protected OAuthCache oauthCache;
private OAuthCallbackManager callbackManager;
+ protected IdentityOAuth2AuthorizationDetailsService identityOAuth2AuthorizationDetailsService;
@Override
public void init() throws IdentityOAuth2Exception {
@@ -68,6 +70,7 @@ public void init() throws IdentityOAuth2Exception {
if (cacheEnabled) {
oauthCache = OAuthCache.getInstance();
}
+ this.identityOAuth2AuthorizationDetailsService = new IdentityOAuth2AuthorizationDetailsService();
}
@Override
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/CodeResponseTypeHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/CodeResponseTypeHandler.java
index adb9dfefd1..489226250f 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/CodeResponseTypeHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/CodeResponseTypeHandler.java
@@ -47,6 +47,8 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx
AuthzCodeDO authorizationCode =
ResponseTypeHandlerUtil.generateAuthorizationCode(oauthAuthzMsgCtx, cacheEnabled);
+ super.identityOAuth2AuthorizationDetailsService
+ .storeOAuth2CodeAuthorizationDetails(authorizationCode, oauthAuthzMsgCtx);
String sessionDataKey = oauthAuthzMsgCtx.getAuthorizationReqDTO().getSessionDataKey();
if (log.isDebugEnabled()) {
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
index c90c4285e6..68aa46f7d8 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
@@ -21,6 +21,8 @@
package org.wso2.carbon.identity.oauth2.dao;
import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
+import org.wso2.carbon.identity.oauth2.rar.common.dao.AuthorizationDetailsDAO;
+import org.wso2.carbon.identity.oauth2.rar.common.dao.AuthorizationDetailsDAOImpl;
import org.wso2.carbon.identity.openidconnect.dao.CacheBackedScopeClaimMappingDAOImpl;
import org.wso2.carbon.identity.openidconnect.dao.RequestObjectDAO;
import org.wso2.carbon.identity.openidconnect.dao.RequestObjectDAOImpl;
@@ -40,6 +42,7 @@ public class OAuthTokenPersistenceFactory {
private ScopeClaimMappingDAO scopeClaimMappingDAO;
private TokenBindingMgtDAO tokenBindingMgtDAO;
private OAuthUserConsentedScopesDAO oauthUserConsentedScopesDAO;
+ private final AuthorizationDetailsDAO authorizationDetailsDAO;
public OAuthTokenPersistenceFactory() {
@@ -51,6 +54,7 @@ public OAuthTokenPersistenceFactory() {
this.scopeClaimMappingDAO = new CacheBackedScopeClaimMappingDAOImpl();
this.tokenBindingMgtDAO = new TokenBindingMgtDAOImpl();
this.oauthUserConsentedScopesDAO = new CacheBackedOAuthUserConsentedScopesDAOImpl();
+ this.authorizationDetailsDAO = new AuthorizationDetailsDAOImpl();
}
public static OAuthTokenPersistenceFactory getInstance() {
@@ -107,4 +111,17 @@ public OAuthUserConsentedScopesDAO getOAuthUserConsentedScopesDAO() {
return oauthUserConsentedScopesDAO;
}
+
+ /**
+ * Retrieves the DAO for authorization details.
+ *
+ * This method returns an {@link AuthorizationDetailsDAO} singleton instance that provides access to the
+ * {@link org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails} data. This DAO is used to interact
+ * with the underlying data store to fetch and manipulate authorization information.
+ *
+ * @return the {@link AuthorizationDetailsDAO} instance that provides access to authorization details data.
+ */
+ public AuthorizationDetailsDAO getAuthorizationDetailsDAO() {
+ return this.authorizationDetailsDAO;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/OAuth2Parameters.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/OAuth2Parameters.java
index 5bc77e5bea..868a5ff164 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/OAuth2Parameters.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/OAuth2Parameters.java
@@ -18,6 +18,8 @@
package org.wso2.carbon.identity.oauth2.model;
+import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -55,6 +57,7 @@ public class OAuth2Parameters implements Serializable {
private boolean isRequestObjectFlow;
private boolean isMtlsRequest;
private String requestedSubjectId;
+ private AuthorizationDetails authorizationDetails;
public String getRequestedSubjectId() {
@@ -328,4 +331,26 @@ public void setIsMtlsRequest(boolean isMtlsRequest) {
this.isMtlsRequest = isMtlsRequest;
}
+
+ /**
+ * Retrieves the current authorization details.
+ *
+ * @return the {@link AuthorizationDetails} instance representing the current authorization information.
+ * If no authorization details are available, it will return {@code null}.
+ */
+ public AuthorizationDetails getAuthorizationDetails() {
+
+ return this.authorizationDetails;
+ }
+
+ /**
+ * Sets the authorization details.
+ * This method updates the authorization details with the provided {@link AuthorizationDetails} instance.
+ *
+ * @param authorizationDetails the {@link AuthorizationDetails} to set.
+ */
+ public void setAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ this.authorizationDetails = authorizationDetails;
+ }
}
diff --git a/pom.xml b/pom.xml
index 93aaedf6c6..278ca1bfc9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,8 @@
features/org.wso2.carbon.identity.oauth.server.feature
features/org.wso2.carbon.identity.oauth.ui.feature
features/org.wso2.carbon.identity.oauth.dcr.server.feature
+ components/org.wso2.carbon.identity.oauth.rar.common
+ components/org.wso2.carbon.identity.oauth.rar
@@ -402,6 +404,11 @@
gson
${com.google.code.gson.version}
+
+ com.google.auto.service
+ auto-service
+ ${com.google.auto.service.version}
+
@@ -547,6 +554,16 @@
org.wso2.carbon.identity.oauth.extension
${project.version}
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar
+ ${project.version}
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar.common
+ ${project.version}
+
@@ -994,6 +1011,7 @@
2.4.7
5.2
9.2
+ 1.1.1
5.1.2
From f7544ce0bcef1945b2015994e49b7e8cc8fb9c1a Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 26 Jul 2024 17:10:34 +0530
Subject: [PATCH 02/28] Accept and persist authorization_details of token
request - Accept 'authorization_details' field in the token request - Persist
access token authorization details in the database - Moving common logic from
oauth.rar.common module to a new rar package within oauth module - Adds RAR
support for hybrid authorization flows
---
.../identity/oauth/common/OAuthConstants.java | 4 +
.../endpoint/authz/OAuth2AuthzEndpoint.java | 90 ++-
.../AuthorizationDetailsServiceFactory.java | 47 ++
.../endpoint/token/OAuth2TokenEndpoint.java | 16 +
.../oauth/endpoint/util/EndpointUtil.java | 30 +-
.../src/main/webapp/WEB-INF/cxf-servlet.xml | 2 +
.../pom.xml | 60 --
.../common/dao/AuthorizationDetailsDAO.java | 69 ---
.../dto/AuthorizationDetailsCodeDTO.java | 22 -
.../dto/AuthorizationDetailsConsentDTO.java | 38 --
.../common/dto/AuthorizationDetailsDTO.java | 53 --
.../pom.xml | 44 +-
.../rar/AuthorizationDetailsService.java | 278 ---------
.../rar/AuthorizationDetailsValidator.java | 171 ------
.../rar/dao/AuthorizationDetailsDAO.java | 125 ++++
.../rar}/dao/AuthorizationDetailsDAOImpl.java | 156 +++--
.../identity/oauth2/rar}/dao/SQLQueries.java | 35 +-
.../dto/AuthorizationDetailsConsentDTO.java | 67 +++
.../rar/dto/AuthorizationDetailsDTO.java | 98 +++
.../rar/dto/AuthorizationDetailsTokenDTO.java | 51 ++
...thorizationDetailsProcessingException.java | 30 -
.../RARAccessTokenResponseHandler.java | 61 --
.../AuthorizationDetailsDataHolder.java | 94 ---
.../AuthorizationDetailsServiceComponent.java | 69 ---
.../rar}/model/AuthorizationDetail.java | 61 +-
.../rar}/model/AuthorizationDetails.java | 39 +-
.../model/AuthorizationDetailsContext.java | 98 ---
.../util/AuthorizationDetailsCommonUtils.java | 76 ++-
.../util/AuthorizationDetailsConstants.java | 2 +-
.../rar/util/AuthorizationDetailsUtils.java | 56 --
.../org.wso2.carbon.identity.oauth/pom.xml | 2 +-
...tityOAuth2AuthorizationDetailsService.java | 134 -----
.../authz/AuthorizationHandlerManager.java | 22 +
.../authz/OAuthAuthzReqMessageContext.java | 2 +-
.../handlers/AbstractResponseTypeHandler.java | 4 +-
.../handlers/CodeResponseTypeHandler.java | 2 -
.../util/ResponseTypeHandlerUtil.java | 3 +
.../dao/OAuthTokenPersistenceFactory.java | 4 +-
.../oauth2/dto/OAuth2AccessTokenReqDTO.java | 25 +
.../oauth2/dto/OAuth2AuthorizeReqDTO.java | 24 +
.../oauth2/dto/OAuth2AuthorizeRespDTO.java | 25 +
.../internal/OAuth2ServiceComponent.java | 9 +
.../OAuth2ServiceComponentHolder.java | 32 +-
.../oauth2/model/OAuth2Parameters.java | 2 +-
.../rar/AuthorizationDetailsService.java | 558 ++++++++++++++++++
.../core/AuthorizationDetailsProcessor.java} | 30 +-
.../AuthorizationDetailsProviderFactory.java | 39 +-
...thorizationDetailsProcessingException.java | 37 ++
.../model/AuthorizationDetailsContext.java | 154 +++++
.../token/AccessTokenResponseRARHandler.java | 49 ++
.../token/IntrospectionRARDataProvider.java | 118 ++++
.../token/JWTAccessTokenRARClaimProvider.java | 70 +++
.../rar/util/AuthorizationDetailsUtils.java | 341 +++++++++++
.../AuthorizationDetailsValidator.java | 62 ++
.../DefaultAuthorizationDetailsValidator.java | 289 +++++++++
.../provider/SuccessResponseDTO.java | 23 +
.../impl/FragmentResponseModeProvider.java | 10 +
.../oauth2/token/AccessTokenIssuer.java | 37 ++
.../token/OAuthTokenReqMessageContext.java | 25 +
.../AbstractAuthorizationGrantHandler.java | 27 +
.../grant/AuthorizationCodeGrantHandler.java | 5 +-
.../handlers/grant/RefreshGrantHandler.java | 3 +
pom.xml | 6 -
63 files changed, 2761 insertions(+), 1454 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/dao/AuthorizationDetailsDAOImpl.java (64%)
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/dao/SQLQueries.java (58%)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/model/AuthorizationDetail.java (91%)
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/model/AuthorizationDetails.java (80%)
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/util/AuthorizationDetailsCommonUtils.java (68%)
rename components/{org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common => org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar}/util/AuthorizationDetailsConstants.java (96%)
delete mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
delete mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/IdentityOAuth2AuthorizationDetailsService.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
rename components/{org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProvider.java => org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessor.java} (75%)
rename components/{org.wso2.carbon.identity.oauth.rar => org.wso2.carbon.identity.oauth}/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java (75%)
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
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 57e7feac1e..78437a236b 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
@@ -749,6 +749,9 @@ public static class ActionIDs {
public static final String VALIDATE_EXISTING_CONSENT = "validate-existing-consent";
public static final String GENERATE_INTROSPECTION_RESPONSE = "generate-introspect-response";
public static final String RECEIVE_REVOKE_REQUEST = "receive-revoke-request";
+ public static final String VALIDATE_AUTHORIZATION_DETAILS = "validate-authorization-details";
+ public static final String VALIDATE_AUTHORIZATION_DETAILS_BEFORE_CONSENT
+ = "validate-authorization-details-before-consent";
}
/**
@@ -768,6 +771,7 @@ public static class InputKeys {
public static final String CALLBACK_URI = "callback URI";
public static final String PROMPT = "prompt";
public static final String APP_STATE = "app state";
+ public static final String REQUESTED_AUTHORIZATION_DETAILS = "requested authorization details";
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
index 47f2f21f5b..6c3a897d52 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
@@ -116,10 +116,10 @@
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ScopeException;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2UnauthorizedScopeException;
import org.wso2.carbon.identity.oauth2.OAuth2Service;
import org.wso2.carbon.identity.oauth2.RequestObjectException;
-import org.wso2.carbon.identity.oauth2.authz.AuthorizationHandlerManager;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext;
import org.wso2.carbon.identity.oauth2.device.api.DeviceAuthService;
@@ -136,10 +136,9 @@
import org.wso2.carbon.identity.oauth2.model.HttpRequestHeaderHandler;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
-import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsValidator;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.responsemode.provider.AuthorizationResponseDTO;
import org.wso2.carbon.identity.oauth2.responsemode.provider.ResponseModeProvider;
@@ -1717,13 +1716,12 @@ private void storeUserConsent(OAuthMessage oAuthMessage, String consent) throws
if (approvedAlways) {
OpenIDConnectUserRPStore.getInstance().putUserRPToStore(loggedInUser, applicationName,
true, clientId);
- final AuthorizationDetails userConsentedAuthorizationDetails =
- authorizationDetailsService.getUserConsentedAuthorizationDetails(
- oAuthMessage.getRequest().getParameterMap(), oauth2Params);
+ final AuthorizationDetails userConsentedAuthorizationDetails = AuthorizationDetailsUtils
+ .extractAuthorizationDetailsFromRequest(oAuthMessage.getRequest(), oauth2Params);
if (hasPromptContainsConsent(oauth2Params)) {
EndpointUtil.storeOAuthScopeConsent(loggedInUser, oauth2Params, true);
- authorizationDetailsService.storeOrReplaceUserConsentedAuthorizationDetails(loggedInUser,
+ authorizationDetailsService.replaceUserConsentedAuthorizationDetails(loggedInUser,
clientId, oauth2Params, userConsentedAuthorizationDetails);
} else {
EndpointUtil.storeOAuthScopeConsent(loggedInUser, oauth2Params, false);
@@ -1868,6 +1866,7 @@ private OAuthResponse handleSuccessAuthorization(OAuthMessage oAuthMessage, OIDC
if (isResponseTypeNotIdTokenOrNone(responseType, authzRespDTO)) {
setAccessToken(authzRespDTO, builder, authorizationResponseDTO);
setScopes(authzRespDTO, builder, authorizationResponseDTO);
+ setAuthorizationDetails(authzRespDTO, builder, authorizationResponseDTO);
}
if (isSubjectTokenFlow(responseType, authzRespDTO)) {
setSubjectToken(authzRespDTO, builder, authorizationResponseDTO);
@@ -2606,9 +2605,11 @@ private String populateOauthParameters(OAuth2Parameters params, OAuthMessage oAu
}
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oauthRequest)) {
+
final String authorizationDetailsJson = oauthRequest
.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS);
- params.setAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
+ params.setAuthorizationDetails(AuthorizationDetailsUtils
+ .generateAndAssignUniqueIDs(authorizationDetailsJson));
}
handleMaxAgeParameter(oauthRequest, params);
@@ -3015,7 +3016,7 @@ private String doUserAuthorization(OAuthMessage oAuthMessage, String sessionData
}
try {
- validateAuthorizationDetailsBeforeConsent(oAuthMessage, oauth2Params, authzReqDTO);
+ validateAuthorizationDetailsBeforeConsent(oAuthMessage, oauth2Params);
} catch (AuthorizationDetailsProcessingException e) {
log.debug("Error occurred while validating authorization details. Caused by, ", e);
@@ -3728,6 +3729,9 @@ private boolean isUserAlreadyApproved(OAuth2Parameters oauth2Params, Authenticat
} catch (IdentityOAuth2ScopeException | IdentityOAuthAdminException e) {
throw new OAuthSystemException("Error occurred while checking user has already approved the consent " +
"required OAuth scopes.", e);
+ } catch (IdentityOAuth2Exception e) {
+ throw new OAuthSystemException("Error occurred while checking user has already approved the consent " +
+ "required authorization details.", e);
}
}
@@ -3820,6 +3824,7 @@ private OAuth2AuthorizeReqDTO buildAuthRequest(OAuth2Parameters oauth2Params, Se
authzReqDTO.setState(oauth2Params.getState());
authzReqDTO.setHttpServletRequestWrapper(new HttpServletRequestWrapper(request));
authzReqDTO.setRequestedSubjectId(oauth2Params.getRequestedSubjectId());
+ authzReqDTO.setAuthorizationDetails(oauth2Params.getAuthorizationDetails());
if (sessionDataCacheEntry.getParamMap() != null && sessionDataCacheEntry.getParamMap().get(OAuthConstants
.AMR) != null) {
@@ -4808,14 +4813,12 @@ private Response handleUnsupportedGrantForApiBasedAuth() {
*
* @param oAuthMessage The {@link OAuthMessage} containing the authorization request details.
* @param oAuth2Parameters The {@link OAuth2Parameters} object holding the parameters of the OAuth request.
- * @param oAuth2AuthorizeReqDTO The {@link OAuth2AuthorizeReqDTO} object containing the authorization request.
- * @throws OAuthSystemException If there is an error during the validation process.
* @throws AuthorizationDetailsProcessingException If there is an error processing the authorization details.
+ * @throws OAuthSystemException If there is an error during the validation process.
*/
private void validateAuthorizationDetailsBeforeConsent(final OAuthMessage oAuthMessage,
- final OAuth2Parameters oAuth2Parameters,
- final OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO)
- throws OAuthSystemException, AuthorizationDetailsProcessingException {
+ final OAuth2Parameters oAuth2Parameters)
+ throws AuthorizationDetailsProcessingException, OAuthSystemException {
if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2Parameters)) {
log.debug("Authorization request is not a rich authorization request. Skipping validation.");
@@ -4823,26 +4826,61 @@ private void validateAuthorizationDetailsBeforeConsent(final OAuthMessage oAuthM
}
try {
- final OAuthAppDO oAuthAppDO = AuthorizationHandlerManager.getInstance()
- .getAppInformation(oAuth2AuthorizeReqDTO);
+ if (LoggerUtils.isDiagnosticLogsEnabled()) {
+ DiagnosticLog.DiagnosticLogBuilder diagnosticLogBuilder = new DiagnosticLog.DiagnosticLogBuilder(
+ OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE,
+ OAuthConstants.LogConstants.ActionIDs.VALIDATE_AUTHORIZATION_DETAILS_BEFORE_CONSENT);
+ diagnosticLogBuilder.inputParam(LogConstants.InputKeys.CLIENT_ID, oAuth2Parameters.getClientId())
+ .inputParam(LogConstants.InputKeys.APPLICATION_NAME, oAuth2Parameters.getApplicationName())
+ .inputParam("authorization details to be validated",
+ oAuth2Parameters.getAuthorizationDetails().toSet())
+ .resultStatus(DiagnosticLog.ResultStatus.SUCCESS)
+ .resultMessage("authorization details validation started")
+ .logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION);
+ LoggerUtils.triggerDiagnosticLogEvent(diagnosticLogBuilder);
+ }
+
+ final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext =
+ oAuthMessage.getSessionDataCacheEntry().getAuthzReqMsgCtx();
+
// Validate the authorization details
- final AuthorizationDetails validatedAuthorizationDetails = new AuthorizationDetailsValidator()
- .getValidatedAuthorizationDetails(oAuth2Parameters, oAuthAppDO, oAuth2AuthorizeReqDTO.getUser());
+ final AuthorizationDetails validatedAuthorizationDetails = OAuth2ServiceComponentHolder.getInstance()
+ .getAuthorizationDetailsValidator()
+ .getValidatedAuthorizationDetails(oAuthAuthzReqMessageContext);
- if (log.isDebugEnabled()) {
- log.debug("Authorization details validated successfully for user: "
- + oAuth2AuthorizeReqDTO.getUser().getLoggableMaskedUserId());
- }
// update oAuth2Parameters with validated authorization details
oAuth2Parameters.setAuthorizationDetails(validatedAuthorizationDetails);
// Update the authorization message context with validated authorization details
- OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext =
- oAuthMessage.getSessionDataCacheEntry().getAuthzReqMsgCtx();
oAuthAuthzReqMessageContext.setAuthorizationDetails(validatedAuthorizationDetails);
- } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) {
+ oAuthMessage.getSessionDataCacheEntry().setAuthzReqMsgCtx(oAuthAuthzReqMessageContext);
+
+ if (LoggerUtils.isDiagnosticLogsEnabled()) {
+ DiagnosticLog.DiagnosticLogBuilder diagnosticLogBuilder = new DiagnosticLog.DiagnosticLogBuilder(
+ OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE,
+ OAuthConstants.LogConstants.ActionIDs.VALIDATE_AUTHORIZATION_DETAILS_BEFORE_CONSENT);
+ diagnosticLogBuilder.inputParam(LogConstants.InputKeys.CLIENT_ID, oAuth2Parameters.getClientId())
+ .inputParam(LogConstants.InputKeys.APPLICATION_NAME, oAuth2Parameters.getApplicationName())
+ .inputParam("authorization details after validation",
+ oAuth2Parameters.getAuthorizationDetails().toSet())
+ .resultStatus(DiagnosticLog.ResultStatus.SUCCESS)
+ .resultMessage("authorization details validation completed")
+ .logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION);
+ LoggerUtils.triggerDiagnosticLogEvent(diagnosticLogBuilder);
+ }
+ } catch (IdentityOAuth2ServerException e) {
log.error("Error occurred while validating authorization details. Caused by, ", e);
throw new OAuthSystemException("Error occurred while validating requested authorization details", e);
}
}
+
+ private void setAuthorizationDetails(final OAuth2AuthorizeRespDTO oAuth2AuthorizeRespDTO,
+ final OAuthASResponse.OAuthAuthorizationResponseBuilder builder,
+ final AuthorizationResponseDTO authorizationResponseDTO) {
+
+ final AuthorizationDetails authorizationDetails = oAuth2AuthorizeRespDTO.getAuthorizationDetails();
+ builder.setParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
+ AuthorizationDetailsUtils.getUrlEncodedAuthorizationDetails(authorizationDetails));
+ authorizationResponseDTO.getSuccessResponseDTO().setAuthorizationDetails(authorizationDetails);
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
new file mode 100644
index 0000000000..f33588a722
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.wso2.carbon.identity.oauth.endpoint.factory;
+
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+
+/**
+ * This class is used to register AuthorizationDetailsService as a factory bean.
+ */
+public class AuthorizationDetailsServiceFactory extends AbstractFactoryBean {
+
+ private AuthorizationDetailsService authorizationDetailsService;
+
+ @Override
+ public Class getObjectType() {
+
+ return AuthorizationDetailsService.class;
+ }
+
+ @Override
+ protected AuthorizationDetailsService createInstance() throws Exception {
+
+ if (this.authorizationDetailsService == null) {
+ this.authorizationDetailsService =
+ OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService();
+ }
+ return this.authorizationDetailsService;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/token/OAuth2TokenEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/token/OAuth2TokenEndpoint.java
index 54403f9d35..b521a4c799 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/token/OAuth2TokenEndpoint.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/token/OAuth2TokenEndpoint.java
@@ -46,6 +46,9 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthTokenRequest;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.handlers.response.OAuth2TokenResponse;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import org.wso2.carbon.utils.DiagnosticLog;
@@ -407,6 +410,19 @@ private OAuth2AccessTokenReqDTO buildAccessTokenReqDTO(CarbonOAuthTokenRequest o
tokenReqDTO.setWindowsToken(oauthRequest.getWindowsToken());
}
tokenReqDTO.addAuthenticationMethodReference(grantType);
+
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oauthRequest)) {
+ final String encodedAuthorizationDetailsJson = oauthRequest
+ .getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS);
+ final String authorizationDetailsJson = AuthorizationDetailsUtils
+ .getUrlDecodedAuthorizationDetails(encodedAuthorizationDetailsJson);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Adding requested authorization details to tokenReqDTO: " + authorizationDetailsJson);
+ }
+ tokenReqDTO.setAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
+ }
+
return tokenReqDTO;
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
index 4129b752b7..4d0d9a3722 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
@@ -103,7 +103,8 @@
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthAuthzRequest;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.model.OAuth2ScopeConsentResponse;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.scopeservice.OAuth2Resource;
import org.wso2.carbon.identity.oauth2.scopeservice.ScopeMetadataService;
@@ -872,8 +873,9 @@ public static String getUserConsentURL(OAuth2Parameters params, String loggedInU
// Append authorization details to consent page url
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(params)) {
- consentPageUrl = consentPageUrl + "&" + AuthorizationDetailsConstants.AUTHORIZATION_DETAILS + "="
- + URLEncoder.encode(params.getAuthorizationDetails().toJsonString(), UTF_8);
+ additionalQueryParams = additionalQueryParams + "&" +
+ AuthorizationDetailsConstants.AUTHORIZATION_DETAILS + "=" + AuthorizationDetailsUtils
+ .getUrlEncodedAuthorizationDetails(filterConsentRequiredAuthorizationDetails(user, params));
}
// Append scope metadata to additionalQueryParams.
@@ -2153,4 +2155,26 @@ public static void preHandleParRequest(HttpServletRequest request, Map
+
@@ -103,4 +104,5 @@
+
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml b/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
deleted file mode 100644
index 1ac995d59f..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar.common/pom.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
- org.wso2.carbon.identity.inbound.auth.oauth2
- identity-inbound-auth-oauth
- 7.0.107-SNAPSHOT
- ../../pom.xml
-
-
- 4.0.0
- org.wso2.carbon.identity.oauth.rar.common
- jar
- WSO2 Carbon - Rich Authorization Requests Common
- http://wso2.org
-
-
- UTF-8
-
-
-
-
- org.wso2.carbon.identity.framework
- org.wso2.carbon.identity.core
- provided
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- provided
-
-
-
- junit
- junit
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 8
-
-
-
- com.github.spotbugs
- spotbugs-maven-plugin
-
- High
- 2048
-
-
-
-
-
-
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
deleted file mode 100644
index a21b68b4d7..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAO.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. 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.oauth2.rar.common.dao;
-
-import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
-
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Provides methods to interact with the database to manage authorization details.
- */
-public interface AuthorizationDetailsDAO {
-
- /**
- * Adds authorization details against a given OAuth2 code.
- *
- * @param authorizationCodeID The ID of the authorization code.
- * @param authorizationDetails The authorization details to store.
- * @param tenantId The tenant ID.
- * @return An array of positive integers indicating the number of rows affected for each batch operation,
- * or negative integers if any of the batch operations fail.
- * @throws SQLException If a database access error occurs.
- */
- int[] addOAuth2CodeAuthorizationDetails(String authorizationCodeID, AuthorizationDetails authorizationDetails,
- int tenantId) throws SQLException;
-
- /**
- * Adds user consented authorization details.
- *
- * @param authorizationDetailsConsentDTOs List of user consented authorization details DTOs.
- * {@link AuthorizationDetailsConsentDTO }
- * @return An array of positive integers indicating the number of rows affected for each batch operation,
- * or negative integers if any of the batch operations fail.
- * @throws SQLException If a database access error occurs.
- */
- int[] addUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
- throws SQLException;
-
- int deleteUserConsentedAuthorizationDetails(String consentId, int tenantId)
- throws SQLException;
-
- // add a todo and mention to move this to consent module
- String getConsentIdByUserIdAndAppId(String userId, String appId, int tenantId) throws SQLException;
-
- Set getUserConsentedAuthorizationDetails(String consentId, int tenantId)
- throws SQLException;
-
- int[] updateUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
- throws SQLException;
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
deleted file mode 100644
index bc143a9325..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsCodeDTO.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar.common.dto;
-
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-
-/**
- *
- */
-public class AuthorizationDetailsCodeDTO extends AuthorizationDetailsDTO {
-
- final String codeId;
-
- public AuthorizationDetailsCodeDTO(final String id, final String codeId, final int typeId,
- final AuthorizationDetail authorizationDetail, final int tenantId) {
-
- super(id, typeId, authorizationDetail, tenantId);
- this.codeId = codeId;
- }
-
- public String getCodeId() {
- return codeId;
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
deleted file mode 100644
index 0cf61dc230..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsConsentDTO.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar.common.dto;
-
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-
-/**
- *
- */
-public class AuthorizationDetailsConsentDTO extends AuthorizationDetailsDTO {
-
- final String consentId;
- final boolean isConsentActive;
-
- public AuthorizationDetailsConsentDTO(final String id, final String consentId, final int typeId,
- final String authorizationDetail,
- final boolean isConsentActive, final int tenantId) {
-
- super(id, typeId, authorizationDetail, tenantId);
- this.consentId = consentId;
- this.isConsentActive = isConsentActive;
- }
-
- public AuthorizationDetailsConsentDTO(final String consentId,
- final AuthorizationDetail authorizationDetail,
- final boolean isConsentActive, final int tenantId) {
-
- super(authorizationDetail, tenantId);
- this.consentId = consentId;
- this.isConsentActive = isConsentActive;
- }
-
- public boolean isConsentActive() {
- return isConsentActive;
- }
-
- public String getConsentId() {
- return consentId;
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java b/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
deleted file mode 100644
index fa73865c8b..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dto/AuthorizationDetailsDTO.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar.common.dto;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
-
-/**
- *
- */
-public class AuthorizationDetailsDTO {
-
- final String id;
- final int typeId;
- final AuthorizationDetail authorizationDetail;
- final int tenantId;
-
- public AuthorizationDetailsDTO(final String id, final int typeId, final AuthorizationDetail authorizationDetail,
- final int tenantId) {
-
- this.id = id;
- this.typeId = typeId;
- this.authorizationDetail = authorizationDetail;
- this.tenantId = tenantId;
- }
-
- public AuthorizationDetailsDTO(final String id, final int typeId, final String authorizationDetailJson,
- final int tenantId) {
-
- this(id, typeId, AuthorizationDetailsCommonUtils
- .fromJSON(authorizationDetailJson, AuthorizationDetail.class, new ObjectMapper()), tenantId);
- }
-
- public AuthorizationDetailsDTO(final AuthorizationDetail authorizationDetail, final int tenantId) {
-
- this(null, 0, authorizationDetail, tenantId);
- }
-
- public String getId() {
- return this.id;
- }
-
- public int getTypeId() {
- return this.typeId;
- }
-
- public AuthorizationDetail getAuthorizationDetail() {
- return this.authorizationDetail;
- }
-
- public int getTenantId() {
- return this.tenantId;
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index bb6bc7c861..ad80a06a34 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -29,7 +29,7 @@
4.0.0
org.wso2.carbon.identity.oauth.rar
- bundle
+ jar
WSO2 Carbon - Rich Authorization Requests
http://wso2.org
@@ -39,8 +39,8 @@
- org.wso2.carbon.identity.inbound.auth.oauth2
- org.wso2.carbon.identity.oauth
+ org.wso2.carbon.identity.framework
+ org.wso2.carbon.identity.core
provided
@@ -50,42 +50,20 @@
- org.wso2.carbon.identity.inbound.auth.oauth2
- org.wso2.carbon.identity.oauth.rar.common
+ com.fasterxml.jackson.core
+ jackson-databind
+ provided
+
+ junit
+ junit
+ test
+
-
- org.apache.felix
- maven-bundle-plugin
- true
-
-
-
- ${project.artifactId}
-
-
- org.wso2.carbon.identity.oauth2.rar.internal
-
-
- org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}",
- org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}",
- org.wso2.carbon.identity.oauth2.*; version="${identity.inbound.auth.oauth.exp.pkg.version}",
-
-
- !org.wso2.carbon.identity.oauth2.rar.internal,
- org.wso2.carbon.identity.oauth2.rar.*;
- version="${identity.inbound.auth.oauth.exp.pkg.version}",
-
- *
- <_dsannotations>*
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
deleted file mode 100644
index 00f4c97c96..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
-import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
-import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
-import org.wso2.carbon.identity.application.common.model.ServiceProvider;
-import org.wso2.carbon.identity.oauth2.IdentityOAuth2AuthorizationDetailsService;
-import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
-import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
-import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
-import org.wso2.carbon.identity.oauth2.rar.common.dao.AuthorizationDetailsDAO;
-import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
-import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
-
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import static org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS_ID_PREFIX;
-
-/**
- *
- */
-public class AuthorizationDetailsService extends IdentityOAuth2AuthorizationDetailsService {
-
- private static final Log log = LogFactory.getLog(AuthorizationDetailsService.class);
- private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
-
- public AuthorizationDetailsService() {
-
- this(OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO(),
- AuthorizationDetailsProviderFactory.getInstance());
- }
-
- public AuthorizationDetailsService(final AuthorizationDetailsDAO authorizationDetailsDAO,
- final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory) {
-
- super(authorizationDetailsDAO);
- this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
- }
-
- public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser, final String clientId,
- final OAuth2Parameters oAuth2Parameters,
- final AuthorizationDetails userConsentedAuthorizationDetails)
- throws OAuthSystemException {
-
- if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
- return;
- }
-
- try {
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
-
- if (consentId.isPresent()) {
-
- super.authorizationDetailsDAO.addUserConsentedAuthorizationDetails(
- generateAuthorizationDetailsConsentDTOs(consentId.get(),
- userConsentedAuthorizationDetails, tenantId));
- }
- } catch (SQLException | IdentityOAuth2Exception e) {
- log.error("Error occurred while storing user consented authorization details. Caused by, ", e);
- throw new OAuthSystemException("Error occurred while storing authorization details", e);
- }
- }
-
- public void updateUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final String clientId, final OAuth2Parameters oAuth2Parameters,
- final AuthorizationDetails userConsentedAuthorizationDetails)
- throws OAuthSystemException {
-
- if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
- return;
- }
-
- try {
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
-
- if (consentId.isPresent()) {
-
- super.authorizationDetailsDAO.updateUserConsentedAuthorizationDetails(
- generateAuthorizationDetailsConsentDTOs(consentId.get(),
- userConsentedAuthorizationDetails, tenantId));
- }
- } catch (SQLException | IdentityOAuth2Exception e) {
- log.error("Error occurred while updating user consented authorization details. Caused by, ", e);
- throw new OAuthSystemException("Error occurred while updating authorization details", e);
- }
- }
-
- public void deleteUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final String clientId, final OAuth2Parameters oAuth2Parameters)
- throws OAuthSystemException {
-
- if (!AuthorizationDetailsService.isRichAuthorizationRequest(oAuth2Parameters)) {
- return;
- }
-
- try {
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
-
- if (consentId.isPresent()) {
-
- super.authorizationDetailsDAO.deleteUserConsentedAuthorizationDetails(consentId.get(), tenantId);
- }
- } catch (SQLException | IdentityOAuth2Exception e) {
- log.error("Error occurred while deleting user consented authorization details. Caused by, ", e);
- throw new OAuthSystemException("Error occurred while storing authorization details", e);
- }
- }
-
- public void storeOrReplaceUserConsentedAuthorizationDetails(
- final AuthenticatedUser authenticatedUser, final String clientId, final OAuth2Parameters oAuth2Parameters,
- final AuthorizationDetails userConsentedAuthorizationDetails) throws OAuthSystemException {
-
- this.deleteUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters);
- this.storeUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters,
- userConsentedAuthorizationDetails);
- }
-
- /**
- * Check if the user has already given consent to requested authorization details.
- *
- * @param authenticatedUser Authenticated user.
- * @param oAuth2Parameters OAuth2 parameters.
- * @return True if user has given consent to all the requested authorization details.
- */
- public boolean isUserAlreadyConsentedForAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final OAuth2Parameters oAuth2Parameters)
- throws OAuthSystemException {
-
- try {
- final String userId = this.getUserId(authenticatedUser);
- final String appId = this.getApplicationResourceIdFromClientId(oAuth2Parameters.getClientId());
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
-
- if (consentId.isPresent()) {
- final Set consentedAuthorizationDetailsDTOs =
- super.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId.get(), tenantId);
-
- final Map> consentedAuthorizationDetailsByType =
- consentedAuthorizationDetailsDTOs
- .stream()
- .filter(AuthorizationDetailsConsentDTO::isConsentActive)
- .map(AuthorizationDetailsConsentDTO::getAuthorizationDetail)
- .collect(Collectors.groupingBy(AuthorizationDetail::getType,
- Collectors.mapping(Function.identity(), Collectors.toSet())));
-
- for (final AuthorizationDetail requestedAuthorizationDetail :
- oAuth2Parameters.getAuthorizationDetails().getDetails()) {
-
- if (consentedAuthorizationDetailsByType.containsKey(requestedAuthorizationDetail.getType())) {
-
- final Optional provider = authorizationDetailsProviderFactory
- .getProviderByType(requestedAuthorizationDetail.getType());
- if (provider.isPresent()) {
-
- final AuthorizationDetails existingAuthorizationDetails = new AuthorizationDetails(
- consentedAuthorizationDetailsByType.get(requestedAuthorizationDetail.getType()));
- if (!provider.get()
- .isEqualOrSubset(requestedAuthorizationDetail, existingAuthorizationDetails)) {
-
- if (log.isDebugEnabled()) {
- log.debug("User has not consented for the requested authorization details type: "
- + requestedAuthorizationDetail.getType());
-
- }
- return false;
- }
- }
- }
- }
- return true;
- }
- return false;
- } catch (IdentityOAuth2Exception | SQLException e) {
- log.error("Error occurred while extracting user consented authorization details. Caused by, ", e);
- throw new OAuthSystemException("Error occurred while extracting user consented authorization details", e);
- }
- }
-
- /**
- * Retrieves the user-consented authorization details based on the provided parameter map and OAuth2 parameters.
- *
- * This method is used to extract and return the authorization details that the user has consented to,
- * filtering them based on a provided authorization details in the parameter map.
- *
- *
- * @param parameterMap A map of query parameters.
- * @param oAuth2Parameters The OAuth2 parameters that include the details of the authorization request.
- * @return The {@link AuthorizationDetails} object containing the details the user has consented to.
- */
- public AuthorizationDetails getUserConsentedAuthorizationDetails(
- final Map parameterMap, final OAuth2Parameters oAuth2Parameters) {
-
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
- return new AuthorizationDetails();
- }
-
- // Extract consented authorization detail IDs from the parameter map
- final Set consentedAuthorizationDetailIDs = parameterMap.keySet().stream()
- .filter(parameterName -> parameterName.startsWith(AUTHORIZATION_DETAILS_ID_PREFIX))
- .map(parameterName -> parameterName.substring(AUTHORIZATION_DETAILS_ID_PREFIX.length()))
- .collect(Collectors.toSet());
-
- // Filter and collect the consented authorization details
- final Set consentedAuthorizationDetails = oAuth2Parameters.getAuthorizationDetails()
- .stream()
- .filter(authorizationDetail -> consentedAuthorizationDetailIDs.contains(authorizationDetail.getId()))
- .collect(Collectors.toSet());
-
- return new AuthorizationDetails(consentedAuthorizationDetails);
- }
-
- public Optional getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
- throws OAuthSystemException {
-
- try {
- return Optional
- .ofNullable(super.authorizationDetailsDAO.getConsentIdByUserIdAndAppId(userId, appId, tenantId));
- } catch (SQLException e) {
- log.error(String.format("Error occurred while retrieving user consent by " +
- "userId: %s and appId: %s. Caused by, ", userId, appId), e);
- throw new OAuthSystemException("Error occurred while retrieving user consent", e);
- }
- }
-
- private String getApplicationResourceIdFromClientId(final String clientId) throws IdentityOAuth2Exception {
-
- final ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(clientId);
- if (serviceProvider != null) {
- return serviceProvider.getApplicationResourceId();
- }
- throw new IdentityOAuth2Exception("Unable to find a service provider for client Id: " + clientId);
- }
-
- private String getUserId(final AuthenticatedUser authenticatedUser) throws OAuthSystemException {
- try {
- return authenticatedUser.getUserId();
- } catch (UserIdNotFoundException e) {
- log.error("Error occurred while extracting userId from authenticated user. Caused by, ", e);
- throw new OAuthSystemException(
- "User id is not found for user: " + authenticatedUser.getLoggableMaskedUserId(), e);
- }
- }
-
- private List generateAuthorizationDetailsConsentDTOs(
- final String consentId, final AuthorizationDetails userConsentedAuthorizationDetails, final int tenantId) {
-
- return userConsentedAuthorizationDetails.stream()
- .map(authorizationDetail ->
- new AuthorizationDetailsConsentDTO(consentId, authorizationDetail, true, tenantId))
- .collect(Collectors.toList());
- }
-
- private Optional getConsentId(final AuthenticatedUser authenticatedUser, final String clientId,
- final int tenantId)
- throws OAuthSystemException, IdentityOAuth2Exception {
-
- final String userId = this.getUserId(authenticatedUser);
- final String appId = this.getApplicationResourceIdFromClientId(clientId);
-
- return this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
deleted file mode 100644
index 6b67f226d8..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsValidator.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. 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.oauth2.rar;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
-import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
-import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
-import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
-import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
-import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
-
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * {@code AuthorizationDetailsValidator} class responsible for managing and validating authorization details.
- */
-public class AuthorizationDetailsValidator {
-
- private static final Log log = LogFactory.getLog(AuthorizationDetailsValidator.class);
- private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
-
- public AuthorizationDetailsValidator() {
-
- this(AuthorizationDetailsProviderFactory.getInstance());
- }
-
- public AuthorizationDetailsValidator(AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory) {
-
- this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
- }
-
- /**
- * Retrieves and validates the authorization details for a given OAuth2 parameters context.
- *
- * @param oAuth2Parameters The OAuth2 parameters associated with the request.
- * @param oAuthAppDO The OAuth application details.
- * @param authenticatedUser The authenticated user information.
- * @return An {@link AuthorizationDetails} object containing the validated authorization details.
- */
- public AuthorizationDetails getValidatedAuthorizationDetails(
- final OAuth2Parameters oAuth2Parameters, final OAuthAppDO oAuthAppDO,
- final AuthenticatedUser authenticatedUser) throws AuthorizationDetailsProcessingException {
-
- final Set validatedAuthorizationDetails = new HashSet<>();
- final Set authorizedAuthorizationDetailsTypes = this.getAuthorizedAuthorizationDetailsTypes(
- oAuth2Parameters.getClientId(), oAuth2Parameters.getTenantDomain());
- for (AuthorizationDetail authorizationDetail : oAuth2Parameters.getAuthorizationDetails().getDetails()) {
-
- if (!isSupportedAuthorizationDetailType(authorizationDetail.getType())) {
- throw new AuthorizationDetailsProcessingException(String.format(AuthorizationDetailsConstants
- .TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT, authorizationDetail.getType()));
- }
-
- if (isAuthorizedAuthorizationDetail(authorizationDetail, authorizedAuthorizationDetailsTypes)) {
-
- final AuthorizationDetailsContext authorizationDetailsContext = new AuthorizationDetailsContext(
- oAuth2Parameters, oAuthAppDO, authenticatedUser, authorizationDetail);
-
- if (isValidAuthorizationDetail(authorizationDetailsContext)) {
- validatedAuthorizationDetails.add(getEnrichedAuthorizationDetail(authorizationDetailsContext));
- }
- }
- }
-
- return new AuthorizationDetails(validatedAuthorizationDetails);
- }
-
- private boolean isAuthorizedAuthorizationDetail(final AuthorizationDetail authorizationDetail,
- final Set authorizedAuthorizationDetailsTypes) {
-
- return authorizedAuthorizationDetailsTypes.contains(authorizationDetail.getType());
- }
-
- private boolean isSupportedAuthorizationDetailType(final String authorizationDetailType) {
-
- return this.authorizationDetailsProviderFactory
- .isSupportedAuthorizationDetailsType(authorizationDetailType);
- }
-
- /**
- * Checks if the provided authorization details context is valid.
- *
- * @param authorizationDetailsContext The context containing authorization details.
- * @return {@code true} if the authorization details are valid; {@code false} otherwise.
- */
- private boolean isValidAuthorizationDetail(final AuthorizationDetailsContext authorizationDetailsContext)
- throws AuthorizationDetailsProcessingException {
-
- Optional optionalProvider = this.authorizationDetailsProviderFactory
- .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType());
-
- if (optionalProvider.isPresent()) {
-
- final ValidationResult validationResult = optionalProvider.get().validate(authorizationDetailsContext);
- if (log.isDebugEnabled() && validationResult.isInvalid()) {
-
- log.debug(String.format("Authorization details validation failed for type %s. Caused by, %s",
- authorizationDetailsContext.getAuthorizationDetail().getType(), validationResult.getReason()));
-
- }
- return validationResult.isValid();
- }
- throw new AuthorizationDetailsProcessingException(String.format(
- AuthorizationDetailsConstants.TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT,
- authorizationDetailsContext.getAuthorizationDetail().getType()));
- }
-
- /**
- * Enriches the authorization details using the provided context.
- *
- * @param authorizationDetailsContext The context containing authorization details.
- * @return An enriched {@link AuthorizationDetail} object.
- */
- private AuthorizationDetail getEnrichedAuthorizationDetail(
- final AuthorizationDetailsContext authorizationDetailsContext) {
-
- return this.authorizationDetailsProviderFactory
- .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType())
- .map(authorizationDetailsService -> authorizationDetailsService.enrich(authorizationDetailsContext))
- // If provider is missing, return the original authorization detail instance
- .orElse(authorizationDetailsContext.getAuthorizationDetail());
- }
-
- /**
- * Retrieves the set of authorized authorization types for the given client and tenant domain.
- *
- * @param clientID The client ID.
- * @param tenantDomain The tenant domain.
- * @return A set of strings representing the authorized authorization types.
- */
- private Set getAuthorizedAuthorizationDetailsTypes(final String clientID, final String tenantDomain) {
-
-// try {
-// final String appId = OAuth2Util
-// .getApplicationResourceIDByClientId(clientID, tenantDomain, this.applicationMgtService);
-//
-//// OAuth2ServiceComponentHolder.getInstance().getAuthorizedAPIManagementService()
-// .getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
-// } catch (IdentityOAuth2Exception e) {
-// throw new RuntimeException(e);
-// }
- Set authorizedAuthorizationDetailsTypes = new HashSet<>();
- authorizedAuthorizationDetailsTypes.add("payment_initiation");
- return authorizedAuthorizationDetailsTypes;
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
new file mode 100644
index 0000000000..5c467f47bf
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.dao;
+
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Provides methods to interact with the database to manage rich authorization requests.
+ *
+ * {@link AuthorizationDetailsDAO} provides methods to add, update, retrieve, and delete authorization details
+ * associated with user consent and access tokens.
+ */
+public interface AuthorizationDetailsDAO {
+
+ /**
+ * Adds user consented authorization details to the database.
+ *
+ * @param authorizationDetailsConsentDTOs List of user consented authorization details DTOs.
+ * {@link AuthorizationDetailsConsentDTO }
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] addUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
+ throws SQLException;
+
+ /**
+ * Retrieves user consented authorization details from the database.
+ *
+ * @param consentId The ID of the consent.
+ * @param tenantId The tenant ID.
+ * @return A set of user consented authorization details DTOs.
+ * @throws SQLException If a database access error occurs.
+ */
+ Set getUserConsentedAuthorizationDetails(String consentId, int tenantId)
+ throws SQLException;
+
+ /**
+ * Updates user consented authorization details in the database.
+ *
+ * @param authorizationDetailsConsentDTOs A list of user consented authorization details DTOs.
+ * {@link AuthorizationDetailsConsentDTO}
+ * @return An array of integers indicating the number of rows affected for each batch operation.
+ * Positive values indicate success, negative values indicate failure.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] updateUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
+ throws SQLException;
+
+ /**
+ * Deletes user consented authorization details from the database.
+ *
+ * @param consentId The ID of the consent.
+ * @param tenantId The tenant ID.
+ * @return The number of rows affected by the delete operation.
+ * @throws SQLException If a database access error occurs.
+ */
+ int deleteUserConsentedAuthorizationDetails(String consentId, int tenantId) throws SQLException;
+
+ /**
+ * Adds access token authorization details to the database.
+ *
+ * @param authorizationDetailsTokenDTOs A list of access token authorization details DTOs.
+ * {@link AuthorizationDetailsTokenDTO}
+ * @return An array of integers indicating the number of rows affected for each batch operation.
+ * Positive values indicate success, negative values indicate failure.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] addAccessTokenAuthorizationDetails(List authorizationDetailsTokenDTOs)
+ throws SQLException;
+
+ /**
+ * Retrieves access token authorization details from the database.
+ *
+ * @param accessTokenId The ID of the access token.
+ * @param tenantId The tenant ID.
+ * @return A set of access token authorization details DTOs.
+ * @throws SQLException If a database access error occurs.
+ */
+ Set getAccessTokenAuthorizationDetails(String accessTokenId, int tenantId)
+ throws SQLException;
+
+ /**
+ * Deletes access token authorization details from the database.
+ *
+ * @param accessTokenId The ID of the access token.
+ * @param tenantId The tenant ID.
+ * @return The number of rows affected by the delete operation.
+ * @throws SQLException If a database access error occurs.
+ */
+ int deleteAccessTokenAuthorizationDetails(String accessTokenId, int tenantId) throws SQLException;
+
+ /**
+ * Retrieves the consent ID associated with a specific user ID and application ID.
+ *
+ * @param userId The user ID.
+ * @param appId The application ID.
+ * @param tenantId The tenant ID.
+ * @return The consent ID as a string.
+ * @throws SQLException If a database access error occurs.
+ */
+ // TODO: Move this method to the consent module
+ String getConsentIdByUserIdAndAppId(String userId, String appId, int tenantId) throws SQLException;
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
similarity index 64%
rename from components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index 839f23c464..b7a561d0f5 100644
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -16,12 +16,11 @@
* under the License.
*/
-package org.wso2.carbon.identity.oauth2.rar.common.dao;
+package org.wso2.carbon.identity.oauth2.rar.dao;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
-import org.wso2.carbon.identity.oauth2.rar.common.dto.AuthorizationDetailsConsentDTO;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -32,36 +31,31 @@
import java.util.Set;
/**
- * Implementation of {@link AuthorizationDetailsDAO}.
- * This class provides methods to add authorization details to the database.
+ * Implements the {@link AuthorizationDetailsDAO} interface to manage rich authorization requests.
+ *
+ * {@link AuthorizationDetailsDAO} provides methods to add, update, retrieve, and delete authorization details
+ * associated with user consent and access tokens.
*/
public class AuthorizationDetailsDAOImpl implements AuthorizationDetailsDAO {
/**
- * Stores authorization details against the provided OAuth2 authorization code.
- *
- * @param authorizationCodeID The ID of the authorization code.
- * @param authorizationDetails The details to be added.
- * @param tenantId The tenant ID.
- * @return An array of positive integers indicating the number of rows affected for each batch operation,
- * or negative integers if any of the batch operations fail.
- * @throws SQLException If a database access error occurs.
+ * {@inheritDoc}
*/
@Override
- public int[] addOAuth2CodeAuthorizationDetails(final String authorizationCodeID,
- final AuthorizationDetails authorizationDetails,
- final int tenantId) throws SQLException {
+ public int[] addUserConsentedAuthorizationDetails(
+ final List authorizationDetailsConsentDTOs) throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
- connection.prepareStatement(SQLQueries.ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS)) {
-
- for (AuthorizationDetail authorizationDetail : authorizationDetails.getDetails()) {
- ps.setString(1, authorizationCodeID);
- ps.setString(2, authorizationDetail.getType());
- ps.setInt(3, tenantId);
- ps.setString(4, authorizationDetail.toJsonString());
- ps.setInt(5, tenantId);
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
+ ps.setString(1, consentDTO.getConsentId());
+ ps.setString(2, consentDTO.getAuthorizationDetail().toJsonString());
+ ps.setBoolean(3, consentDTO.isConsentActive());
+ ps.setString(4, consentDTO.getAuthorizationDetail().getType());
+ ps.setInt(5, consentDTO.getTenantId());
+ ps.setInt(6, consentDTO.getTenantId());
ps.addBatch();
}
return ps.executeBatch();
@@ -69,34 +63,39 @@ public int[] addOAuth2CodeAuthorizationDetails(final String authorizationCodeID,
}
/**
- * Stores user consented authorization details.
- *
- * @param authorizationDetailsConsentDTOs The user consented authorization details DTOs
- * @return An array of positive integers indicating the number of rows affected for each batch operation,
- * or negative integers if any of the batch operations fail.
- * @throws SQLException If a database access error occurs.
+ * {@inheritDoc}
*/
@Override
- public int[] addUserConsentedAuthorizationDetails(
- final List authorizationDetailsConsentDTOs) throws SQLException {
+ public Set getUserConsentedAuthorizationDetails(final String consentId,
+ final int tenantId)
+ throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
- connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+ connection.prepareStatement(SQLQueries.GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
- for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
- ps.setString(1, consentDTO.getConsentId());
- ps.setString(2, consentDTO.getAuthorizationDetail().getType());
- ps.setInt(3, consentDTO.getTenantId());
- ps.setString(4, consentDTO.getAuthorizationDetail().toJsonString());
- ps.setBoolean(5, consentDTO.isConsentActive());
- ps.setInt(6, consentDTO.getTenantId());
- ps.addBatch();
+ ps.setString(1, consentId);
+ ps.setInt(2, tenantId);
+ try (ResultSet rs = ps.executeQuery()) {
+
+ final Set authorizationDetailsConsentDTOs = new HashSet<>();
+ while (rs.next()) {
+ final String id = rs.getString(1);
+ final int typeId = rs.getInt(2);
+ final String authorizationDetail = rs.getString(3);
+ final boolean isConsentActive = rs.getBoolean(4);
+
+ authorizationDetailsConsentDTOs.add(new AuthorizationDetailsConsentDTO(id, consentId, typeId,
+ authorizationDetail, isConsentActive, tenantId));
+ }
+ return authorizationDetailsConsentDTOs;
}
- return ps.executeBatch();
}
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public int[] updateUserConsentedAuthorizationDetails(
final List authorizationDetailsConsentDTOs) throws SQLException {
@@ -116,6 +115,9 @@ public int[] updateUserConsentedAuthorizationDetails(
}
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public int deleteUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
throws SQLException {
@@ -130,42 +132,76 @@ public int deleteUserConsentedAuthorizationDetails(final String consentId, final
}
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public Set getUserConsentedAuthorizationDetails(final String consentId,
- final int tenantId)
- throws SQLException {
+ public int[] addAccessTokenAuthorizationDetails(final List
+ authorizationDetailsTokenDTOs) throws SQLException {
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsTokenDTO tokenDTO : authorizationDetailsTokenDTOs) {
+ ps.setString(1, tokenDTO.getAccessTokenId());
+ ps.setString(2, tokenDTO.getAuthorizationDetail().toJsonString());
+ ps.setString(3, tokenDTO.getAuthorizationDetail().getType());
+ ps.setInt(4, tokenDTO.getTenantId());
+ ps.setInt(5, tokenDTO.getTenantId());
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set getAccessTokenAuthorizationDetails(
+ final String accessTokenId, final int tenantId) throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
- connection.prepareStatement(SQLQueries.GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+ connection.prepareStatement(SQLQueries.GET_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
- ps.setString(1, consentId);
+ ps.setString(1, accessTokenId);
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
- final Set authorizationDetailsConsentDTOs = new HashSet<>();
+ final Set authorizationDetailsTokenDTO = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
final int typeId = rs.getInt(2);
final String authorizationDetail = rs.getString(3);
- final boolean isConsentActive = rs.getBoolean(4);
- authorizationDetailsConsentDTOs.add(new AuthorizationDetailsConsentDTO(id, consentId, typeId,
- authorizationDetail, isConsentActive, tenantId));
+ authorizationDetailsTokenDTO.add(
+ new AuthorizationDetailsTokenDTO(id, accessTokenId, typeId, authorizationDetail, tenantId));
}
- return authorizationDetailsConsentDTOs;
+ return authorizationDetailsTokenDTO;
}
}
}
/**
- * Retrieves the first consent ID for a given user ID and application ID.
- *
- * @param userId The ID of the user.
- * @param appId The ID of the application.
- * @param tenantId The tenant ID.
- * @return The first consent ID found, or null if no consent ID is found.
- * @throws SQLException If a database access error occurs.
+ * {@inheritDoc}
+ */
+ @Override
+ public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, final int tenantId)
+ throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
+
+ ps.setString(1, accessTokenId);
+ ps.setInt(2, tenantId);
+ return ps.executeUpdate();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
*/
@Override
public String getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
similarity index 58%
rename from components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
index 79faa31c9e..9cbed27365 100644
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/dao/SQLQueries.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
@@ -16,7 +16,7 @@
* under the License.
*/
-package org.wso2.carbon.identity.oauth2.rar.common.dao;
+package org.wso2.carbon.identity.oauth2.rar.dao;
/**
* The {@code SQLQueries} class contains SQL query constants used for performing
@@ -28,25 +28,11 @@ private SQLQueries() {
// Private constructor to prevent instantiation
}
- public static final String ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS =
- "INSERT INTO IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS " +
- "(CODE_ID, TYPE_ID, AUTHORIZATION_DETAILS, TENANT_ID) VALUES " +
- "(?, (SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), " +
- "? FORMAT JSON, ?)";
-
- public static final String GET_OAUTH2_CODE_AUTHORIZATION_DETAILS =
- "SELECT IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.AUTHORIZATION_DETAILS " +
- "FROM IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS " +
- "INNER JOIN IDN_OAUTH2_AUTHORIZATION_CODE " +
- "ON IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.CODE_ID = IDN_OAUTH2_AUTHORIZATION_CODE.CODE_ID " +
- "WHERE IDN_OAUTH2_AUTHORIZATION_CODE.AUTHORIZATION_CODE=? " +
- "AND IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS.TENANT_ID=?";
-
public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
- "(CONSENT_ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT, TENANT_ID) VALUES " +
- "(?,(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), " +
- "? FORMAT JSON, ?, ?)";
+ "(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
+ "VALUES (?, ? FORMAT JSON, ?," +
+ "(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
public static final String UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"UPDATE IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
@@ -59,9 +45,18 @@ private SQLQueries() {
public static final String DELETE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"DELETE FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS WHERE CONSENT_ID=? AND TENANT_ID=?";
- public static final String CREATE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
+ public static final String ADD_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
- "(AUTHORIZATION_DETAILS_TYPE, AUTHORIZATION_DETAILS, TOKEN_ID, TENANT_ID) VALUES (?, ?, ?, ?)";
+ "(TOKEN_ID, AUTHORIZATION_DETAILS, TYPE_ID, TENANT_ID) " +
+ "VALUES (?, ? FORMAT JSON, " +
+ "(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+
+ public static final String DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
+ "DELETE FROM IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS WHERE TOKEN_ID=? AND TENANT_ID=?";
+
+ public static final String GET_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
+ "SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS FROM IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
+ "WHERE TOKEN_ID=? AND TENANT_ID=?";
public static final String GET_IDN_OAUTH2_USER_CONSENT_CONSENT_ID =
"SELECT CONSENT_ID FROM IDN_OAUTH2_USER_CONSENT WHERE USER_ID=? AND APP_ID=? AND TENANT_ID=?";
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
new file mode 100644
index 0000000000..c70619615f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
@@ -0,0 +1,67 @@
+package org.wso2.carbon.identity.oauth2.rar.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+
+/**
+ * Data Transfer Object (DTO) for representing authorization details along with consent information.
+ * This class extends {@link AuthorizationDetailsDTO} to include additional fields for consent ID and consent status.
+ */
+public class AuthorizationDetailsConsentDTO extends AuthorizationDetailsDTO {
+
+ final String consentId;
+ final boolean isConsentActive;
+
+ /**
+ * Constructs an {@link AuthorizationDetailsConsentDTO} with all required fields.
+ *
+ * @param id the ID of the authorization detail DTO.
+ * @param consentId the consent ID associated with the authorization detail.
+ * @param typeId the type ID of the authorization detail.
+ * @param authorizationDetailJson the JSON string of the authorization detail.
+ * @param isConsentActive the consent status.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsConsentDTO(final String id, final String consentId, final int typeId,
+ final String authorizationDetailJson,
+ final boolean isConsentActive, final int tenantId) {
+
+ super(id, typeId, authorizationDetailJson, tenantId);
+ this.consentId = consentId;
+ this.isConsentActive = isConsentActive;
+ }
+
+ /**
+ * Constructs an {@link AuthorizationDetailsConsentDTO} with essential fields.
+ *
+ * @param consentId the consent ID associated with the authorization detail.
+ * @param authorizationDetail the {@link AuthorizationDetail} object.
+ * @param isConsentActive the consent status.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsConsentDTO(final String consentId,
+ final AuthorizationDetail authorizationDetail,
+ final boolean isConsentActive, final int tenantId) {
+
+ super(authorizationDetail, tenantId);
+ this.consentId = consentId;
+ this.isConsentActive = isConsentActive;
+ }
+
+ /**
+ * Checks if the consent is active.
+ *
+ * @return {@code true} if consent is active, {@code false} otherwise.
+ */
+ public boolean isConsentActive() {
+ return isConsentActive;
+ }
+
+ /**
+ * Gets the consent ID associated with the authorization detail.
+ *
+ * @return the consent ID.
+ */
+ public String getConsentId() {
+ return consentId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
new file mode 100644
index 0000000000..fe6a85b8ef
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
@@ -0,0 +1,98 @@
+package org.wso2.carbon.identity.oauth2.rar.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils;
+
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
+
+/**
+ * Data Transfer Object (DTO) for representing authorization details.
+ * This class encapsulates the details of authorization, including the ID, type ID,
+ * authorization detail object, and tenant ID.
+ */
+public class AuthorizationDetailsDTO {
+
+ final String id;
+ final int typeId;
+ final AuthorizationDetail authorizationDetail;
+ final int tenantId;
+
+ /**
+ * Constructs an AuthorizationDetailsDTO with all fields.
+ *
+ * @param id the ID of the authorization detail DTO.
+ * @param typeId the type ID of the authorization detail.
+ * @param authorizationDetail the authorization detail object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsDTO(final String id, final int typeId, final AuthorizationDetail authorizationDetail,
+ final int tenantId) {
+
+ this.id = id;
+ this.typeId = typeId;
+ this.authorizationDetail = authorizationDetail;
+ this.tenantId = tenantId;
+ }
+
+ /**
+ * Constructs an AuthorizationDetailsDTO from authorization detail JSON string.
+ *
+ * @param id the ID of the authorization detail DTO.
+ * @param typeId the type ID of the authorization detail.
+ * @param authorizationDetailJson the JSON string of the authorization detail.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsDTO(final String id, final int typeId, final String authorizationDetailJson,
+ final int tenantId) {
+
+ this(id, typeId, AuthorizationDetailsCommonUtils
+ .fromJSON(authorizationDetailJson, AuthorizationDetail.class, getDefaultObjectMapper()), tenantId);
+ }
+
+ /**
+ * Constructs an AuthorizationDetailsDTO with an authorization detail object and tenant ID.
+ *
+ * @param authorizationDetail the authorization detail object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsDTO(final AuthorizationDetail authorizationDetail, final int tenantId) {
+
+ this(null, 0, authorizationDetail, tenantId);
+ }
+
+ /**
+ * Gets the ID of the authorization detail.
+ *
+ * @return the ID of the authorization detail.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * Gets the type ID of the authorization detail.
+ *
+ * @return the type ID of the authorization detail.
+ */
+ public int getTypeId() {
+ return this.typeId;
+ }
+
+ /**
+ * Gets the authorization detail object.
+ *
+ * @return the authorization detail object.
+ */
+ public AuthorizationDetail getAuthorizationDetail() {
+ return this.authorizationDetail;
+ }
+
+ /**
+ * Gets the tenant ID.
+ *
+ * @return the tenant ID.
+ */
+ public int getTenantId() {
+ return this.tenantId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
new file mode 100644
index 0000000000..a75d7b8681
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
@@ -0,0 +1,51 @@
+package org.wso2.carbon.identity.oauth2.rar.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+
+/**
+ * Data Transfer Object (DTO) for representing authorization details along with access token information.
+ * This class extends {@link AuthorizationDetailsDTO} to include additional fields for access token ID.
+ */
+public class AuthorizationDetailsTokenDTO extends AuthorizationDetailsDTO {
+
+ final String accessTokenId;
+
+ /**
+ * Constructs an {@link AuthorizationDetailsTokenDTO} with all required fields.
+ *
+ * @param id the ID of the authorization detail DTO.
+ * @param accessTokenId the access token ID associated with the authorization detail.
+ * @param typeId the type ID of the authorization detail.
+ * @param authorizationDetail the {@link AuthorizationDetail} object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsTokenDTO(final String id, final String accessTokenId, final int typeId,
+ final String authorizationDetail, final int tenantId) {
+
+ super(id, typeId, authorizationDetail, tenantId);
+ this.accessTokenId = accessTokenId;
+ }
+
+ /**
+ * Constructs an {@link AuthorizationDetailsTokenDTO} with essential fields.
+ *
+ * @param accessTokenId the access token ID associated with the authorization detail.
+ * @param authorizationDetail the {@link AuthorizationDetail} object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsTokenDTO(final String accessTokenId, final AuthorizationDetail authorizationDetail,
+ final int tenantId) {
+
+ super(authorizationDetail, tenantId);
+ this.accessTokenId = accessTokenId;
+ }
+
+ /**
+ * Gets the access token ID associated with the authorization detail.
+ *
+ * @return the access token ID.
+ */
+ public String getAccessTokenId() {
+ return this.accessTokenId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
deleted file mode 100644
index 62a65d9859..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar.exception;
-
-/**
- *
- */
-public class AuthorizationDetailsProcessingException extends RuntimeException {
-
- private static final long serialVersionUID = -206212512259482200L;
-
- /**
- * Constructs a new exception with an error message.
- *
- * @param message The detail message.
- */
- public AuthorizationDetailsProcessingException(String message) {
-
- super(message);
- }
-
- /**
- * Constructs a new exception with the message and cause.
- *
- * @param message The detail message.
- * @param cause The cause.
- */
- public AuthorizationDetailsProcessingException(String message, Throwable cause) {
-
- super(message, cause);
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
deleted file mode 100644
index a35e8bd0ae..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/handler/RARAccessTokenResponseHandler.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.wso2.carbon.identity.oauth2.rar.handler;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.json.JsonMapper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.json.JSONArray;
-import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
-import org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails;
-import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
-import org.wso2.carbon.identity.oauth2.token.handlers.response.AccessTokenResponseHandler;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- */
-public class RARAccessTokenResponseHandler implements AccessTokenResponseHandler {
- private static final ObjectMapper OBJECT_MAPPER = new JsonMapper();
- private static final Log LOG = LogFactory.getLog(RARAccessTokenResponseHandler.class);
-
- @Override
-// public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMessageContext tokReqMsgCtx)
-// throws IdentityOAuth2Exception {
-//
-// List authorizationDetails = AuthorizationDetailService.getInstance()
-// .getConsentedAuthorizationDetailsByAuthzCode(tokReqMsgCtx.getOauth2AccessTokenReqDTO()
-// .getAuthorizationCode());
-//
-// Map additionalAttributes = new HashMap<>();
-// if (isNotEmptyList(authorizationDetails)) {
-// additionalAttributes.put(AUTHORIZATION_DETAILS, convertToJsonArray(authorizationDetails));
-// }
-// return additionalAttributes;
-// }
-
- public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMessageContext tokReqMsgCtx)
- throws IdentityOAuth2Exception {
-
- Map additionalAttributes = new HashMap<>();
-
- return additionalAttributes;
- }
-
-
- private boolean isNotEmptyList(List list) {
- return list != null && !list.isEmpty();
- }
-
- private JSONArray convertToJsonArray(List authorizationDetails) {
- try {
- return OBJECT_MAPPER.convertValue(OBJECT_MAPPER.writeValueAsString(authorizationDetails), JSONArray.class);
- } catch (JsonProcessingException e) {
- LOG.error("Serialization error. Caused by, ", e);
- }
- return new JSONArray(authorizationDetails);
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
deleted file mode 100644
index bd0c92f5f3..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsDataHolder.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. 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.oauth2.rar.internal;
-
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Singleton class that holds rich authorization details data.
- * This class uses the singleton design pattern to ensure there is only one instance
- * managing the authorization details providers. The instance is lazily initialized
- * with double-checked locking to ensure thread safety.
- * The class provides methods to retrieve and set the authorization details data,
- * which can be used in different parts of the application to manage rich authorization details.
- */
-public class AuthorizationDetailsDataHolder {
-
- private static volatile AuthorizationDetailsDataHolder instance;
- private Set authorizationDetailsProviders;
-
- /**
- * Private constructor to prevent instantiation from outside the class.
- */
- private AuthorizationDetailsDataHolder() {
-
- this.authorizationDetailsProviders = new HashSet<>();
- }
-
- /**
- * Returns the singleton instance of {@link AuthorizationDetailsDataHolder}.
- *
- * This method uses double-checked locking to ensure that the instance is initialized
- * only once and in a thread-safe manner. If the instance is not already created, it
- * will be created and returned; otherwise, the existing instance will be returned.
- *
- * @return The singleton instance of {@link AuthorizationDetailsDataHolder}.
- */
- public static AuthorizationDetailsDataHolder getInstance() {
-
- if (instance == null) {
- synchronized (AuthorizationDetailsDataHolder.class) {
- if (instance == null) {
- instance = new AuthorizationDetailsDataHolder();
- }
- }
- }
- return instance;
- }
-
- /**
- * Returns the current set of {@link AuthorizationDetailsProvider} instances.
- *
- * This method provides access to the authorization details providers.
- * The returned set can be used to query or modify the authorization details providers.
- *
- * @return A {@link Set} of {@link AuthorizationDetailsProvider} instances.
- */
- public Set getAuthorizationDetailsProviders() {
-
- return this.authorizationDetailsProviders;
- }
-
- /**
- * Sets the set of {@link AuthorizationDetailsProvider} instances to the provided value.
- *
- * This method replaces the current set of authorization details providers with the
- * provided set. It can be used to update the list of providers that the application
- * uses to manage authorization details.
- *
- * @param authorizationDetailsProviders The new {@link Set} of {@link AuthorizationDetailsProvider} instances.
- */
- public void setAuthorizationDetailsProviders(Set authorizationDetailsProviders) {
-
- this.authorizationDetailsProviders = authorizationDetailsProviders;
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
deleted file mode 100644
index 2cd272dc71..0000000000
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/internal/AuthorizationDetailsServiceComponent.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. 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.oauth2.rar.internal;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProvider;
-
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-/**
- * Authorization Details OSGI service component.
- */
-@Component(name = "org.wso2.carbon.identity.oauth.rar.internal.AuthorizationDetailsServiceComponent")
-public class AuthorizationDetailsServiceComponent {
- private static final Log log = LogFactory.getLog(AuthorizationDetailsServiceComponent.class);
-
- @Activate
- protected void activate(ComponentContext context) {
-
- AuthorizationDetailsDataHolder.getInstance().setAuthorizationDetailsProviders(
- loadAuthorizationDetailsProviders(ServiceLoader.load(AuthorizationDetailsProvider.class,
- this.getClass().getClassLoader())));
-
- log.debug("AuthorizationDetailsServiceComponent is activated");
- }
-
- @Deactivate
- protected void deactivate(ComponentContext context) {
-
- log.debug("AuthorizationDetailsServiceComponent is deactivated");
- }
-
- /**
- * Loads supported authorization details providers from the provided {@link ServiceLoader}.
- *
- * @param serviceLoader {@link ServiceLoader} for {@link AuthorizationDetailsProvider}.
- * @return Set of authorization details providers.
- */
- private Set loadAuthorizationDetailsProviders(
- final ServiceLoader serviceLoader) {
-
- return StreamSupport.stream(serviceLoader.spliterator(), false)
- .collect(Collectors.toSet());
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
similarity index 91%
rename from components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
index 96194b3485..9d3c87af10 100644
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetail.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
@@ -16,24 +16,23 @@
* under the License.
*/
-package org.wso2.carbon.identity.oauth2.rar.common.model;
+package org.wso2.carbon.identity.oauth2.rar.model;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
import java.util.function.Function;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
+
/**
* Represents an individual authorization details object which specifies the authorization requirements for a
* specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
@@ -71,15 +70,13 @@
*
* Refer to
* OAuth 2.0 Rich Authorization Requests for detailed information on the Authorization Details structure.
- *
- * @since 7.0.26.9
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AuthorizationDetail implements Serializable {
private static final long serialVersionUID = -3928636285264078857L;
- @JsonIgnore
+ @JsonProperty("_id")
private String id;
private String type;
private List locations;
@@ -91,16 +88,21 @@ public class AuthorizationDetail implements Serializable {
private Map details;
private String consentDescription;
- public AuthorizationDetail() {
- this.setId(UUID.randomUUID().toString());
- }
-
+ /**
+ * Gets the unique ID of the authorization detail.
+ *
+ * @return the ID of the authorization detail.
+ */
public String getId() {
+
return this.id;
}
- @JsonProperty("_id")
+ /**
+ * Sets a unique temporary ID for a given authorization detail instance.
+ */
public void setId(final String id) {
+
this.id = id;
}
@@ -112,13 +114,15 @@ public void setId(final String id) {
*
* @return The String value of the type field
* @see
- * Authorization Details Types
+ * Authorization Details Types
*/
public String getType() {
+
return this.type;
}
public void setType(final String type) {
+
this.type = type;
}
@@ -131,10 +135,12 @@ public void setType(final String type) {
* @return A list of locations or {@code null} if the {@code locations} field is not present.
*/
public List getLocations() {
+
return this.locations;
}
public void setLocations(final List locations) {
+
this.locations = locations;
}
@@ -146,10 +152,12 @@ public void setLocations(final List locations) {
* @return A list of actions or {@code null} if the {@code actions} field is not present.
*/
public List getActions() {
+
return this.actions;
}
public void setActions(final List actions) {
+
this.actions = actions;
}
@@ -161,10 +169,12 @@ public void setActions(final List actions) {
* @return A list of datatypes or {@code null} if the {@code datatypes} field is not present.
*/
public List getDataTypes() {
+
return this.dataTypes;
}
public void setDataTypes(final List dataTypes) {
+
this.dataTypes = dataTypes;
}
@@ -176,10 +186,12 @@ public void setDataTypes(final List dataTypes) {
* @return The String value of the identifier or {@code null} if the {@code identifier} field is not present.
*/
public String getIdentifier() {
+
return this.identifier;
}
public void setIdentifier(final String identifier) {
+
this.identifier = identifier;
}
@@ -192,10 +204,12 @@ public void setIdentifier(final String identifier) {
* @return The String value of the privileges or {@code null} if the {@code privileges} field is not present.
*/
public List getPrivileges() {
+
return this.privileges;
}
public void setPrivileges(final List privileges) {
+
this.privileges = privileges;
}
@@ -207,15 +221,18 @@ public void setPrivileges(final List privileges) {
*/
@JsonAnyGetter
public Map getDetails() {
+
return this.details;
}
public void setDetails(final Map details) {
+
this.details = details;
}
@JsonAnySetter
public void setDetail(final String key, final Object value) {
+
if (this.details == null) {
setDetails(new HashMap<>());
}
@@ -243,6 +260,7 @@ public String getConsentDescription() {
* explaining what they are consenting to.
*/
public void setConsentDescription(final String consentDescription) {
+
this.consentDescription = consentDescription;
}
@@ -269,6 +287,7 @@ public void setConsentDescription(final String consentDescription) {
* @return the consent description if present, otherwise the value from the Function
*/
public String getConsentDescriptionOrDefault(Function defaultFunction) {
+
return StringUtils.isNotEmpty(this.getConsentDescription()) ?
this.getConsentDescription() : defaultFunction.apply(this);
}
@@ -279,11 +298,23 @@ public String getConsentDescriptionOrDefault(Function} representation of the authorization detail.
+ */
+ public Map toMap() {
+
+ return AuthorizationDetailsCommonUtils.toMap(this, getDefaultObjectMapper());
}
@Override
public String toString() {
+
return "AuthorizationDetails {" +
"type='" + this.type + '\'' +
", locations=" + this.locations +
diff --git a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
similarity index 80%
rename from components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
index 0befab02b1..11c16e87fb 100644
--- a/components/org.wso2.carbon.identity.oauth.rar.common/src/main/java/org/wso2/carbon/identity/oauth2/rar/common/model/AuthorizationDetails.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
@@ -16,21 +16,23 @@
* under the License.
*/
-package org.wso2.carbon.identity.oauth2.rar.common.model;
+package org.wso2.carbon.identity.oauth2.rar.model;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsCommonUtils;
-import org.wso2.carbon.identity.oauth2.rar.common.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
import java.io.Serializable;
import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
+
/**
* Represents a set of {@link AuthorizationDetail} objects which specifies the authorization requirements for a
* specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
@@ -52,6 +54,7 @@ public class AuthorizationDetails implements Serializable {
* Constructs an empty set of {@link AuthorizationDetail}.
*/
public AuthorizationDetails() {
+
this(Collections.emptySet());
}
@@ -61,6 +64,7 @@ public AuthorizationDetails() {
* @param authorizationDetails The set of authorization details. If null, an empty set is assigned.
*/
public AuthorizationDetails(final Set authorizationDetails) {
+
this.authorizationDetails = Optional.ofNullable(authorizationDetails)
.map(Collections::unmodifiableSet)
.orElse(Collections.emptySet());
@@ -72,8 +76,9 @@ public AuthorizationDetails(final Set authorizationDetails)
* @param authorizationDetailsJson The JSON string representing the authorization details.
*/
public AuthorizationDetails(final String authorizationDetailsJson) {
+
this(AuthorizationDetailsCommonUtils.fromJSONArray(
- authorizationDetailsJson, AuthorizationDetail.class, new ObjectMapper()));
+ authorizationDetailsJson, AuthorizationDetail.class, getDefaultObjectMapper()));
}
/**
@@ -82,15 +87,30 @@ public AuthorizationDetails(final String authorizationDetailsJson) {
* @return A set of {@link AuthorizationDetail}.
*/
public Set getDetails() {
+
return this.authorizationDetails;
}
+ /**
+ * Converts a stream of AuthorizationDetail objects into a {@link Set} of {@link Map}.
+ *
+ * Each AuthorizationDetail object is transformed into a Map representation using
+ * the {@link AuthorizationDetail#toMap} method.
+ *
+ * @return a Set of Maps representing the AuthorizationDetail objects.
+ */
+ public Set
*
- * @see AuthorizationDetailsProvider AuthorizationDetailsService
+ * @see AuthorizationDetailsProcessor AuthorizationDetailsService
* @see
* Request Parameter "authorization_details"
- * @since 7.0.26.9
*/
public class AuthorizationDetailsProviderFactory {
private static volatile AuthorizationDetailsProviderFactory instance;
- private final Map supportedAuthorizationDetailsTypes;
+ private final Map supportedAuthorizationDetailsTypes;
/**
* Private constructor to initialize the factory.
@@ -65,16 +63,17 @@ private AuthorizationDetailsProviderFactory() {
}
/**
- * Loads supported authorization details types from the provided {@link ServiceLoader}.
+ * Loads supported authorization details Processors from the provided {@link ServiceLoader}.
*
- * @return Map of authorization details types with their corresponding services.
+ * @return Map of authorization details types with their corresponding SPI services.
*/
- private Map loadSupportedAuthorizationDetailsTypes() {
+ private Map loadSupportedAuthorizationDetailsTypes() {
+
+ final ServiceLoader serviceLoader = ServiceLoader
+ .load(AuthorizationDetailsProcessor.class, this.getClass().getClassLoader());
- return AuthorizationDetailsDataHolder.getInstance()
- .getAuthorizationDetailsProviders()
- .stream()
- .collect(Collectors.toMap(AuthorizationDetailsProvider::getType, Function.identity()));
+ return StreamSupport.stream(serviceLoader.spliterator(), false)
+ .collect(Collectors.toMap(AuthorizationDetailsProcessor::getType, Function.identity()));
}
/**
@@ -95,13 +94,13 @@ public static AuthorizationDetailsProviderFactory getInstance() {
}
/**
- * Returns the {@link AuthorizationDetailsProvider} provider for the given type.
+ * Returns the {@link AuthorizationDetailsProcessor} provider for the given type.
*
* @param type A supported authorization details type.
- * @return {@link Optional} containing the {@link AuthorizationDetailsProvider} if present, otherwise empty.
- * @see AuthorizationDetailsProvider#getType() getAuthorizationDetailsType
+ * @return {@link Optional} containing the {@link AuthorizationDetailsProcessor} if present, otherwise empty.
+ * @see AuthorizationDetailsProcessor#getType() getAuthorizationDetailsType
*/
- public Optional getProviderByType(final String type) {
+ public Optional getProviderByType(final String type) {
return Optional.ofNullable(this.supportedAuthorizationDetailsTypes.get(type));
}
@@ -111,7 +110,7 @@ public Optional getProviderByType(final String typ
*
* @param type The type to check.
* @return {@code true} if the type is supported, {@code false} otherwise.
- * @see AuthorizationDetailsProvider AuthorizationDetailsService
+ * @see AuthorizationDetailsProcessor AuthorizationDetailsService
*/
public boolean isSupportedAuthorizationDetailsType(final String type) {
@@ -121,7 +120,7 @@ public boolean isSupportedAuthorizationDetailsType(final String type) {
/**
* Returns a {@link Collections#unmodifiableSet} of all supported authorization details types.
* To be included as a supported authorization details type, there must be a custom implementation
- * of the {@link AuthorizationDetailsProvider} Service Provider Interface (SPI) available in the classpath
+ * of the {@link AuthorizationDetailsProcessor} Service Provider Interface (SPI) available in the classpath
* for the specified type.
*
* @return A set of supported authorization details types.
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
new file mode 100644
index 0000000000..3ccc2784cc
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
@@ -0,0 +1,37 @@
+package org.wso2.carbon.identity.oauth2.rar.exception;
+
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException;
+
+/**
+ * Exception class to represent failures related to Rich Authorization Requests in OAuth 2.0 clients.
+ *
+ * This exception is thrown when there are errors in processing authorization details during the OAuth 2.0
+ * authorization flow. It extends the {@link IdentityOAuth2ClientException} class, providing more specific
+ * context for authorization-related issues.
+ */
+public class AuthorizationDetailsProcessingException extends IdentityOAuth2ClientException {
+
+ private static final long serialVersionUID = -206212512259482200L;
+
+ /**
+ * Constructs a new exception with the specified detail message.
+ *
+ * @param message The detail message. It provides information about the cause of the exception.
+ */
+ public AuthorizationDetailsProcessingException(final String message) {
+
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and cause.
+ *
+ * @param message The detail message. It provides information about the cause of the exception.
+ * @param cause The cause of the exception. It can be used to retrieve the stack trace or other information
+ * about the root cause of the exception.
+ */
+ public AuthorizationDetailsProcessingException(final String message, final Throwable cause) {
+
+ super(message, cause);
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
new file mode 100644
index 0000000000..998ea794ac
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.model;
+
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+
+import java.util.Objects;
+
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import static org.wso2.carbon.identity.oauth2.authz.AuthorizationHandlerManager.OAUTH_APP_PROPERTY;
+
+/**
+ * Represents the context for rich authorization requests in an OAuth2 flow.
+ *
+ * This class holds relevant details such as OAuth2 parameters, application details, the authenticated user,
+ * and specific authorization details. It is immutable to ensure that the context remains consistent throughout its use.
+ *
+ */
+public class AuthorizationDetailsContext {
+
+ private final AuthenticatedUser authenticatedUser;
+ private final AuthorizationDetail authorizationDetail;
+ private final HttpServletRequestWrapper httpServletRequestWrapper;
+ private final OAuthAppDO oAuthAppDO;
+ private final String[] scopes;
+
+ /**
+ * Constructs a new {@code AuthorizationDetailsContext}.
+ *
+ * This constructor ensures that all necessary details for an authorization context are provided.
+ *
+ *
+ * @param authenticatedUser the {@link AuthenticatedUser}.
+ * @param authorizationDetail the specific {@link AuthorizationDetail} to be validated.
+ * @param httpServletRequestWrapper the {@link HttpServletRequestWrapper} instance containing request details.
+ * @param oAuthAppDO the {@link OAuthAppDO} containing application details.
+ * @param scopes the array of scopes requested.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public AuthorizationDetailsContext(final AuthenticatedUser authenticatedUser,
+ final AuthorizationDetail authorizationDetail,
+ final HttpServletRequestWrapper httpServletRequestWrapper,
+ final OAuthAppDO oAuthAppDO,
+ final String[] scopes) {
+
+ this.authenticatedUser = Objects.requireNonNull(authenticatedUser, "authenticatedUser cannot be null");
+ this.authorizationDetail = Objects.requireNonNull(authorizationDetail, "authorizationDetail cannot be null");
+ this.httpServletRequestWrapper = Objects
+ .requireNonNull(httpServletRequestWrapper, "httpServletRequestWrapper cannot be null");
+ this.oAuthAppDO = Objects.requireNonNull(oAuthAppDO, "oAuthAppDO cannot be null");
+ this.scopes = Objects.requireNonNull(scopes, "scopes cannot be null");
+ }
+
+ /**
+ * Constructs a new {@code AuthorizationDetailsContext}.
+ *
+ * @param authorizationDetail the specific {@link AuthorizationDetail} to be validated.
+ * @param oAuthAuthzReqMessageContext the {@link OAuthAuthzReqMessageContext} instance which represent
+ * the authorization request context.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail,
+ final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
+
+ this(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getUser(),
+ authorizationDetail,
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getHttpServletRequestWrapper(),
+ (OAuthAppDO) oAuthAuthzReqMessageContext.getProperty(OAUTH_APP_PROPERTY),
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getScopes());
+ }
+
+ /**
+ * Constructs a new {@code AuthorizationDetailsContext}.
+ *
+ * @param authorizationDetail the specific {@link AuthorizationDetail} to be validated.
+ * @param oAuthTokenReqMessageContext the {@link OAuthTokenReqMessageContext} instance which represent
+ * the token request context.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail,
+ final OAuthTokenReqMessageContext oAuthTokenReqMessageContext) {
+
+ this(oAuthTokenReqMessageContext.getAuthorizedUser(),
+ authorizationDetail,
+ oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getHttpServletRequestWrapper(),
+ (OAuthAppDO) oAuthTokenReqMessageContext.getProperty(OAUTH_APP_PROPERTY),
+ oAuthTokenReqMessageContext.getScope());
+ }
+
+ /**
+ * Returns the {@code AuthorizationDetail} instance.
+ *
+ * @return the {@link AuthorizationDetail} instance.
+ */
+ public AuthorizationDetail getAuthorizationDetail() {
+ return this.authorizationDetail;
+ }
+
+ /**
+ * Returns the OAuth application details.
+ *
+ * @return the {@link OAuthAppDO} instance.
+ */
+ public OAuthAppDO getoAuthAppDO() {
+ return this.oAuthAppDO;
+ }
+
+ /**
+ * Returns the authenticated user.
+ *
+ * @return the {@link AuthenticatedUser} instance.
+ */
+ public AuthenticatedUser getAuthenticatedUser() {
+ return this.authenticatedUser;
+ }
+
+ /**
+ * Returns the HTTP servlet request user.
+ *
+ * @return the {@link HttpServletRequestWrapper} instance containing HTTP request details.
+ */
+ public HttpServletRequestWrapper getHttpServletRequestWrapper() {
+ return this.httpServletRequestWrapper;
+ }
+
+ /**
+ * Returns the valid scopes requested by the client.
+ *
+ * @return the {@link String} array of scopes.
+ */
+ public String[] getScopes() {
+ return this.scopes;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
new file mode 100644
index 0000000000..a6d4baa1cd
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
@@ -0,0 +1,49 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.token.handlers.response.AccessTokenResponseHandler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.isRichAuthorizationRequest;
+
+/**
+ * Class responsible for modifying the access token response to include user-consented authorization details.
+ *
+ * This class enhances the access token response by appending user-consented authorization details.
+ * It is invoked by the {@link org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer#issue} method during
+ * the OAuth 2.0 token issuance process.
+ */
+public class AccessTokenResponseRARHandler implements AccessTokenResponseHandler {
+
+ private static final Log log = LogFactory.getLog(AccessTokenResponseRARHandler.class);
+
+ /**
+ * Returns Rich Authorization Request attributes to be added to the access token response.
+ *
+ * @param oAuthTokenReqMessageContext {@link OAuthTokenReqMessageContext} token request message context.
+ * @return Map of additional attributes to be added to the token response.
+ * @throws IdentityOAuth2Exception Error while constructing additional token response attributes.
+ */
+ @Override
+ public Map getAdditionalTokenResponseAttributes(
+ final OAuthTokenReqMessageContext oAuthTokenReqMessageContext) throws IdentityOAuth2Exception {
+
+ Map additionalAttributes = new HashMap<>();
+ if (isRichAuthorizationRequest(oAuthTokenReqMessageContext.getAuthorizationDetails())) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Processing Rich Authorization Request in token flow. authorization_details: " +
+ oAuthTokenReqMessageContext.getAuthorizationDetails().toJsonString());
+ }
+ additionalAttributes.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
+ oAuthTokenReqMessageContext.getAuthorizationDetails().toSet());
+ }
+ return additionalAttributes;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
new file mode 100644
index 0000000000..e2399aff36
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
@@ -0,0 +1,118 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth.common.OAuthConstants;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.IntrospectionDataProvider;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2IntrospectionResponseDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS;
+
+/**
+ * Class responsible for modifying the introspection response to include user-consented authorization details.
+ *
+ * This class enhances the introspection response by appending user-consented authorization details.
+ * It is invoked by the /introspect endpoint of the oauth.endpoint webapp during the token introspection process.
+ */
+public class IntrospectionRARDataProvider implements IntrospectionDataProvider {
+
+ private static final Log log = LogFactory.getLog(IntrospectionRARDataProvider.class);
+ private final AuthorizationDetailsValidator authorizationDetailsValidator;
+
+ public IntrospectionRARDataProvider() {
+
+ this.authorizationDetailsValidator =
+ OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsValidator();
+ }
+
+ /**
+ * Provides additional Rich Authorization Requests data for OAuth token introspection.
+ *
+ * @param tokenValidationRequestDTO Token validation request DTO.
+ * @param introspectionResponseDTO Token introspection response DTO.
+ * @return Map of additional data to be added to the introspection response.
+ * @throws IdentityOAuth2Exception If an error occurs while setting additional introspection data.
+ */
+ @Override
+ public Map getIntrospectionData(
+ final OAuth2TokenValidationRequestDTO tokenValidationRequestDTO,
+ final OAuth2IntrospectionResponseDTO introspectionResponseDTO) throws IdentityOAuth2Exception {
+
+ final Map introspectionData = new HashMap<>();
+ final OAuth2TokenValidationMessageContext tokenValidationMessageContext =
+ generateOAuth2TokenValidationMessageContext(tokenValidationRequestDTO, introspectionResponseDTO);
+
+ if (Objects.nonNull(tokenValidationMessageContext)) {
+ final AuthorizationDetails validatedAuthorizationDetails = this.authorizationDetailsValidator
+ .getValidatedAuthorizationDetails(tokenValidationMessageContext);
+ introspectionData.put(AUTHORIZATION_DETAILS, validatedAuthorizationDetails.toSet());
+ }
+ return introspectionData;
+ }
+
+ /**
+ * Generates an OAuth2TokenValidationMessageContext based on the token validation request and
+ * introspection response.
+ *
+ * @param tokenValidationRequestDTO The OAuth2 token validation request DTO.
+ * @param introspectionResponseDTO The OAuth2 introspection response DTO.
+ * @return The generated OAuth2TokenValidationMessageContext.
+ * @throws IdentityOAuth2Exception If an error occurs during the generation of the context.
+ */
+ private OAuth2TokenValidationMessageContext generateOAuth2TokenValidationMessageContext(
+ final OAuth2TokenValidationRequestDTO tokenValidationRequestDTO,
+ final OAuth2IntrospectionResponseDTO introspectionResponseDTO) throws IdentityOAuth2Exception {
+
+ // Check if the introspection response contains a validation message context
+ if (introspectionResponseDTO.getProperties().containsKey(OAuth2Util.OAUTH2_VALIDATION_MESSAGE_CONTEXT)) {
+ log.debug("Introspection response contains a validation message context.");
+
+ final Object oAuth2TokenValidationMessageContext = introspectionResponseDTO.getProperties()
+ .get(OAuth2Util.OAUTH2_VALIDATION_MESSAGE_CONTEXT);
+
+ if (oAuth2TokenValidationMessageContext instanceof OAuth2TokenValidationMessageContext) {
+ return (OAuth2TokenValidationMessageContext) oAuth2TokenValidationMessageContext;
+ }
+ } else {
+ // Create a new validation message context
+ final OAuth2TokenValidationMessageContext oAuth2TokenValidationMessageContext =
+ new OAuth2TokenValidationMessageContext(tokenValidationRequestDTO,
+ generateOAuth2TokenValidationResponseDTO(introspectionResponseDTO));
+
+ final AccessTokenDO accessTokenDO = OAuth2ServiceComponentHolder.getInstance().getTokenProvider()
+ .getVerifiedAccessToken(tokenValidationRequestDTO.getAccessToken().getIdentifier(), false);
+
+ oAuth2TokenValidationMessageContext.addProperty(OAuthConstants.ACCESS_TOKEN_DO, accessTokenDO);
+
+ return oAuth2TokenValidationMessageContext;
+ }
+
+ log.debug("OAuth2TokenValidationMessageContext could not be generated. returning null");
+ return null;
+ }
+
+ private OAuth2TokenValidationResponseDTO generateOAuth2TokenValidationResponseDTO(
+ final OAuth2IntrospectionResponseDTO oAuth2IntrospectionResponseDTO) {
+
+ final OAuth2TokenValidationResponseDTO tokenValidationResponseDTO = new OAuth2TokenValidationResponseDTO();
+ tokenValidationResponseDTO.setValid(oAuth2IntrospectionResponseDTO.isActive());
+ tokenValidationResponseDTO.setErrorMsg(oAuth2IntrospectionResponseDTO.getError());
+ tokenValidationResponseDTO.setScope(OAuth2Util.buildScopeArray(oAuth2IntrospectionResponseDTO.getScope()));
+ tokenValidationResponseDTO.setExpiryTime(oAuth2IntrospectionResponseDTO.getExp());
+
+ return tokenValidationResponseDTO;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
new file mode 100644
index 0000000000..d429390131
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
@@ -0,0 +1,70 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.token.handlers.claims.JWTAccessTokenClaimProvider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Provides additional claims related to Rich Authorization Requests to be included in JWT Access Tokens.
+ * This implementation supports both the OAuth2 authorization and token flows.
+ */
+public class JWTAccessTokenRARClaimProvider implements JWTAccessTokenClaimProvider {
+
+ private static final Log log = LogFactory.getLog(JWTAccessTokenRARClaimProvider.class);
+
+ /**
+ * Returns a map of additional claims related to Rich Authorization Requests to be included in
+ * JWT Access Tokens issued in the OAuth2 authorize flow.
+ *
+ * @param oAuthAuthzReqMessageContext The OAuth authorization request message context.
+ * @return A map of additional claims.
+ * @throws IdentityOAuth2Exception If an error occurs during claim retrieval.
+ */
+ @Override
+ public Map getAdditionalClaims(final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ final Map additionalClaims = new HashMap<>();
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Processing Rich Authorization Request in authorization flow. authorization_details: " +
+ oAuthAuthzReqMessageContext.getAuthorizationDetails().toJsonString());
+ }
+ additionalClaims.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
+ oAuthAuthzReqMessageContext.getAuthorizationDetails().toSet());
+ }
+ return additionalClaims;
+ }
+
+ /**
+ * Returns a map of additional claims related to Rich Authorization Requests to be included in
+ * JWT Access Tokens issued in the OAuth2 token flow.
+ *
+ * @param oAuthTokenReqMessageContext The OAuth token request message context.
+ * @return A map of additional claims.
+ * @throws IdentityOAuth2Exception If an error occurs during claim retrieval.
+ */
+ @Override
+ public Map getAdditionalClaims(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ final Map additionalClaims = new HashMap<>();
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Processing Rich Authorization Request in token flow.authorization_details: " +
+ oAuthTokenReqMessageContext.getAuthorizationDetails().toJsonString());
+ }
+ additionalClaims.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
+ oAuthTokenReqMessageContext.getAuthorizationDetails().toSet());
+ }
+ return additionalClaims;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
new file mode 100644
index 0000000000..eaf24b4c39
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -0,0 +1,341 @@
+package org.wso2.carbon.identity.oauth2.rar.util;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
+import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.application.common.model.ServiceProvider;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.CarbonOAuthTokenRequest;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS_ID_PREFIX;
+
+/**
+ * Utility class for handling and validating authorization details in OAuth2 requests.
+ */
+public class AuthorizationDetailsUtils {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsUtils.class);
+
+ /**
+ * Determines if the given {@link OAuthAuthzReqMessageContext} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuthAuthzReqMessageContext The requested OAuthAuthzReqMessageContext to check.
+ * @return {@code true} if the OAuthAuthzReqMessageContext contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
+
+ return isRichAuthorizationRequest(oAuthAuthzReqMessageContext.getAuthorizationDetails());
+ }
+
+ /**
+ * Determines if the given {@link OAuthAuthzRequest} object contains {@code authorization_details}.
+ *
+ * @param oauthRequest The OAuth Authorization Request to check.
+ * @return {@code true} if the OAuth authorization request contains a non-blank authorization details parameter,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuthAuthzRequest oauthRequest) {
+
+ return StringUtils.isNotBlank(oauthRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ }
+
+ /**
+ * Determines if the given {@link CarbonOAuthTokenRequest} object contains {@code authorization_details}.
+ *
+ * @param carbonOAuthTokenRequest The OAuth Token Request to check.
+ * @return {@code true} if the OAuth token request contains a non-blank authorization details parameter,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final CarbonOAuthTokenRequest carbonOAuthTokenRequest) {
+
+ return StringUtils
+ .isNotBlank(carbonOAuthTokenRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ }
+
+ /**
+ * Determines if the request is a rich authorization request using provided {@link AuthorizationDetails} object.
+ *
+ * This method checks if the specified {@link AuthorizationDetails} instance is not {@code null}
+ * and has a non-empty details set.
+ *
+ * @param authorizationDetails The {@link AuthorizationDetails} to check.
+ * @return {@code true} if the {@link AuthorizationDetails} is not {@code null} and has a non-empty details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final AuthorizationDetails authorizationDetails) {
+
+ return authorizationDetails != null && !authorizationDetails.getDetails().isEmpty();
+ }
+
+ /**
+ * Determines if the given {@link OAuth2Parameters} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuth2Parameters The requested OAuth2Parameters to check.
+ * @return {@code true} if the OAuth2Parameters contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Parameters) {
+
+ return isRichAuthorizationRequest(oAuth2Parameters.getAuthorizationDetails());
+ }
+
+ /**
+ * Determines if the given {@link OAuthTokenReqMessageContext} object or the
+ * {@link OAuthTokenReqMessageContext#getOauth2AccessTokenReqDTO} contains {@link AuthorizationDetails}.
+ *
+ * @param oAuthTokenReqMessageContext The requested oAuthTokenReqMessageContext to check.
+ * @return {@code true} if the oAuthTokenReqMessageContext contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext) {
+
+ return isRichAuthorizationRequest(oAuthTokenReqMessageContext.getAuthorizationDetails()) ||
+ isRichAuthorizationRequest(oAuthTokenReqMessageContext
+ .getOauth2AccessTokenReqDTO().getAuthorizationDetails());
+ }
+
+ /**
+ * Determines if the given {@link OAuth2AuthorizeReqDTO} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuth2AuthorizeReqDTO The requested oAuth2AuthorizeReqDTO to check.
+ * @return {@code true} if the oAuth2AuthorizeReqDTO contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO) {
+
+ return isRichAuthorizationRequest(oAuth2AuthorizeReqDTO.getAuthorizationDetails());
+ }
+
+ /**
+ * Retrieves the application resource ID from the client ID.
+ *
+ * @param clientId The client ID.
+ * @return The application resource ID.
+ * @throws IdentityOAuth2Exception if an error occurs while retrieving the application resource ID.
+ */
+ public static String getApplicationResourceIdFromClientId(final String clientId) throws IdentityOAuth2Exception {
+
+ final ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(clientId);
+ if (serviceProvider != null) {
+ return serviceProvider.getApplicationResourceId();
+ }
+ throw new IdentityOAuth2Exception("Unable to find a service provider for client Id: " + clientId);
+ }
+
+ /**
+ * Retrieves the user ID from the authenticated user.
+ *
+ * @param authenticatedUser The authenticated user.
+ * @return The user ID.
+ * @throws IdentityOAuth2Exception if an error occurs while retrieving the user ID.
+ */
+ public static String getIdFromAuthenticatedUser(final AuthenticatedUser authenticatedUser)
+ throws IdentityOAuth2Exception {
+
+ try {
+ return authenticatedUser.getUserId();
+ } catch (UserIdNotFoundException e) {
+ log.error("Error occurred while extracting userId from authenticated user. Caused by, ", e);
+ throw new IdentityOAuth2Exception(
+ "User id is not found for user: " + authenticatedUser.getLoggableMaskedUserId(), e);
+ }
+ }
+
+ /**
+ * Generates a list of {@link AuthorizationDetailsConsentDTO} from the provided consent ID,
+ * authorization details, and tenant ID.
+ *
+ * @param consentId The consent ID.
+ * @param userConsentedAuthorizationDetails The user-consented authorization details.
+ * @param tenantId The tenant ID.
+ * @return A list of {@link AuthorizationDetailsConsentDTO}.
+ */
+ public static List getAuthorizationDetailsConsentDTOs(
+ final String consentId, final AuthorizationDetails userConsentedAuthorizationDetails, final int tenantId) {
+
+ return userConsentedAuthorizationDetails.stream()
+ .map(detail -> new AuthorizationDetailsConsentDTO(consentId, detail, true, tenantId))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Generates a list of {@link AuthorizationDetailsTokenDTO} from the provided access token and
+ * authorization details.
+ *
+ * @param accessTokenDO The access token data object.
+ * @param authorizationDetails The user-consented authorization details.
+ * @return A list of {@link AuthorizationDetailsTokenDTO}.
+ */
+ public static List getAccessTokenAuthorizationDetailsDTOs(
+ final AccessTokenDO accessTokenDO, final AuthorizationDetails authorizationDetails) {
+
+ return authorizationDetails
+ .stream()
+ .map(authorizationDetail -> new AuthorizationDetailsTokenDTO(
+ accessTokenDO.getTokenId(), authorizationDetail, accessTokenDO.getTenantID()))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Extracts the user-consented authorization details from the request parameters and OAuth2 parameters.
+ *
+ * @param httpServletRequest The HTTP servlet request containing the authorization details.
+ * @param oAuth2Parameters The OAuth2 parameters that include the authorization details.
+ * @return The {@link AuthorizationDetails} containing the user-consented authorization details.
+ */
+ public static AuthorizationDetails extractAuthorizationDetailsFromRequest(
+ final HttpServletRequest httpServletRequest, final OAuth2Parameters oAuth2Parameters) {
+
+ if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2Parameters)) {
+ log.debug("Request is not a rich authorization request. Returning empty authorization details.");
+ return new AuthorizationDetails();
+ }
+
+ // Extract consented authorization detail IDs from the parameter map
+ final Set consentedAuthorizationDetailIDs = httpServletRequest.getParameterMap().keySet().stream()
+ .filter(parameterName -> parameterName.startsWith(AUTHORIZATION_DETAILS_ID_PREFIX))
+ .map(parameterName -> parameterName.substring(AUTHORIZATION_DETAILS_ID_PREFIX.length()))
+ .collect(Collectors.toSet());
+
+ // Filter and collect the consented authorization details
+ final Set consentedAuthorizationDetails = oAuth2Parameters.getAuthorizationDetails()
+ .stream()
+ .filter(authorizationDetail -> consentedAuthorizationDetailIDs.contains(authorizationDetail.getId()))
+ .collect(Collectors.toSet());
+
+ log.debug("User consented authorization details extracted successfully.");
+ return new AuthorizationDetails(consentedAuthorizationDetails);
+ }
+
+ /**
+ * Transforms the given {@link AuthorizationDetails} by creating a new set of {@link AuthorizationDetail} objects
+ * with only the displayable fields ({@code type}, {@code id}, {@code consentDescription}) copied over.
+ *
+ * @param authorizationDetails The original AuthorizationDetails to be transformed.
+ * @return A new {@link AuthorizationDetails} object containing the displayable authorization details.
+ */
+ public static AuthorizationDetails getDisplayableAuthorizationDetails(
+ final AuthorizationDetails authorizationDetails) {
+
+ final Set displayableAuthorizationDetails = authorizationDetails.stream()
+ .map(protectedAuthorizationDetail -> {
+ final AuthorizationDetail authorizationDetail = new AuthorizationDetail();
+ authorizationDetail.setType(protectedAuthorizationDetail.getType());
+ authorizationDetail.setId(protectedAuthorizationDetail.getId());
+ authorizationDetail.setConsentDescription(protectedAuthorizationDetail.getConsentDescription());
+ return authorizationDetail;
+ }).collect(Collectors.toSet());
+
+ return new AuthorizationDetails(displayableAuthorizationDetails);
+ }
+
+ /**
+ * Trims the given {@link AuthorizationDetails} by setting the temporary {@code id} and {@code consentDescription}
+ * fields to null for each {@link AuthorizationDetail}.
+ *
+ * @param authorizationDetails The original AuthorizationDetails to be trimmed.
+ * @return The same AuthorizationDetails object with trimmed fields.
+ */
+ public static AuthorizationDetails getTrimmedAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ authorizationDetails.stream().forEach(authorizationDetail -> {
+ authorizationDetail.setId(null);
+ authorizationDetail.setConsentDescription(null);
+ });
+ return authorizationDetails;
+ }
+
+ /**
+ * Generates an {@link AuthorizationDetails} instance from given JSON string
+ * and assigns unique IDs for each {@link AuthorizationDetail}.
+ *
+ * @param authorizationDetailsJson The JSON string representing the authorization details.
+ * @return The AuthorizationDetails object with unique IDs assigned to each AuthorizationDetail.
+ */
+ public static AuthorizationDetails generateAndAssignUniqueIDs(final String authorizationDetailsJson) {
+
+ return assignUniqueIDsToAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
+ }
+
+ /**
+ * Generates unique IDs for each {@link AuthorizationDetail} within the given {@link AuthorizationDetails} object.
+ *
+ * @param authorizationDetails The AuthorizationDetails object containing a set of AuthorizationDetail objects.
+ * @return The AuthorizationDetails object with unique IDs assigned to each AuthorizationDetail.
+ */
+ public static AuthorizationDetails assignUniqueIDsToAuthorizationDetails(final AuthorizationDetails
+ authorizationDetails) {
+
+ authorizationDetails.stream().filter(Objects::nonNull)
+ .forEach(authorizationDetail -> authorizationDetail.setId(UUID.randomUUID().toString()));
+ return authorizationDetails;
+ }
+
+ /**
+ * Encodes the given AuthorizationDetails object to a URL-encoded JSON string.
+ *
+ * @param authorizationDetails The AuthorizationDetails object to be encoded.
+ * @return A URL-encoded JSON string representing the authorization details.
+ */
+ public static String getUrlEncodedAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Starts URL encoding authorization details: " + authorizationDetails.toJsonString());
+ }
+ if (isRichAuthorizationRequest(authorizationDetails)) {
+ return URLEncoder.encode(authorizationDetails.toJsonString(), StandardCharsets.UTF_8.toString());
+ }
+ } catch (UnsupportedEncodingException e) {
+ log.error("Error occurred while URL encoding authorization details. Caused by, ", e);
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * Decodes the given URL-encoded AuthorizationDetails JSON String.
+ *
+ * @param encodedAuthorizationDetails The encoded AuthorizationDetails String to be decoded.
+ * @return A URL-decoded JSON string representing the authorization details.
+ */
+ public static String getUrlDecodedAuthorizationDetails(final String encodedAuthorizationDetails) {
+
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Starts decoding URL encoded authorization details JSON: " + encodedAuthorizationDetails);
+ }
+ if (StringUtils.isNotEmpty(encodedAuthorizationDetails)) {
+ return URLDecoder.decode(encodedAuthorizationDetails, StandardCharsets.UTF_8.toString());
+ }
+ } catch (UnsupportedEncodingException e) {
+ log.error("Error occurred while URL decoding authorization details Json. Caused by, ", e);
+ }
+ return StringUtils.EMPTY;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
new file mode 100644
index 0000000000..2cdf2afd7f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
@@ -0,0 +1,62 @@
+package org.wso2.carbon.identity.oauth2.rar.validator;
+
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
+
+/**
+ * Interface for validating {@link AuthorizationDetails} in different OAuth2 message contexts.
+ *
+ * This interface provides methods to validate {@link AuthorizationDetails} across various OAuth2 message contexts,
+ * including authorization requests, token requests, and token validation requests. Implementations of this
+ * interface should handle the validation logic specific to the type of request and ensure that the returned
+ * AuthorizationDetails are accurate and compliant with the application's security policies.
+ */
+public interface AuthorizationDetailsValidator {
+
+ /**
+ * Validates and returns the {@link AuthorizationDetails} for the given {@link OAuthAuthzReqMessageContext}.
+ *
+ * Validates the {@link AuthorizationDetails} during the authorization request phase.
+ * This is typically invoked when an authorization request is received and needs to be processed.
+ *
+ * @param oAuthAuthzReqMessageContext The OAuth authorization request message context.
+ * @return The validated {@link AuthorizationDetails}.
+ * @throws AuthorizationDetailsProcessingException If an error occurs during the processing of authorization details
+ * @throws IdentityOAuth2ServerException if the validation fails due to a server error.
+ */
+ AuthorizationDetails getValidatedAuthorizationDetails(OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException;
+
+ /**
+ * Validates and returns the {@link AuthorizationDetails} for the given {@link OAuthTokenReqMessageContext}.
+ *
+ * Validates the AuthorizationDetails during the token request phase. This is usually called when an authorization
+ * code is exchanged for an access token, or when a refresh token request is made.
+ *
+ * @param oAuthTokenReqMessageContext The OAuth token request message context.
+ * @return The validated {@link AuthorizationDetails}.
+ * @throws AuthorizationDetailsProcessingException If an error occurs during the processing of authorization details
+ * @throws IdentityOAuth2ServerException if the validation fails due to a server error.
+ */
+ AuthorizationDetails getValidatedAuthorizationDetails(OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException;
+
+ /**
+ * Validates and returns the {@link AuthorizationDetails} for the given {@link OAuth2TokenValidationMessageContext}.
+ *
+ * Validates the {@link AuthorizationDetails} during the token validation phase. This method is often used when an
+ * access token is being introspected to ensure its legitimacy and the associated AuthorizationDetails.
+ *
+ * @param oAuth2TokenValidationMessageContext The OAuth2 token validation message context.
+ * @return The validated {@link AuthorizationDetails}.
+ * @throws AuthorizationDetailsProcessingException If an error occurs during the processing of authorization details
+ * @throws IdentityOAuth2ServerException If an error occurs related to the OAuth2 server.
+ */
+ AuthorizationDetails getValidatedAuthorizationDetails(OAuth2TokenValidationMessageContext
+ oAuth2TokenValidationMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException;
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
new file mode 100644
index 0000000000..52fce6d3e8
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.validator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.oltu.oauth2.common.message.types.GrantType;
+import org.wso2.carbon.identity.oauth.common.OAuthConstants;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
+import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Default implementation class responsible for validating {@link AuthorizationDetails} in different
+ * OAuth2 message contexts.
+ */
+public class DefaultAuthorizationDetailsValidator implements AuthorizationDetailsValidator {
+
+ private static final Log log = LogFactory.getLog(DefaultAuthorizationDetailsValidator.class);
+ private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
+ private final AuthorizationDetailsService authorizationDetailsService;
+
+ public DefaultAuthorizationDetailsValidator() {
+
+ this(
+ AuthorizationDetailsProviderFactory.getInstance(),
+ OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService()
+ );
+ }
+
+ public DefaultAuthorizationDetailsValidator(
+ final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory,
+ final AuthorizationDetailsService authorizationDetailsService) {
+
+ this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
+ this.authorizationDetailsService = authorizationDetailsService;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AuthorizationDetails getValidatedAuthorizationDetails(final OAuthAuthzReqMessageContext
+ oAuthAuthzReqMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ try {
+ return this.getValidatedAuthorizationDetails(
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getConsumerKey(),
+ OAuth2Util.getTenantId(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain()),
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getAuthorizationDetails(),
+ authorizationDetail ->
+ new AuthorizationDetailsContext(authorizationDetail, oAuthAuthzReqMessageContext)
+ );
+ } catch (IdentityOAuth2Exception e) {
+ log.error("Unable find the tenant ID of the domain: " +
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain() + " Caused by, ", e);
+ throw new AuthorizationDetailsProcessingException("Invalid tenant domain", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AuthorizationDetails getValidatedAuthorizationDetails(final OAuthTokenReqMessageContext
+ oAuthTokenReqMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ final OAuth2AccessTokenReqDTO accessTokenReqDTO = oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO();
+
+ if (GrantType.AUTHORIZATION_CODE.toString().equals(accessTokenReqDTO.getGrantType())) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping the authorization_details validation for authorization code flow " +
+ "as this validation has already happened in the authorize flow.");
+ }
+ return oAuthTokenReqMessageContext.getAuthorizationDetails();
+ }
+
+ if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(accessTokenReqDTO.getAuthorizationDetails())) {
+ if (log.isDebugEnabled()) {
+ log.debug("Client application does not request new authorization details. " +
+ "Returning previously validated authorization details.");
+
+ }
+ return oAuthTokenReqMessageContext.getAuthorizationDetails();
+ }
+
+ return this.getValidatedAuthorizationDetails(
+ accessTokenReqDTO.getClientId(),
+ oAuthTokenReqMessageContext.getTenantID(),
+ accessTokenReqDTO.getAuthorizationDetails(),
+ authorizationDetail -> new AuthorizationDetailsContext(authorizationDetail, oAuthTokenReqMessageContext)
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AuthorizationDetails getValidatedAuthorizationDetails(
+ final OAuth2TokenValidationMessageContext oAuth2TokenValidationMessageContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ try {
+ final AccessTokenDO accessTokenDO = (AccessTokenDO) oAuth2TokenValidationMessageContext
+ .getProperty(OAuthConstants.ACCESS_TOKEN_DO);
+
+ final AuthorizationDetails accessTokenAuthorizationDetails = this.authorizationDetailsService
+ .getAccessTokenAuthorizationDetails(accessTokenDO.getTokenId(), accessTokenDO.getTenantID());
+
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(accessTokenAuthorizationDetails)) {
+ final Set authorizedAuthorizationDetails =
+ this.getAuthorizedAuthorizationDetails(
+ accessTokenDO.getConsumerKey(),
+ accessTokenDO.getTenantID(),
+ accessTokenAuthorizationDetails);
+ return new AuthorizationDetails(authorizedAuthorizationDetails);
+ }
+ } catch (IdentityOAuth2Exception e) {
+ log.error("Error occurred while retrieving access token authorization details. Caused by, ", e);
+ throw new AuthorizationDetailsProcessingException("Unable to retrieve token authorization details", e);
+ }
+ return new AuthorizationDetails();
+ }
+
+ /**
+ * Validates the authorization details for OAuthTokenReqMessageContext.
+ *
+ * @param clientId The client ID.
+ * @param tenantId The tenant ID.
+ * @param authorizationDetails The set of authorization details to validate.
+ * @param contextProvider A lambda function to create the AuthorizationDetailsContext.
+ * @return An {@link AuthorizationDetails} object containing the validated authorization details.
+ * @throws AuthorizationDetailsProcessingException if validation fails.
+ */
+ private AuthorizationDetails getValidatedAuthorizationDetails(
+ final String clientId, final int tenantId, final AuthorizationDetails authorizationDetails,
+ final Function contextProvider)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ final Set validatedAuthorizationDetails = new HashSet<>();
+ for (final AuthorizationDetail authorizationDetail :
+ this.getAuthorizedAuthorizationDetails(clientId, tenantId, authorizationDetails)) {
+
+ if (!isSupportedAuthorizationDetailType(authorizationDetail.getType())) {
+ throw new AuthorizationDetailsProcessingException(String.format(AuthorizationDetailsConstants
+ .TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT, authorizationDetail.getType()));
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Validation started for authorization detail of type: " + authorizationDetail.getType());
+ }
+
+ final AuthorizationDetailsContext authorizationDetailsContext = contextProvider.apply(authorizationDetail);
+
+ if (this.isValidAuthorizationDetail(authorizationDetailsContext)) {
+ validatedAuthorizationDetails.add(getEnrichedAuthorizationDetail(authorizationDetailsContext));
+ }
+ }
+
+ return new AuthorizationDetails(validatedAuthorizationDetails);
+ }
+
+ private Set getAuthorizedAuthorizationDetails(
+ final String clientId, final int tenantId, final AuthorizationDetails authorizationDetails) {
+
+ final Set authorizedAuthorizationDetailsTypes =
+ this.getAuthorizedAuthorizationDetailsTypes(clientId, tenantId);
+
+ return authorizationDetails.stream()
+ .filter(authorizationDetail ->
+ authorizedAuthorizationDetailsTypes.contains(authorizationDetail.getType()))
+ .collect(Collectors.toSet());
+ }
+
+ private boolean isSupportedAuthorizationDetailType(final String authorizationDetailType) {
+
+ return this.authorizationDetailsProviderFactory
+ .isSupportedAuthorizationDetailsType(authorizationDetailType);
+ }
+
+ /**
+ * Checks if the provided authorization details context is valid.
+ *
+ * @param authorizationDetailsContext The context containing authorization details.
+ * @return {@code true} if the authorization details are valid; {@code false} otherwise.
+ */
+ private boolean isValidAuthorizationDetail(final AuthorizationDetailsContext authorizationDetailsContext)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ Optional optionalProvider = this.authorizationDetailsProviderFactory
+ .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType());
+
+ if (optionalProvider.isPresent()) {
+
+ final ValidationResult validationResult = optionalProvider.get().validate(authorizationDetailsContext);
+ if (log.isDebugEnabled() && validationResult.isInvalid()) {
+
+ log.debug(String.format("Authorization details validation failed for type %s. Caused by, %s",
+ authorizationDetailsContext.getAuthorizationDetail().getType(), validationResult.getReason()));
+
+ }
+ return validationResult.isValid();
+ }
+ throw new AuthorizationDetailsProcessingException(String.format(
+ AuthorizationDetailsConstants.TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT,
+ authorizationDetailsContext.getAuthorizationDetail().getType()));
+ }
+
+ /**
+ * Enriches the authorization details using the provided context.
+ *
+ * @param authorizationDetailsContext The context containing authorization details.
+ * @return An enriched {@link AuthorizationDetail} object.
+ */
+ private AuthorizationDetail getEnrichedAuthorizationDetail(
+ final AuthorizationDetailsContext authorizationDetailsContext) {
+
+ return this.authorizationDetailsProviderFactory
+ .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType())
+ .map(authorizationDetailsProcessor -> authorizationDetailsProcessor.enrich(authorizationDetailsContext))
+ // If provider is missing, return the original authorization detail instance
+ .orElse(authorizationDetailsContext.getAuthorizationDetail());
+ }
+
+ /**
+ * Retrieves the set of authorized authorization types for the given client and tenant domain.
+ *
+ * @param clientId The client ID.
+ * @param tenantId The tenant ID.
+ * @return A set of strings representing the authorized authorization types.
+ */
+ private Set getAuthorizedAuthorizationDetailsTypes(final String clientId, final int tenantId) {
+
+// try {
+// final String appId = OAuth2Util
+// .getApplicationResourceIDByClientId(clientID, tenantDomain, this.applicationMgtService);
+//
+//// OAuth2ServiceComponentHolder.getInstance().getAuthorizedAPIManagementService()
+// .getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
+// } catch (IdentityOAuth2Exception e) {
+// throw new RuntimeException(e);
+// }
+ Set authorizedAuthorizationDetailsTypes = new HashSet<>();
+ authorizedAuthorizationDetailsTypes.add("payment_initiation");
+ return authorizedAuthorizationDetailsTypes;
+ }
+
+
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/SuccessResponseDTO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/SuccessResponseDTO.java
index 4c96445fe5..524e5ce2ab 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/SuccessResponseDTO.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/SuccessResponseDTO.java
@@ -18,6 +18,7 @@
package org.wso2.carbon.identity.oauth2.responsemode.provider;
import org.apache.commons.lang.StringUtils;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import java.util.Set;
@@ -34,6 +35,7 @@ public class SuccessResponseDTO {
private String formPostBody;
private String subjectToken;
private Set scope = null;
+ private AuthorizationDetails authorizationDetails;
public String getAuthorizationCode() {
@@ -117,4 +119,25 @@ public void setSubjectToken(String subjectToken) {
this.subjectToken = subjectToken;
}
+
+ /**
+ * Retrieves the authorization details to be included in the successful authorization response.
+ *
+ * @return the {@link AuthorizationDetails} instance representing the current authorization information.
+ * If no authorization details are available, it will return {@code null}.
+ */
+ public AuthorizationDetails getAuthorizationDetails() {
+
+ return this.authorizationDetails;
+ }
+
+ /**
+ * Sets the authorization details to be included in the successful authorization response.
+ *
+ * @param authorizationDetails the {@link AuthorizationDetails} to set.
+ */
+ public void setAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ this.authorizationDetails = authorizationDetails;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/impl/FragmentResponseModeProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/impl/FragmentResponseModeProvider.java
index 51c5237234..313353d82e 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/impl/FragmentResponseModeProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/responsemode/provider/impl/FragmentResponseModeProvider.java
@@ -20,6 +20,9 @@
import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.responsemode.provider.AbstractResponseModeProvider;
import org.wso2.carbon.identity.oauth2.responsemode.provider.AuthorizationResponseDTO;
@@ -55,6 +58,8 @@ public String getAuthResponseRedirectUrl(AuthorizationResponseDTO authorizationR
String scope = authorizationResponseDTO.getSuccessResponseDTO().getScope();
String authenticatedIdPs = authorizationResponseDTO.getAuthenticatedIDPs();
String subjectToken = authorizationResponseDTO.getSuccessResponseDTO().getSubjectToken();
+ final AuthorizationDetails authorizationDetails = authorizationResponseDTO.getSuccessResponseDTO()
+ .getAuthorizationDetails();
List params = new ArrayList<>();
if (accessToken != null) {
params.add(OAuthConstants.ACCESS_TOKEN_RESPONSE_PARAM + "=" + accessToken);
@@ -93,6 +98,11 @@ public String getAuthResponseRedirectUrl(AuthorizationResponseDTO authorizationR
params.add(OAuthConstants.SUBJECT_TOKEN + "=" + subjectToken);
}
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(authorizationDetails)) {
+ params.add(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS + "=" +
+ AuthorizationDetailsUtils.getUrlEncodedAuthorizationDetails(authorizationDetails));
+ }
+
redirectUrl += "#" + String.join("&", params);
} else {
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 6d6f986290..ee5054ee99 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
@@ -64,6 +64,12 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
+import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
+import org.wso2.carbon.identity.oauth2.rar.validator.DefaultAuthorizationDetailsValidator;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationGrantHandler;
@@ -116,6 +122,7 @@ public class AccessTokenIssuer {
private Map authzGrantHandlers;
public static final String OAUTH_APP_DO = "OAuthAppDO";
private static final String SERVICE_PROVIDERS_SUB_CLAIM = "ServiceProviders.UseUsernameAsSubClaim";
+ private final AuthorizationDetailsValidator authorizationDetailsValidator;
/**
* Private constructor which will not allow to create objects of this class from outside
@@ -123,6 +130,7 @@ public class AccessTokenIssuer {
private AccessTokenIssuer() throws IdentityOAuth2Exception {
authzGrantHandlers = OAuthServerConfiguration.getInstance().getSupportedGrantTypes();
+ this.authorizationDetailsValidator = new DefaultAuthorizationDetailsValidator();
AppInfoCache appInfoCache = AppInfoCache.getInstance();
if (appInfoCache != null) {
if (log.isDebugEnabled()) {
@@ -449,6 +457,35 @@ private OAuth2AccessTokenRespDTO validateGrantAndIssueToken(OAuth2AccessTokenReq
return tokenRespDTO;
}
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(tokReqMsgCtx)) {
+ try {
+ final AuthorizationDetails validatedAuthorizationDetails = this.authorizationDetailsValidator
+ .getValidatedAuthorizationDetails(tokReqMsgCtx);
+ tokReqMsgCtx.setAuthorizationDetails(validatedAuthorizationDetails);
+ } catch (AuthorizationDetailsProcessingException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Invalid authorization details requested by client Id: " + tokenReqDTO.getClientId());
+ }
+
+ if (LoggerUtils.isDiagnosticLogsEnabled()) {
+ LoggerUtils.triggerDiagnosticLogEvent(new DiagnosticLog.DiagnosticLogBuilder(
+ OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE,
+ OAuthConstants.LogConstants.ActionIDs.VALIDATE_AUTHORIZATION_DETAILS)
+ .inputParam(LogConstants.InputKeys.CLIENT_ID, tokenReqDTO.getClientId())
+ .inputParam(OAuthConstants.LogConstants.InputKeys.REQUESTED_AUTHORIZATION_DETAILS,
+ tokenReqDTO.getAuthorizationDetails().toSet())
+ .resultMessage(AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG)
+ .logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION)
+ .resultStatus(DiagnosticLog.ResultStatus.FAILED));
+ }
+ tokenRespDTO = handleError(AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_CODE,
+ AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG, tokenReqDTO);
+ setResponseHeaders(tokReqMsgCtx, tokenRespDTO);
+ triggerPostListeners(tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest);
+ return tokenRespDTO;
+ }
+ }
+
handleTokenBinding(tokenReqDTO, grantType, tokReqMsgCtx, oAuthAppDO);
try {
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java
index 4f1a55358a..693b7fe8ab 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/OAuthTokenReqMessageContext.java
@@ -21,6 +21,7 @@
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding;
import java.util.Properties;
@@ -56,6 +57,8 @@ public class OAuthTokenReqMessageContext {
private boolean isImpersonationRequest;
+ private AuthorizationDetails authorizationDetails;
+
public OAuthTokenReqMessageContext(OAuth2AccessTokenReqDTO oauth2AccessTokenReqDTO) {
this.oauth2AccessTokenReqDTO = oauth2AccessTokenReqDTO;
@@ -183,4 +186,26 @@ public void setImpersonationRequest(boolean impersonationRequest) {
isImpersonationRequest = impersonationRequest;
}
+
+ /**
+ * Retrieves the user consented or authorized authorization details.
+ *
+ * @return the {@link AuthorizationDetails} instance representing the rich authorization requests.
+ * If no authorization details are available, it will return {@code null}.
+ */
+ public AuthorizationDetails getAuthorizationDetails() {
+
+ return this.authorizationDetails;
+ }
+
+ /**
+ * Sets the validated authorization details.
+ * This method updates the authorization details with the provided {@link AuthorizationDetails} instance.
+ *
+ * @param authorizationDetails the {@link AuthorizationDetails} to set.
+ */
+ public void setAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+
+ this.authorizationDetails = authorizationDetails;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
index 4fefb780b8..1ab7b78a5c 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
@@ -54,6 +54,9 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.OauthTokenIssuer;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
@@ -89,6 +92,7 @@ public abstract class AbstractAuthorizationGrantHandler implements Authorization
protected static final String EXISTING_TOKEN_ISSUED = "existingTokenUsed";
protected static final int SECONDS_TO_MILISECONDS_FACTOR = 1000;
private boolean isHashDisabled = OAuth2Util.isHashDisabled();
+ protected AuthorizationDetailsService authorizationDetailsService;
@Override
public void init() throws IdentityOAuth2Exception {
@@ -98,6 +102,7 @@ public void init() throws IdentityOAuth2Exception {
cacheEnabled = true;
oauthCache = OAuthCache.getInstance();
}
+ this.authorizationDetailsService = OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService();
}
@Override
@@ -419,6 +424,11 @@ private OAuth2AccessTokenRespDTO issueExistingAccessToken(OAuthTokenReqMessageCo
existingTokenBean.getTokenId(), true);
}
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(tokReqMsgCtx)) {
+ this.authorizationDetailsService.replaceAccessTokenAuthorizationDetails(existingTokenBean.getTokenId(),
+ existingTokenBean, tokReqMsgCtx);
+ }
+
setDetailsToMessageContext(tokReqMsgCtx, existingTokenBean);
return createResponseWithTokenBean(existingTokenBean, expireTime, scope);
}
@@ -555,6 +565,8 @@ private void persistAccessTokenInDB(OAuthTokenReqMessageContext tokReqMsgCtx, Ac
}
storeAccessToken(tokenReq, getUserStoreDomain(tokReqMsgCtx.getAuthorizedUser()), newTokenBean, newAccessToken,
existingTokenBean);
+ this.authorizationDetailsService
+ .storeOrReplaceAccessTokenAuthorizationDetails(newTokenBean, existingTokenBean, tokReqMsgCtx);
}
private void updateCacheIfEnabled(AccessTokenDO newTokenBean, String scope, OauthTokenIssuer oauthTokenIssuer)
@@ -1176,4 +1188,19 @@ private boolean isFederatedUser(OAuthTokenReqMessageContext tokReqMsgCtx) {
}
return tokReqMsgCtx.getAuthorizedUser().isFederatedUser();
}
+
+ protected void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ final int tenantId = OAuth2Util
+ .getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
+
+ final AuthorizationDetails userConsentedAuthorizationDetails =
+ this.authorizationDetailsService.getUserConsentedAuthorizationDetails(
+ oAuthTokenReqMessageContext.getAuthorizedUser(),
+ oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId(),
+ tenantId);
+
+ oAuthTokenReqMessageContext.setAuthorizationDetails(userConsentedAuthorizationDetails);
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
index 21b3ae46d0..e111552248 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
@@ -126,12 +126,15 @@ public String buildSyncLockString(OAuthTokenReqMessageContext tokReqMsgCtx) {
}
private void setPropertiesForTokenGeneration(OAuthTokenReqMessageContext tokReqMsgCtx,
- OAuth2AccessTokenReqDTO tokenReq, AuthzCodeDO authzCodeBean) {
+ OAuth2AccessTokenReqDTO tokenReq, AuthzCodeDO authzCodeBean)
+ throws IdentityOAuth2Exception {
+
tokReqMsgCtx.setAuthorizedUser(authzCodeBean.getAuthorizedUser());
tokReqMsgCtx.setScope(authzCodeBean.getScope());
// keep the pre processed authz code as a OAuthTokenReqMessageContext property to avoid
// calculating it again when issuing the access token.
tokReqMsgCtx.addProperty(AUTHZ_CODE, tokenReq.getAuthorizationCode());
+ super.setRARPropertiesForTokenGeneration(tokReqMsgCtx);
}
private boolean validateCallbackUrlFromRequest(String callbackUrlFromRequest,
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
index 8a2752997c..ccebaa2650 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
@@ -131,6 +131,8 @@ public OAuth2AccessTokenRespDTO issue(OAuthTokenReqMessageContext tokReqMsgCtx)
// sets accessToken, refreshToken and validity data
setTokenData(accessTokenBean, tokReqMsgCtx, validationBean, tokenReq, accessTokenBean.getIssuedTime());
persistNewToken(tokReqMsgCtx, accessTokenBean, tokenReq.getClientId());
+ super.authorizationDetailsService
+ .replaceAccessTokenAuthorizationDetails(validationBean.getTokenId(), accessTokenBean, tokReqMsgCtx);
if (log.isDebugEnabled()) {
log.debug("Persisted an access token for the refresh token, " +
@@ -222,6 +224,7 @@ private void setPropertiesForTokenGeneration(OAuthTokenReqMessageContext tokReqM
// Store the old access token as a OAuthTokenReqMessageContext property, this is already
// a preprocessed token.
tokReqMsgCtx.addProperty(PREV_ACCESS_TOKEN, validationBean);
+ super.setRARPropertiesForTokenGeneration(tokReqMsgCtx);
}
private boolean validateRefreshTokenInRequest(OAuth2AccessTokenReqDTO tokenReq,
diff --git a/pom.xml b/pom.xml
index 278ca1bfc9..e9dec24b8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,7 +67,6 @@
features/org.wso2.carbon.identity.oauth.server.feature
features/org.wso2.carbon.identity.oauth.ui.feature
features/org.wso2.carbon.identity.oauth.dcr.server.feature
- components/org.wso2.carbon.identity.oauth.rar.common
components/org.wso2.carbon.identity.oauth.rar
@@ -559,11 +558,6 @@
org.wso2.carbon.identity.oauth.rar
${project.version}
-
- org.wso2.carbon.identity.inbound.auth.oauth2
- org.wso2.carbon.identity.oauth.rar.common
- ${project.version}
-
From 824163c0d3fffeccb7bfe1e6d09c471782de863e Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Wed, 7 Aug 2024 15:43:34 +0530
Subject: [PATCH 03/28] Add unit tests for the rar module
---
.../pom.xml | 106 ++++++++++++-
.../rar/dao/AuthorizationDetailsDAOImpl.java | 27 ++--
.../dao/AuthorizationDetailsDAOImplTest.java | 143 ++++++++++++++++++
.../AuthorizationDetailsCommonUtilsTest.java | 136 +++++++++++++++++
.../identity/oauth2/rar/util/DAOUtils.java | 46 ++++++
.../src/test/resources/dbScripts/h2.sql | 29 ++++
.../src/test/resources/testng.xml | 28 ++++
7 files changed, 501 insertions(+), 14 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index b0999a268f..bccfc86fe7 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -55,11 +55,32 @@
provided
+
- junit
- junit
+ org.testng
+ testng
test
+
+
+ org.mockito
+ mockito-testng
+ test
+
+
+
+ org.jacoco
+ org.jacoco.agent
+ runtime
+ test
+
+
+
+ com.h2database
+ h2
+ test
+
+
@@ -80,6 +101,87 @@
2048
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ src/test/resources/testng.xml
+
+
+ target/jacoco.exec
+
+ true
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+ **/*Constants.class
+ **/model/**
+ **/dto/**
+
+
+
+
+ default-prepare-agent
+
+ prepare-agent
+
+
+
+ default-instrument
+
+ instrument
+
+
+
+ default-restore-instrumented-classes
+
+ restore-instrumented-classes
+
+
+
+ default-report
+ prepare-package
+
+ report
+
+
+
+ default-report-integration
+
+ report-integration
+
+
+
+ default-check
+
+ check
+
+
+
+
+ BUNDLE
+
+
+ COMPLEXITY
+ COVEREDRATIO
+ 0.80
+
+
+
+
+
+
+
+
+
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index b7a561d0f5..224a4c7e11 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -100,19 +100,22 @@ public Set getUserConsentedAuthorizationDetails(
public int[] updateUserConsentedAuthorizationDetails(
final List authorizationDetailsConsentDTOs) throws SQLException {
- try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
- final PreparedStatement ps =
- connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+// todo: This won't update the expected element. Hence, need to revisit the update logic
+ return null;
- for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
- ps.setString(1, consentDTO.getAuthorizationDetail().toJsonString());
- ps.setBoolean(2, consentDTO.isConsentActive());
- ps.setString(3, consentDTO.getConsentId());
- ps.setInt(4, consentDTO.getTenantId());
- ps.addBatch();
- }
- return ps.executeBatch();
- }
+// try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+// final PreparedStatement ps =
+// connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+//
+// for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
+// ps.setString(1, consentDTO.getAuthorizationDetail().toJsonString());
+// ps.setBoolean(2, consentDTO.isConsentActive());
+// ps.setString(3, consentDTO.getConsentId());
+// ps.setInt(4, consentDTO.getTenantId());
+// ps.addBatch();
+// }
+// return ps.executeBatch();
+// }
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
new file mode 100644
index 0000000000..c5784f9a80
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -0,0 +1,143 @@
+package org.wso2.carbon.identity.oauth2.rar.dao;
+
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.util.DAOUtils;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+
+public class AuthorizationDetailsDAOImplTest {
+
+ private static final String TEST_CONSENT_ID = "52481ccd-0927-4d17-8cfc-5110fc4aa009";
+ private static final String TEST_DB_NAME = "TEST_IAM_RAR_DATABASE";
+ private static final int TEST_TENANT_ID = 1234;
+ private static final String TEST_TOKEN_ID = "e1fea951-a3b5-4347-bd73-b18b3feecd54";
+ private static final String TEST_TYPE = "test_type_v1";
+
+ private MockedStatic identityDatabaseUtilMock;
+ private AuthorizationDetailsDAO uut;
+
+ @BeforeClass
+ public void setUp() throws SQLException {
+ this.uut = new AuthorizationDetailsDAOImpl();
+ DAOUtils.initializeDataSource(TEST_DB_NAME, DAOUtils.getFilePath("h2.sql"));
+ this.identityDatabaseUtilMock = Mockito.mockStatic(IdentityDatabaseUtil.class);
+ }
+
+ @AfterClass
+ public void tearDown() throws SQLException {
+
+ if (this.identityDatabaseUtilMock != null && !this.identityDatabaseUtilMock.isClosed()) {
+ this.identityDatabaseUtilMock.close();
+ }
+ }
+
+ @BeforeMethod
+ public void setUpBeforeMethod() throws SQLException {
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ }
+
+ @Test(priority = 0)
+ public void testAddUserConsentedAuthorizationDetails() throws SQLException {
+
+ assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+
+ AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
+ testAuthorizationDetail.setType(TEST_TYPE);
+
+ AuthorizationDetailsConsentDTO consentDTO =
+ new AuthorizationDetailsConsentDTO(TEST_CONSENT_ID, testAuthorizationDetail, true, TEST_TENANT_ID);
+ int[] result = uut.addUserConsentedAuthorizationDetails(Collections.singletonList(consentDTO));
+
+ assertEquals(1, result.length);
+ }
+
+ @Test(priority = 1)
+ public void testGetUserConsentedAuthorizationDetails() throws SQLException {
+
+ Set consentDTOs =
+ this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID);
+
+ assertEquals(1, consentDTOs.size());
+ consentDTOs.forEach(dto -> {
+ assertEquals(TEST_CONSENT_ID, dto.getConsentId());
+ assertNotNull(dto.getAuthorizationDetail());
+ assertEquals(TEST_TYPE, dto.getAuthorizationDetail().getType());
+ });
+ }
+
+ @Test(priority = 2)
+ public void testDeleteUserConsentedAuthorizationDetails() throws SQLException {
+
+ assertEquals(1, uut.deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID));
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+
+ assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
+ }
+
+ @Test(priority = 0)
+ public void testAddAccessTokenAuthorizationDetails() throws SQLException {
+ assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+
+ AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
+ testAuthorizationDetail.setType(TEST_TYPE);
+
+ AuthorizationDetailsTokenDTO tokenDTO =
+ new AuthorizationDetailsTokenDTO(TEST_TOKEN_ID, testAuthorizationDetail, TEST_TENANT_ID);
+
+ int[] result = uut.addAccessTokenAuthorizationDetails(Collections.singletonList(tokenDTO));
+
+ assertEquals(1, result.length);
+ }
+
+ @Test(priority = 1)
+ public void testGetAccessTokenAuthorizationDetails() throws SQLException {
+ Set tokenDTOs =
+ this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID);
+
+ assertEquals(1, tokenDTOs.size());
+ tokenDTOs.forEach(dto -> {
+ assertEquals(TEST_TOKEN_ID, dto.getAccessTokenId());
+ assertNotNull(dto.getAuthorizationDetail());
+ assertEquals(TEST_TYPE, dto.getAuthorizationDetail().getType());
+ });
+ }
+
+ @Test(priority = 2)
+ public void testDeleteAccessTokenAuthorizationDetails() throws SQLException {
+ assertEquals(1, uut.deleteAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID));
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+
+ assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
new file mode 100644
index 0000000000..e5c35d5d05
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
@@ -0,0 +1,136 @@
+package org.wso2.carbon.identity.oauth2.rar.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.mockito.Mockito;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.collections.Sets;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+
+/**
+ * Test class for {@link AuthorizationDetailsCommonUtils}.
+ */
+public class AuthorizationDetailsCommonUtilsTest {
+
+ private ObjectMapper objectMapper;
+ private ObjectMapper mockObjectMapper;
+ private static final String TEST_TYPE = "test_type_v1";
+
+ @BeforeClass
+ public void setUp() throws JsonProcessingException {
+
+ this.objectMapper = AuthorizationDetailsCommonUtils.getDefaultObjectMapper();
+ this.mockObjectMapper = Mockito.spy(this.objectMapper);
+
+ // mock
+ doThrow(JsonProcessingException.class)
+ .when(this.mockObjectMapper).writeValueAsString(any(TestAuthorizationDetail.class));
+ doThrow(JsonProcessingException.class).when(this.mockObjectMapper).writeValueAsString(any(Set.class));
+ }
+
+ @DataProvider(name = "AuthorizationDetailsCommonUtilsTestDataProvider")
+ public Object[][] provideAuthorizationDetailsCommonUtilsTestData(Method testMethod) {
+
+ switch (testMethod.getName()) {
+ case "shouldReturnNull_whenJSONIsInvalid":
+ case "shouldReturnCorrectSize_whenJSONArrayIsValid":
+ return new Object[][]{
+ {null, 0},
+ {"", 0},
+ {" ", 0},
+ {"invalid JSON", 0},
+ {"[]", 0},
+ {"[{}]", 1},
+ {"[{},{}]", 2}
+ };
+ case "shouldReturnCorrectType_whenJSONIsValid":
+ return new Object[][]{
+ {AuthorizationDetail.class},
+ {TestAuthorizationDetail.class}
+ };
+ }
+ return null;
+ }
+
+ @Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
+ public void shouldReturnCorrectSize_whenJSONArrayIsValid(String inputJson, int expectedSize) {
+
+ Set actualAuthorizationDetails = AuthorizationDetailsCommonUtils
+ .fromJSONArray(inputJson, AuthorizationDetail.class, objectMapper);
+
+ assertEquals(expectedSize, actualAuthorizationDetails.size());
+ }
+
+ @Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
+ public void shouldReturnNull_whenJSONIsInvalid(String inputJson, int expectedSize) {
+
+ assertNull(AuthorizationDetailsCommonUtils.fromJSON(inputJson, AuthorizationDetail.class, objectMapper));
+ }
+
+ @Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
+ public void shouldReturnCorrectType_whenJSONIsValid(Class expectedClazz) {
+
+ final String inputJson = "{\"type\": \"" + TEST_TYPE + "\"}";
+ AuthorizationDetail actualAuthorizationDetail =
+ AuthorizationDetailsCommonUtils.fromJSON(inputJson, expectedClazz, objectMapper);
+
+ assertNotNull(actualAuthorizationDetail);
+ assertEquals(TEST_TYPE, actualAuthorizationDetail.getType());
+ }
+
+ @Test
+ public void shouldReturnCorrectJson_whenAuthorizationDetailsAreValid() {
+
+ AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ inputAuthorizationDetail.setType(TEST_TYPE);
+
+ assertTrue(AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail), objectMapper)
+ .contains(TEST_TYPE));
+ assertEquals("[]", AuthorizationDetailsCommonUtils.toJSON((Set) null, objectMapper));
+ assertEquals("[]",
+ AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail), mockObjectMapper));
+ }
+
+ @Test
+ public void shouldReturnCorrectJson_whenAuthorizationDetailIsValid() {
+
+ AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ inputAuthorizationDetail.setType(TEST_TYPE);
+
+ assertTrue(AuthorizationDetailsCommonUtils.toJSON(inputAuthorizationDetail, objectMapper).contains(TEST_TYPE));
+ assertEquals("{}", AuthorizationDetailsCommonUtils.toJSON((TestAuthorizationDetail) null, objectMapper));
+ assertEquals("{}", AuthorizationDetailsCommonUtils.toJSON(new TestAuthorizationDetail(), mockObjectMapper));
+ }
+
+ @Test
+ public void shouldReturnMap_whenAuthorizationDetailIsValid() {
+
+ AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ inputAuthorizationDetail.setType(TEST_TYPE);
+ Map actualMap = AuthorizationDetailsCommonUtils.toMap(inputAuthorizationDetail, objectMapper);
+
+ assertTrue(actualMap.containsKey("type"));
+ assertEquals(TEST_TYPE, String.valueOf(actualMap.get("type")));
+ assertEquals(1, actualMap.keySet().size());
+
+ assertFalse(AuthorizationDetailsCommonUtils.toMap(null, objectMapper).containsKey(TEST_TYPE));
+ }
+
+ private static class TestAuthorizationDetail extends AuthorizationDetail {
+ // Test authorization detail class which extends AuthorizationDetail
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java
new file mode 100644
index 0000000000..9440b079be
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java
@@ -0,0 +1,46 @@
+package org.wso2.carbon.identity.oauth2.rar.util;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.lang.StringUtils;
+
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * DB Utils.
+ */
+public class DAOUtils {
+
+ private static final Map dataSourceMap = new HashMap<>();
+
+ public static void initializeDataSource(String databaseName, String scriptPath) throws SQLException {
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName("org.h2.Driver");
+ dataSource.setUsername("username");
+ dataSource.setPassword("password");
+ dataSource.setUrl("jdbc:h2:mem:" + databaseName);
+
+ try (Connection connection = dataSource.getConnection()) {
+ connection.createStatement().executeUpdate("RUNSCRIPT FROM '" + scriptPath + "'");
+ }
+ dataSourceMap.put(databaseName, dataSource);
+ }
+
+ public static Connection getConnection(String database) throws SQLException {
+ if (dataSourceMap.get(database) != null) {
+ return dataSourceMap.get(database).getConnection();
+ }
+ throw new RuntimeException("Invalid datasource.");
+ }
+
+ public static String getFilePath(String fileName) {
+ if (StringUtils.isNotBlank(fileName)) {
+ return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbScripts", fileName)
+ .toString();
+ }
+ return null;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
new file mode 100644
index 0000000000..65c28adf66
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
@@ -0,0 +1,29 @@
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES(
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ TYPE VARCHAR(255) NOT NULL,
+ CURSOR_KEY INTEGER DEFAULT 1,
+ NAME VARCHAR(255),
+ DESCRIPTION VARCHAR (255),
+ JSON_SCHEMA JSON NOT NULL,
+ TENANT_ID INTEGER DEFAULT -1
+);
+
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ CONSENT_ID VARCHAR(255) NOT NULL,
+ TYPE_ID INTEGER NOT NULL,
+ AUTHORIZATION_DETAILS JSON NOT NULL,
+ CONSENT BOOLEAN NOT NULL DEFAULT 1,
+ TENANT_ID INTEGER NOT NULL DEFAULT -1
+);
+
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ TYPE_ID INTEGER NOT NULL,
+ AUTHORIZATION_DETAILS JSON NOT NULL,
+ TOKEN_ID VARCHAR (255),
+ TENANT_ID INTEGER DEFAULT -1
+);
+
+INSERT INTO IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES (TYPE, NAME, DESCRIPTION, JSON_SCHEMA, TENANT_ID)
+VALUES ('test_type_v1', 'Test Type', 'Test Type V1', '{}', 1234);
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
new file mode 100644
index 0000000000..f2065912fc
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
From 3031c3268d63ab5457a7ba637653e571db010dc2 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Tue, 3 Sep 2024 15:54:49 +0530
Subject: [PATCH 04/28] Add unit tests
---
.../dao/AuthorizationDetailsDAOImplTest.java | 25 +-
.../AuthorizationDetailsCommonUtilsTest.java | 2 +-
.../oauth2/rar/util/TestConstants.java | 17 +
.../util/{DAOUtils.java => TestDAOUtils.java} | 4 +-
.../authz/AuthorizationHandlerManager.java | 24 +-
.../token/IntrospectionRARDataProvider.java | 15 +-
.../rar/util/AuthorizationDetailsUtils.java | 56 ++-
.../DefaultAuthorizationDetailsValidator.java | 3 +-
.../carbon/identity/oauth2/TestConstants.java | 6 +
.../rar/AuthorizationDetailsServiceTest.java | 403 ++++++++++++++++++
.../AccessTokenResponseRARHandlerTest.java | 34 ++
.../IntrospectionRARDataProviderTest.java | 111 +++++
.../JWTAccessTokenRARClaimProviderTest.java | 49 +++
.../utils/AuthorizationDetailsBaseTest.java | 140 ++++++
...aultAuthorizationDetailsValidatorTest.java | 52 +++
.../src/test/resources/testng.xml | 10 +
16 files changed, 888 insertions(+), 63 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
rename components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/{DAOUtils.java => TestDAOUtils.java} (97%)
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index c5784f9a80..e507d24f25 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -10,7 +10,7 @@
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.util.DAOUtils;
+import org.wso2.carbon.identity.oauth2.rar.util.TestDAOUtils;
import java.sql.SQLException;
import java.util.Collections;
@@ -19,22 +19,21 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_CONSENT_ID;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_DB_NAME;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TENANT_ID;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TOKEN_ID;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
public class AuthorizationDetailsDAOImplTest {
- private static final String TEST_CONSENT_ID = "52481ccd-0927-4d17-8cfc-5110fc4aa009";
- private static final String TEST_DB_NAME = "TEST_IAM_RAR_DATABASE";
- private static final int TEST_TENANT_ID = 1234;
- private static final String TEST_TOKEN_ID = "e1fea951-a3b5-4347-bd73-b18b3feecd54";
- private static final String TEST_TYPE = "test_type_v1";
-
private MockedStatic identityDatabaseUtilMock;
private AuthorizationDetailsDAO uut;
@BeforeClass
public void setUp() throws SQLException {
this.uut = new AuthorizationDetailsDAOImpl();
- DAOUtils.initializeDataSource(TEST_DB_NAME, DAOUtils.getFilePath("h2.sql"));
+ TestDAOUtils.initializeDataSource(TEST_DB_NAME, TestDAOUtils.getFilePath("h2.sql"));
this.identityDatabaseUtilMock = Mockito.mockStatic(IdentityDatabaseUtil.class);
}
@@ -50,7 +49,7 @@ public void tearDown() throws SQLException {
public void setUpBeforeMethod() throws SQLException {
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
}
@Test(priority = 0)
@@ -60,7 +59,7 @@ public void testAddUserConsentedAuthorizationDetails() throws SQLException {
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
testAuthorizationDetail.setType(TEST_TYPE);
@@ -93,7 +92,7 @@ public void testDeleteUserConsentedAuthorizationDetails() throws SQLException {
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
}
@@ -104,7 +103,7 @@ public void testAddAccessTokenAuthorizationDetails() throws SQLException {
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
testAuthorizationDetail.setType(TEST_TYPE);
@@ -136,7 +135,7 @@ public void testDeleteAccessTokenAuthorizationDetails() throws SQLException {
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(DAOUtils.getConnection(TEST_DB_NAME));
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
index e5c35d5d05..ccf61b834c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
/**
* Test class for {@link AuthorizationDetailsCommonUtils}.
@@ -28,7 +29,6 @@ public class AuthorizationDetailsCommonUtilsTest {
private ObjectMapper objectMapper;
private ObjectMapper mockObjectMapper;
- private static final String TEST_TYPE = "test_type_v1";
@BeforeClass
public void setUp() throws JsonProcessingException {
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
new file mode 100644
index 0000000000..b8e276837a
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
@@ -0,0 +1,17 @@
+package org.wso2.carbon.identity.oauth2.rar.util;
+
+/**
+ * Rich Authorization Requests Test Constants.
+ */
+public class TestConstants {
+
+ private TestConstants() {
+ // Private constructor to prevent instantiation
+ }
+
+ public static final String TEST_CONSENT_ID = "52481ccd-0927-4d17-8cfc-5110fc4aa009";
+ public static final String TEST_DB_NAME = "TEST_IAM_RAR_DATABASE";
+ public static final int TEST_TENANT_ID = 1234;
+ public static final String TEST_TOKEN_ID = "e1fea951-a3b5-4347-bd73-b18b3feecd54";
+ public static final String TEST_TYPE = "test_type_v1";
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
similarity index 97%
rename from components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
index 9440b079be..8c354b8217 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/DAOUtils.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
@@ -10,9 +10,9 @@
import java.util.Map;
/**
- * DB Utils.
+ * Test DB Utils.
*/
-public class DAOUtils {
+public class TestDAOUtils {
private static final Map dataSourceMap = new HashMap<>();
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
index 705f4a58a4..a9f1307804 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
@@ -40,9 +40,7 @@
import org.wso2.carbon.identity.oauth2.authz.handlers.ResponseTypeHandler;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO;
-import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
-import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.util.AuthzUtil;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
@@ -258,7 +256,7 @@ public OAuth2AuthorizeRespDTO handleAuthorization(OAuthAuthzReqMessageContext au
// set the authorization request context to be used by downstream handlers. This is introduced as a fix for
// IDENTITY-4111
OAuth2Util.setAuthzRequestContext(authzReqMsgCtx);
- this.setUserConsentedAuthorizationDetails(authzReqMsgCtx);
+ AuthorizationDetailsUtils.setRARPropertiesToAuthzRequestContext(authzReqMsgCtx);
authorizeRespDTO = authzHandler.issue(authzReqMsgCtx);
} finally {
// clears authorization request context
@@ -680,7 +678,7 @@ private boolean isInvalidResponseType(OAuth2AuthorizeReqDTO authzReqDTO, OAuth2A
return false;
}
- public OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
+ private OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
InvalidOAuthClientException {
OAuthAppDO oAuthAppDO = AppInfoCache.getInstance().getValueFromCache(authzReqDTO.getConsumerKey());
if (oAuthAppDO != null) {
@@ -727,22 +725,4 @@ public OAuthErrorDTO handleAuthenticationFailure(OAuth2Parameters oAuth2Paramete
ResponseTypeHandler responseTypeHandler = responseHandlers.get(oAuth2Parameters.getResponseType());
return responseTypeHandler.handleAuthenticationFailure(oAuth2Parameters);
}
-
- private void setUserConsentedAuthorizationDetails(final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
- throws IdentityOAuth2Exception {
-
- OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO = oAuthAuthzReqMessageContext.getAuthorizationReqDTO();
- if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2AuthorizeReqDTO)) {
- return;
- }
-
- final AuthorizationDetails authorizationDetails = OAuth2ServiceComponentHolder.getInstance()
- .getAuthorizationDetailsService()
- .getUserConsentedAuthorizationDetails(
- oAuth2AuthorizeReqDTO.getUser(),
- oAuth2AuthorizeReqDTO.getConsumerKey(),
- IdentityTenantUtil.getTenantId(oAuth2AuthorizeReqDTO.getTenantDomain())
- );
- oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
- }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
index e2399aff36..e6d3f97244 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
@@ -11,6 +11,7 @@
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
@@ -34,8 +35,12 @@ public class IntrospectionRARDataProvider implements IntrospectionDataProvider {
public IntrospectionRARDataProvider() {
- this.authorizationDetailsValidator =
- OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsValidator();
+ this(OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsValidator());
+ }
+
+ public IntrospectionRARDataProvider(final AuthorizationDetailsValidator authorizationDetailsValidator) {
+
+ this.authorizationDetailsValidator = authorizationDetailsValidator;
}
/**
@@ -56,9 +61,13 @@ public Map getIntrospectionData(
generateOAuth2TokenValidationMessageContext(tokenValidationRequestDTO, introspectionResponseDTO);
if (Objects.nonNull(tokenValidationMessageContext)) {
+
final AuthorizationDetails validatedAuthorizationDetails = this.authorizationDetailsValidator
.getValidatedAuthorizationDetails(tokenValidationMessageContext);
- introspectionData.put(AUTHORIZATION_DETAILS, validatedAuthorizationDetails.toSet());
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(validatedAuthorizationDetails)) {
+
+ introspectionData.put(AUTHORIZATION_DETAILS, validatedAuthorizationDetails.toSet());
+ }
}
return introspectionData;
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index eaf24b4c39..ade73ab635 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -7,9 +7,11 @@
import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthTokenRequest;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
@@ -20,7 +22,6 @@
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
-import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@@ -289,8 +290,8 @@ public static AuthorizationDetails generateAndAssignUniqueIDs(final String autho
* @param authorizationDetails The AuthorizationDetails object containing a set of AuthorizationDetail objects.
* @return The AuthorizationDetails object with unique IDs assigned to each AuthorizationDetail.
*/
- public static AuthorizationDetails assignUniqueIDsToAuthorizationDetails(final AuthorizationDetails
- authorizationDetails) {
+ public static AuthorizationDetails assignUniqueIDsToAuthorizationDetails(
+ final AuthorizationDetails authorizationDetails) {
authorizationDetails.stream().filter(Objects::nonNull)
.forEach(authorizationDetail -> authorizationDetail.setId(UUID.randomUUID().toString()));
@@ -305,15 +306,11 @@ public static AuthorizationDetails assignUniqueIDsToAuthorizationDetails(final A
*/
public static String getUrlEncodedAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
- try {
- if (log.isDebugEnabled()) {
- log.debug("Starts URL encoding authorization details: " + authorizationDetails.toJsonString());
- }
- if (isRichAuthorizationRequest(authorizationDetails)) {
- return URLEncoder.encode(authorizationDetails.toJsonString(), StandardCharsets.UTF_8.toString());
- }
- } catch (UnsupportedEncodingException e) {
- log.error("Error occurred while URL encoding authorization details. Caused by, ", e);
+ if (log.isDebugEnabled()) {
+ log.debug("Starts URL encoding authorization details: " + authorizationDetails.toJsonString());
+ }
+ if (isRichAuthorizationRequest(authorizationDetails)) {
+ return URLEncoder.encode(authorizationDetails.toJsonString(), StandardCharsets.UTF_8);
}
return StringUtils.EMPTY;
}
@@ -326,16 +323,35 @@ public static String getUrlEncodedAuthorizationDetails(final AuthorizationDetail
*/
public static String getUrlDecodedAuthorizationDetails(final String encodedAuthorizationDetails) {
- try {
+ if (log.isDebugEnabled()) {
+ log.debug("Starts decoding URL encoded authorization details JSON: " + encodedAuthorizationDetails);
+ }
+ if (StringUtils.isNotEmpty(encodedAuthorizationDetails)) {
+ return URLDecoder.decode(encodedAuthorizationDetails, StandardCharsets.UTF_8);
+ }
+ return StringUtils.EMPTY;
+ }
+
+ public static void setRARPropertiesToAuthzRequestContext(
+ final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) throws IdentityOAuth2Exception {
+
+ OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO = oAuthAuthzReqMessageContext.getAuthorizationReqDTO();
+ if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2AuthorizeReqDTO)) {
if (log.isDebugEnabled()) {
- log.debug("Starts decoding URL encoded authorization details JSON: " + encodedAuthorizationDetails);
+ log.debug("Request is not a rich authorization request. " +
+ "Skips adding authorization details to OAuthAuthzReqMessageContext");
}
- if (StringUtils.isNotEmpty(encodedAuthorizationDetails)) {
- return URLDecoder.decode(encodedAuthorizationDetails, StandardCharsets.UTF_8.toString());
- }
- } catch (UnsupportedEncodingException e) {
- log.error("Error occurred while URL decoding authorization details Json. Caused by, ", e);
+ return;
}
- return StringUtils.EMPTY;
+
+ final AuthorizationDetails authorizationDetails = OAuth2ServiceComponentHolder.getInstance()
+ .getAuthorizationDetailsService()
+ .getUserConsentedAuthorizationDetails(
+ oAuth2AuthorizeReqDTO.getUser(),
+ oAuth2AuthorizeReqDTO.getConsumerKey(),
+ IdentityTenantUtil.getTenantId(oAuth2AuthorizeReqDTO.getTenantDomain())
+ );
+
+ oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
index 52fce6d3e8..3ea9e29085 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
@@ -214,8 +214,7 @@ private Set getAuthorizedAuthorizationDetails(
private boolean isSupportedAuthorizationDetailType(final String authorizationDetailType) {
- return this.authorizationDetailsProviderFactory
- .isSupportedAuthorizationDetailsType(authorizationDetailType);
+ return this.authorizationDetailsProviderFactory.isSupportedAuthorizationDetailsType(authorizationDetailType);
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/TestConstants.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/TestConstants.java
index b07c1e8dd2..add9c80106 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/TestConstants.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/TestConstants.java
@@ -88,4 +88,10 @@ public class TestConstants {
public static final String FAPI_SIGNATURE_ALG_CONFIGURATION = "OAuth.OpenIDConnect.FAPI." +
"AllowedSignatureAlgorithms.AllowedSignatureAlgorithm";
+
+ // Rich Authorization Requests
+ public static final String TEST_CONSENT_ID = "52481ccd-0927-4d17-8cfc-5110fc4aa009";
+ public static final String TEST_USER_ID = "c2179b58-b048-49d1-acb4-45b672d6fe5f";
+ public static final String TEST_APP_ID = "a49257ea-3d5d-4558-b0c5-f9b3b0ca2fb0";
+ public static final String TEST_TYPE = "test_type_v1";
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
new file mode 100644
index 0000000000..4c72935ff5
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -0,0 +1,403 @@
+package org.wso2.carbon.identity.oauth2.rar;
+
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.application.common.model.ServiceProvider;
+import org.wso2.carbon.identity.common.testng.WithCarbonHome;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.dao.AuthorizationDetailsDAO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toSet;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.wso2.carbon.identity.oauth2.TestConstants.ACESS_TOKEN_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.CLIENT_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_DOMAIN;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_APP_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_CONSENT_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_TYPE;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_USER_ID;
+
+/**
+ * Test class for {@link AuthorizationDetailsService}.
+ */
+@WithCarbonHome
+public class AuthorizationDetailsServiceTest extends AuthorizationDetailsBaseTest {
+
+ private AuthorizationDetailsDAO authorizationDetailsDAOMock;
+ private MockedStatic oAuth2UtilMock;
+
+ private AuthorizationDetailsService uut;
+
+ @BeforeClass
+ public void setUp() throws SQLException {
+
+ this.oAuth2UtilMock = Mockito.mockStatic(OAuth2Util.class);
+ this.oAuth2UtilMock.when(() -> OAuth2Util.getTenantId(TENANT_DOMAIN)).thenReturn(TENANT_ID);
+
+ ServiceProvider serviceProvider = new ServiceProvider();
+ serviceProvider.setApplicationResourceId(TEST_APP_ID);
+ this.oAuth2UtilMock.when(() -> OAuth2Util.getServiceProvider(CLIENT_ID)).thenReturn(serviceProvider);
+ }
+
+ @AfterClass
+ public void tearDown() {
+
+ if (this.oAuth2UtilMock != null && !this.oAuth2UtilMock.isClosed()) {
+ this.oAuth2UtilMock.close();
+ }
+ }
+
+ @BeforeMethod()
+ public void setUpMethod() throws SQLException {
+
+ this.authorizationDetailsDAOMock = Mockito.mock(AuthorizationDetailsDAO.class);
+ when(this.authorizationDetailsDAOMock.getConsentIdByUserIdAndAppId(TEST_USER_ID, TEST_APP_ID, TENANT_ID))
+ .thenReturn(TEST_CONSENT_ID);
+
+ when(this.authorizationDetailsDAOMock.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID))
+ .thenReturn(Collections.singleton(new AuthorizationDetailsConsentDTO(TEST_CONSENT_ID,
+ this.authorizationDetail, true, TENANT_ID)));
+
+ when(this.authorizationDetailsDAOMock.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID))
+ .thenReturn(Collections.singleton(new AuthorizationDetailsTokenDTO(ACESS_TOKEN_ID,
+ this.authorizationDetail, TENANT_ID)));
+
+ uut = new AuthorizationDetailsService(this.providerFactoryMock, this.authorizationDetailsDAOMock);
+ }
+
+ @BeforeMethod(onlyForGroups = {"error-flow-tests"}, dependsOnMethods = {"setUpMethod"})
+ public void setUpErrorMethod() throws SQLException {
+
+ when(this.authorizationDetailsDAOMock.addUserConsentedAuthorizationDetails(anyList()))
+ .thenThrow(SQLException.class);
+ when(this.authorizationDetailsDAOMock.deleteUserConsentedAuthorizationDetails(anyString(), anyInt()))
+ .thenThrow(SQLException.class);
+ when(this.authorizationDetailsDAOMock.getUserConsentedAuthorizationDetails(anyString(), anyInt()))
+ .thenThrow(SQLException.class);
+ when(this.authorizationDetailsDAOMock.getAccessTokenAuthorizationDetails(anyString(), anyInt()))
+ .thenThrow(SQLException.class);
+ when(this.authorizationDetailsDAOMock.addAccessTokenAuthorizationDetails(anyList()))
+ .thenThrow(SQLException.class);
+ when(this.authorizationDetailsDAOMock.deleteAccessTokenAuthorizationDetails(anyString(), anyInt()))
+ .thenThrow(SQLException.class);
+
+ uut = new AuthorizationDetailsService(this.providerFactoryMock, this.authorizationDetailsDAOMock);
+ }
+
+ @Test
+ public void shouldNotAddUserConsentedAuthorizationDetails_ifNotRichAuthorizationRequest()
+ throws OAuthSystemException, SQLException {
+
+ uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ new OAuth2Parameters(), authorizationDetails);
+
+ verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldNotAddUserConsentedAuthorizationDetails_whenConsentIsNotFound()
+ throws OAuthSystemException, SQLException {
+
+ final OAuth2Parameters oAuth2Parameters = new OAuth2Parameters();
+ oAuth2Parameters.setAuthorizationDetails(authorizationDetails);
+
+ uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ oAuth2Parameters, authorizationDetails);
+
+ verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldAddUserConsentedAuthorizationDetails_ifRichAuthorizationRequest()
+ throws OAuthSystemException, SQLException {
+
+ uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ oAuth2Parameters, authorizationDetails);
+
+ verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldNotDeleteUserConsentedAuthorizationDetails_ifNotRichAuthorizationRequest()
+ throws OAuthSystemException, SQLException {
+
+ uut.deleteUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, new OAuth2Parameters());
+
+ verify(authorizationDetailsDAOMock, times(0)).deleteUserConsentedAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldNotDeleteUserConsentedAuthorizationDetails_whenConsentIsNotFound()
+ throws OAuthSystemException, SQLException {
+
+ final OAuth2Parameters oAuth2Parameters = new OAuth2Parameters();
+ oAuth2Parameters.setAuthorizationDetails(authorizationDetails);
+
+ uut.deleteUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, oAuth2Parameters);
+
+ verify(authorizationDetailsDAOMock, times(0)).deleteUserConsentedAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldDeleteUserConsentedAuthorizationDetails_ifRichAuthorizationRequest()
+ throws OAuthSystemException, SQLException {
+
+ uut.deleteUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, oAuth2Parameters);
+
+ verify(authorizationDetailsDAOMock, times(1)).deleteUserConsentedAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldReplaceUserConsentedAuthorizationDetails_ifRichAuthorizationRequest()
+ throws OAuthSystemException, SQLException {
+
+ uut.replaceUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ oAuth2Parameters, authorizationDetails);
+
+ verify(authorizationDetailsDAOMock, times(1))
+ .deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldReturnTrue_ifNotRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ assertTrue(uut.isUserAlreadyConsentedForAuthorizationDetails(authenticatedUser, new OAuth2Parameters()));
+ }
+
+ @Test
+ public void shouldReturnFalse_ifAuthorizationDetailsAlreadyConsented() throws IdentityOAuth2Exception {
+
+ assertFalse(uut.isUserAlreadyConsentedForAuthorizationDetails(authenticatedUser, oAuth2Parameters));
+ }
+
+ @Test
+ public void shouldReturnEmptyAuthorizationDetails_whenConsentIsInvalid() throws IdentityOAuth2Exception {
+
+ AuthenticatedUser invalidUser = new AuthenticatedUser();
+ invalidUser.setUserId("invalid-user-id");
+
+ assertTrue(uut.getUserConsentedAuthorizationDetails(invalidUser, CLIENT_ID, TENANT_ID)
+ .getDetails().isEmpty());
+ }
+
+ @Test
+ public void shouldReturnUserConsentedAuthorizationDetails_whenConsentIsValid() throws IdentityOAuth2Exception {
+
+ final AuthorizationDetails authorizationDetails =
+ uut.getUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, TENANT_ID);
+
+ assertEquals(1, authorizationDetails.getDetails().size());
+ authorizationDetails.stream().forEach(detail -> assertEquals(TEST_TYPE, detail.getType()));
+
+ final AuthorizationDetails authorizationDetails1 =
+ uut.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters);
+
+ assertEquals(1, authorizationDetails1.getDetails().size());
+ authorizationDetails1.stream().forEach(detail -> assertEquals(TEST_TYPE, detail.getType()));
+ }
+
+ @Test
+ public void shouldReturnEmptyAuthorizationDetails_whenAccessTokenIsNotFound() throws IdentityOAuth2Exception {
+
+ assertTrue(uut.getAccessTokenAuthorizationDetails("invalid-access-token", TENANT_ID)
+ .getDetails().isEmpty());
+ }
+
+ @Test
+ public void shouldReturnAccessTokenAuthorizationDetails_whenTokenIsValid() throws IdentityOAuth2Exception {
+
+ AuthorizationDetails authorizationDetails = uut.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+
+ assertEquals(1, authorizationDetails.getDetails().size());
+ authorizationDetails.stream().forEach(ad -> assertEquals(TEST_TYPE, ad.getType()));
+ }
+
+ @Test
+ public void shouldNotAddAccessTokenAuthorizationDetails_ifNotRichAuthorizationRequest()
+ throws SQLException, IdentityOAuth2Exception {
+
+ uut.storeAccessTokenAuthorizationDetails(accessTokenDO, new OAuthAuthzReqMessageContext(null));
+
+ verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldAddAccessTokenAuthorizationDetails_ifRichAuthorizationRequest()
+ throws SQLException, IdentityOAuth2Exception {
+
+ OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext = new OAuthAuthzReqMessageContext(null);
+ oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
+
+ uut.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthAuthzReqMessageContext);
+
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldNotReplaceAccessTokenAuthorizationDetails_ifNotRichAuthorizationRequest()
+ throws SQLException, IdentityOAuth2Exception {
+
+ uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, accessTokenDO,
+ new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO()));
+
+ verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldNotDeleteAccessTokenAuthorizationDetails_whenOldAccessTokenIsMissing()
+ throws SQLException, IdentityOAuth2Exception {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+ messageContext.setAuthorizationDetails(authorizationDetails);
+
+ uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, null, messageContext);
+
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldReplaceAccessTokenAuthorizationDetails_whenOldAccessTokenIsPresent()
+ throws SQLException, IdentityOAuth2Exception {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+ messageContext.setAuthorizationDetails(authorizationDetails);
+
+ uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, accessTokenDO, messageContext);
+
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldReplaceAccessTokenAuthorizationDetails_ifRichAuthorizationRequest()
+ throws SQLException, IdentityOAuth2Exception {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+ messageContext.setAuthorizationDetails(authorizationDetails);
+
+ final String oldAccessTokenId = "b8488717-267c-4f45-b039-f31a8efe7cac";
+ uut.replaceAccessTokenAuthorizationDetails(oldAccessTokenId, accessTokenDO, messageContext);
+
+ verify(authorizationDetailsDAOMock, times(1))
+ .deleteAccessTokenAuthorizationDetails(oldAccessTokenId, TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ }
+
+ @Test
+ public void shouldDeleteAccessTokenAuthorizationDetails_ifAccessTokenIsValid()
+ throws SQLException, IdentityOAuth2Exception {
+
+ uut.deleteAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+
+ verify(authorizationDetailsDAOMock, times(1)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test
+ public void shouldReturnEmptyAuthorizationDetails_ifNotRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ assertTrue(uut.getConsentRequiredAuthorizationDetails(authenticatedUser, new OAuth2Parameters())
+ .getDetails().isEmpty());
+ }
+
+ @Test
+ public void shouldReturnEmptyAuthorizationDetails_ifProcessorIsMissing() throws IdentityOAuth2Exception {
+
+ assertTrue(uut.getConsentRequiredAuthorizationDetails(authenticatedUser, new OAuth2Parameters())
+ .getDetails().isEmpty());
+ }
+
+ @Test
+ public void shouldReturnConsentRequiredAuthorizationDetails() throws IdentityOAuth2Exception {
+
+ final String testTypeV2 = "test_type_v2";
+ AuthorizationDetail authorizationDetail = new AuthorizationDetail();
+ authorizationDetail.setType(testTypeV2);
+
+ Set detailSet =
+ Stream.of(authorizationDetails.getDetails(), Collections.singleton(authorizationDetail))
+ .flatMap(Set::stream)
+ .collect(toSet());
+
+ oAuth2Parameters.setAuthorizationDetails(new AuthorizationDetails(detailSet));
+
+ uut.getConsentRequiredAuthorizationDetails(authenticatedUser, oAuth2Parameters)
+ .stream()
+ .forEach(ad -> assertEquals(testTypeV2, ad.getType()));
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {OAuthSystemException.class})
+ public void shouldThrowOAuthSystemException_onUserConsentAuthorizationDetailsInsertionFailure()
+ throws OAuthSystemException {
+
+ uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ oAuth2Parameters, authorizationDetails);
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {OAuthSystemException.class})
+ public void shouldThrowOAuthSystemException_onUserConsentAuthorizationDetailsDeletionFailure()
+ throws OAuthSystemException {
+
+ uut.deleteUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, oAuth2Parameters);
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {IdentityOAuth2Exception.class})
+ public void shouldThrowIdentityOAuth2Exception_onUserConsentAuthorizationDetailsRetrievalFailure()
+ throws IdentityOAuth2Exception {
+
+ uut.getUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, TENANT_ID);
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {IdentityOAuth2Exception.class})
+ public void shouldThrowIdentityOAuth2Exception_onAccessTokenAuthorizationDetailsRetrievalFailure()
+ throws IdentityOAuth2Exception {
+
+ uut.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {IdentityOAuth2Exception.class})
+ public void shouldThrowIdentityOAuth2Exception_onAccessTokenAuthorizationDetailsInsertionFailure()
+ throws IdentityOAuth2Exception {
+
+ uut.storeAccessTokenAuthorizationDetails(accessTokenDO, authorizationDetails);
+ }
+
+ @Test(groups = {"error-flow-tests"}, expectedExceptions = {IdentityOAuth2Exception.class})
+ public void shouldThrowIdentityOAuth2Exception_onAccessTokenAuthorizationDetailsDeletionFailure()
+ throws IdentityOAuth2Exception {
+
+ uut.deleteAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
new file mode 100644
index 0000000000..26dae1ca6c
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
@@ -0,0 +1,34 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+
+/**
+ * Test class for {@link AccessTokenResponseRARHandler}.
+ */
+public class AccessTokenResponseRARHandlerTest extends AuthorizationDetailsBaseTest {
+
+ private AccessTokenResponseRARHandler uut;
+
+ @BeforeClass
+ public void setUp() {
+ this.uut = new AccessTokenResponseRARHandler();
+ }
+
+ @Test
+ public void shouldReturnAuthorizationDetails_ifRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ assertAuthorizationDetailsPresent(uut.getAdditionalTokenResponseAttributes(tokenReqMessageContext));
+ }
+
+ @Test
+ public void shouldReturnEmpty_ifNotRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+ assertAuthorizationDetailsMissing(uut.getAdditionalTokenResponseAttributes(messageContext));
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
new file mode 100644
index 0000000000..c5bcda4332
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
@@ -0,0 +1,111 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.common.testng.WithCarbonHome;
+import org.wso2.carbon.identity.oauth.tokenprocessor.TokenProvider;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
+import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test class for {@link IntrospectionRARDataProvider}.
+ */
+@WithCarbonHome
+public class IntrospectionRARDataProviderTest extends AuthorizationDetailsBaseTest {
+
+ private AuthorizationDetailsValidator validatorMock;
+ private OAuth2ServiceComponentHolder componentHolderMock;
+
+ private IntrospectionRARDataProvider uut;
+
+ @BeforeClass
+ public void setUpClass() throws IdentityOAuth2Exception {
+
+ this.validatorMock = Mockito.mock(AuthorizationDetailsValidator.class);
+ when(validatorMock.getValidatedAuthorizationDetails(any(OAuth2TokenValidationMessageContext.class)))
+ .thenReturn(authorizationDetails);
+
+ this.uut = new IntrospectionRARDataProvider(validatorMock);
+
+ AccessTokenDO accessTokenDO = new AccessTokenDO();
+
+ TokenProvider tokenProviderMock = Mockito.mock(TokenProvider.class);
+ when(tokenProviderMock.getVerifiedAccessToken(anyString(), anyBoolean())).thenReturn(accessTokenDO);
+
+ this.componentHolderMock = Mockito.mock(OAuth2ServiceComponentHolder.class);
+ when(componentHolderMock.getTokenProvider()).thenReturn(tokenProviderMock);
+ }
+
+ @Test(priority = 1)
+ public void shouldNotReturnAuthorizationDetails_ifNotRichAuthorizationRequest()
+ throws IdentityOAuth2Exception {
+
+ when(validatorMock.getValidatedAuthorizationDetails(any(OAuth2TokenValidationMessageContext.class)))
+ .thenReturn(new AuthorizationDetails());
+
+ try (MockedStatic oAuth2UtilMock = Mockito.mockStatic(OAuth2Util.class);
+ MockedStatic componentHolderMock =
+ Mockito.mockStatic(OAuth2ServiceComponentHolder.class)) {
+
+ oAuth2UtilMock.when(() -> OAuth2Util.buildScopeArray(any())).thenReturn(new String[0]);
+ componentHolderMock.when(OAuth2ServiceComponentHolder::getInstance)
+ .thenReturn(this.componentHolderMock);
+
+ assertAuthorizationDetailsMissing(uut.getIntrospectionData(tokenValidationRequestDTO,
+ introspectionResponseDTO));
+ }
+ }
+
+ @Test
+ public void shouldReturnAuthorizationDetails_ifRichAuthorizationRequestAndContextIsMissing()
+ throws IdentityOAuth2Exception {
+
+ try (MockedStatic oAuth2UtilMock = Mockito.mockStatic(OAuth2Util.class);
+ MockedStatic componentHolderMock =
+ Mockito.mockStatic(OAuth2ServiceComponentHolder.class)) {
+
+ oAuth2UtilMock.when(() -> OAuth2Util.buildScopeArray(any())).thenReturn(new String[0]);
+ componentHolderMock.when(OAuth2ServiceComponentHolder::getInstance)
+ .thenReturn(this.componentHolderMock);
+
+ assertAuthorizationDetailsPresent(uut.getIntrospectionData(tokenValidationRequestDTO,
+ introspectionResponseDTO));
+ }
+ }
+
+ @Test
+ public void shouldReturnAuthorizationDetails_ifRichAuthorizationRequestAndContextIsPresent()
+ throws IdentityOAuth2Exception {
+
+ OAuth2TokenValidationMessageContext context = new OAuth2TokenValidationMessageContext(tokenValidationRequestDTO,
+ new OAuth2TokenValidationResponseDTO());
+
+ Map properties = new HashMap<>();
+ properties.put(OAuth2Util.OAUTH2_VALIDATION_MESSAGE_CONTEXT, context);
+ this.introspectionResponseDTO.setProperties(properties);
+
+ try (MockedStatic oAuth2UtilMock = Mockito.mockStatic(OAuth2Util.class)) {
+
+ oAuth2UtilMock.when(() -> OAuth2Util.buildScopeArray(any())).thenReturn(new String[0]);
+ assertAuthorizationDetailsPresent(uut.getIntrospectionData(tokenValidationRequestDTO,
+ introspectionResponseDTO));
+ }
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
new file mode 100644
index 0000000000..7e8c99e6fc
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
@@ -0,0 +1,49 @@
+package org.wso2.carbon.identity.oauth2.rar.token;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+
+public class JWTAccessTokenRARClaimProviderTest extends AuthorizationDetailsBaseTest {
+
+ private JWTAccessTokenRARClaimProvider uut;
+
+ @BeforeClass
+ public void setUp() {
+ this.uut = new JWTAccessTokenRARClaimProvider();
+ }
+
+ @Test
+ public void shouldReturnEmptyForAuthzReq_ifNotRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ OAuthAuthzReqMessageContext messageContext = new OAuthAuthzReqMessageContext(new OAuth2AuthorizeReqDTO());
+ assertAuthorizationDetailsMissing(uut.getAdditionalClaims(messageContext));
+ }
+
+ @Test
+ public void shouldReturnEmptyForTokenReq_ifNotRichAuthorizationRequest() throws IdentityOAuth2Exception {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+
+ assertAuthorizationDetailsMissing(uut.getAdditionalClaims(messageContext));
+ }
+
+ @Test
+ public void shouldReturnAuthorizationDetailsForAuthzReq_ifNotRichAuthorizationRequest()
+ throws IdentityOAuth2Exception {
+
+ assertAuthorizationDetailsPresent(uut.getAdditionalClaims(authzReqMessageContext));
+ }
+
+ @Test
+ public void shouldReturnAuthorizationDetailsForTokenReq_ifNotRichAuthorizationRequest()
+ throws IdentityOAuth2Exception {
+
+ assertAuthorizationDetailsPresent(uut.getAdditionalClaims(tokenReqMessageContext));
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
new file mode 100644
index 0000000000..5108f23f0a
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
@@ -0,0 +1,140 @@
+package org.wso2.carbon.identity.oauth2.rar.utils;
+
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2IntrospectionResponseDTO;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.wso2.carbon.identity.oauth2.TestConstants.ACESS_TOKEN_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.CLIENT_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_DOMAIN;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_TYPE;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TEST_USER_ID;
+
+public class AuthorizationDetailsBaseTest {
+
+ protected AuthorizationDetail authorizationDetail;
+ protected AuthorizationDetails authorizationDetails;
+ protected OAuthAuthzReqMessageContext authzReqMessageContext;
+ protected OAuthTokenReqMessageContext tokenReqMessageContext;
+ protected OAuth2TokenValidationRequestDTO tokenValidationRequestDTO;
+ protected OAuth2IntrospectionResponseDTO introspectionResponseDTO;
+ protected AuthenticatedUser authenticatedUser;
+ protected OAuth2Parameters oAuth2Parameters;
+ protected AccessTokenDO accessTokenDO;
+ protected OAuth2AccessTokenReqDTO accessTokenReqDTO;
+
+ protected AuthorizationDetailsProviderFactory providerFactoryMock;
+ protected AuthorizationDetailsService serviceMock;
+
+ public AuthorizationDetailsBaseTest() {
+
+ this.authorizationDetail = new AuthorizationDetail();
+ this.authorizationDetail.setType(TEST_TYPE);
+
+ this.authorizationDetails = new AuthorizationDetails(Collections.singleton(this.authorizationDetail));
+
+ final OAuth2AuthorizeReqDTO authorizeReqDTO = new OAuth2AuthorizeReqDTO();
+ authorizeReqDTO.setConsumerKey(CLIENT_ID);
+ authorizeReqDTO.setTenantDomain(TENANT_DOMAIN);
+ authorizeReqDTO.setAuthorizationDetails(this.authorizationDetails);
+
+ this.authzReqMessageContext = new OAuthAuthzReqMessageContext(authorizeReqDTO);
+ this.authzReqMessageContext.setAuthorizationDetails(this.authorizationDetails);
+
+ this.accessTokenReqDTO = new OAuth2AccessTokenReqDTO();
+ this.accessTokenReqDTO.setAuthorizationDetails(authorizationDetails);
+
+ this.tokenReqMessageContext = new OAuthTokenReqMessageContext(this.accessTokenReqDTO);
+ this.tokenReqMessageContext.setAuthorizationDetails(this.authorizationDetails);
+
+ this.tokenValidationRequestDTO = new OAuth2TokenValidationRequestDTO();
+ OAuth2TokenValidationRequestDTO.OAuth2AccessToken accessToken =
+ this.tokenValidationRequestDTO.new OAuth2AccessToken();
+ accessToken.setIdentifier(ACESS_TOKEN_ID);
+ this.tokenValidationRequestDTO.setAccessToken(accessToken);
+
+ this.introspectionResponseDTO = new OAuth2IntrospectionResponseDTO();
+
+ this.authenticatedUser = new AuthenticatedUser();
+ this.authenticatedUser.setUserId(TEST_USER_ID);
+
+ this.oAuth2Parameters = new OAuth2Parameters();
+ this.oAuth2Parameters.setTenantDomain(TENANT_DOMAIN);
+ this.oAuth2Parameters.setAuthorizationDetails(this.authorizationDetails);
+ this.oAuth2Parameters.setClientId(CLIENT_ID);
+
+ this.accessTokenDO = new AccessTokenDO();
+ this.accessTokenDO.setTokenId(ACESS_TOKEN_ID);
+ this.accessTokenDO.setTenantID(TENANT_ID);
+
+ mockAuthorizationDetailsProviderFactory();
+ this.serviceMock = mock(AuthorizationDetailsService.class);
+ }
+
+ public static void assertAuthorizationDetailsPresent(final Map attributes) {
+
+ assertTrue(attributes.containsKey(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ assertEquals(((Set)
+ attributes.get(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS)).size(), 1);
+ }
+
+ public static void assertAuthorizationDetailsMissing(final Map attributes) {
+
+ assertFalse(attributes.containsKey(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ }
+
+ private void mockAuthorizationDetailsProviderFactory() {
+
+ this.providerFactoryMock = spy(AuthorizationDetailsProviderFactory.class);
+ try {
+ Field privateField = AuthorizationDetailsProviderFactory.class
+ .getDeclaredField("supportedAuthorizationDetailsTypes");
+ privateField.setAccessible(true);
+
+ privateField.set(this.providerFactoryMock, new HashMap() {{
+ put(TEST_TYPE, getAuthorizationDetailsProcessorMock());
+ }});
+ } catch (Exception e) {
+ // ignores the exceptions
+ }
+ }
+
+ private AuthorizationDetailsProcessor getAuthorizationDetailsProcessorMock() {
+ final AuthorizationDetailsProcessor processorMock = mock(AuthorizationDetailsProcessor.class);
+ when(processorMock.getType()).thenReturn(TEST_TYPE);
+ when(processorMock.isEqualOrSubset(any(AuthorizationDetail.class), any(AuthorizationDetails.class)))
+ .thenAnswer(invocation -> {
+ AuthorizationDetail ad = invocation.getArgument(0, AuthorizationDetail.class);
+ AuthorizationDetails ads = invocation.getArgument(1, AuthorizationDetails.class);
+
+ return ads.stream().map(AuthorizationDetail::getType).allMatch(type -> type.equals(ad.getType()));
+ });
+ return processorMock;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
new file mode 100644
index 0000000000..6b14dc1bf7
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
@@ -0,0 +1,52 @@
+package org.wso2.carbon.identity.oauth2.rar.validator;
+
+import org.apache.oltu.oauth2.common.message.types.GrantType;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.wso2.carbon.identity.oauth2.TestConstants.ACESS_TOKEN_ID;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_ID;
+
+public class DefaultAuthorizationDetailsValidatorTest extends AuthorizationDetailsBaseTest {
+
+ AuthorizationDetailsValidator uut;
+
+ @BeforeClass
+ public void setUp() throws IdentityOAuth2Exception {
+ when(serviceMock.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID))
+ .thenReturn(authorizationDetails);
+
+ this.uut = new DefaultAuthorizationDetailsValidator(providerFactoryMock, serviceMock);
+ }
+
+ @Test
+ public void shouldReturnContextAuthorizationDetails_ifGrantTypeIsAuthzCode()
+ throws IdentityOAuth2ServerException, AuthorizationDetailsProcessingException {
+
+ OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO();
+ reqDTO.setGrantType(GrantType.AUTHORIZATION_CODE.toString());
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(reqDTO);
+ messageContext.setAuthorizationDetails(authorizationDetails);
+
+ assertEquals(authorizationDetails, uut.getValidatedAuthorizationDetails(messageContext));
+ }
+
+ @Test
+ public void shouldReturnContextAuthorizationDetails_ifNoNewAuthorizationDetailsRequested()
+ throws IdentityOAuth2ServerException, AuthorizationDetailsProcessingException {
+
+ OAuthTokenReqMessageContext messageContext = new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO());
+ messageContext.setAuthorizationDetails(authorizationDetails);
+
+ assertEquals(authorizationDetails, uut.getValidatedAuthorizationDetails(messageContext));
+ }
+}
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
index 94ae480fb7..e0e1ece301 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml
+++ b/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml
@@ -122,6 +122,11 @@
+
+
+
+
+
@@ -195,6 +200,11 @@
+
+
+
+
+
From b12db7c9b5e3fe29bddf1cfb0d67e259fe52eebd Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Tue, 8 Oct 2024 15:47:40 +0530
Subject: [PATCH 05/28] Add schema validation - Add unit tests - Add
'authorization_details_types_supported' to /.well-known response
---
.../pom.xml | 4 +
.../discovery/DiscoveryConstants.java | 7 +
.../discovery/OIDProviderConfigResponse.java | 13 +
.../builders/ProviderConfigBuilder.java | 8 +
.../builders/ProviderConfigBuilderTest.java | 16 +-
.../pom.xml | 1 -
.../endpoint/authz/OAuth2AuthzEndpoint.java | 9 +-
.../oauth/endpoint/util/EndpointUtil.java | 3 +-
.../pom.xml | 15 +-
.../AuthorizationDetailsSchemaValidator.java | 207 +++++++++
.../rar/dao/AuthorizationDetailsDAO.java | 44 +-
.../rar/dao/AuthorizationDetailsDAOImpl.java | 97 +++--
.../identity/oauth2/rar/dao/SQLQueries.java | 26 +-
.../rar/dto/AuthorizationDetailsCodeDTO.java | 50 +++
.../dto/AuthorizationDetailsConsentDTO.java | 2 +-
.../rar/dto/AuthorizationDetailsDTO.java | 10 +-
.../rar/dto/AuthorizationDetailsTokenDTO.java | 2 +-
...thorizationDetailsProcessingException.java | 6 +-
.../util/AuthorizationDetailsCommonUtils.java | 35 +-
.../util/AuthorizationDetailsConstants.java | 17 +-
...thorizationDetailsSchemaValidatorTest.java | 105 +++++
.../dao/AuthorizationDetailsDAOImplTest.java | 103 ++++-
.../AuthorizationDetailsCommonUtilsTest.java | 72 +++-
.../oauth2/rar/util/TestConstants.java | 32 +-
.../oauth2/rar/util/TestDAOUtils.java | 38 ++
.../src/test/resources/dbScripts/h2.sql | 46 +-
.../src/test/resources/testng.xml | 3 +-
.../org.wso2.carbon.identity.oauth/pom.xml | 1 -
.../util/ResponseTypeHandlerUtil.java | 3 +
.../internal/OAuth2ServiceComponent.java | 70 +++
.../OAuth2ServiceComponentHolder.java | 22 +-
.../rar/AuthorizationDetailsService.java | 401 ++++++++++--------
.../core/AuthorizationDetailsProcessor.java | 4 +-
.../AuthorizationDetailsProcessorFactory.java | 158 +++++++
.../AuthorizationDetailsProviderFactory.java | 132 ------
.../model/AuthorizationDetailsContext.java | 60 ++-
.../token/IntrospectionRARDataProvider.java | 24 +-
.../rar/util/AuthorizationDetailsUtils.java | 161 ++++---
.../DefaultAuthorizationDetailsValidator.java | 303 +++++++++----
.../AbstractAuthorizationGrantHandler.java | 33 +-
.../rar/AuthorizationDetailsServiceTest.java | 56 ++-
.../IntrospectionRARDataProviderTest.java | 5 +-
.../utils/AuthorizationDetailsBaseTest.java | 17 +-
...aultAuthorizationDetailsValidatorTest.java | 2 +-
pom.xml | 8 +
45 files changed, 1776 insertions(+), 655 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsCodeDTO.java
rename components/{org.wso2.carbon.identity.oauth => org.wso2.carbon.identity.oauth.rar}/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java (86%)
create mode 100644 components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
delete mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index cdfa432d5c..4f832e3978 100644
--- a/components/org.wso2.carbon.identity.discovery/pom.xml
+++ b/components/org.wso2.carbon.identity.discovery/pom.xml
@@ -52,6 +52,10 @@
org.wso2.carbon.identity.framework
org.wso2.carbon.identity.claim.metadata.mgt
+
+ org.wso2.carbon.identity.inbound.auth.oauth2
+ org.wso2.carbon.identity.oauth.rar
+
org.testng
diff --git a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/DiscoveryConstants.java b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/DiscoveryConstants.java
index a77e6a151f..76a6c551c2 100644
--- a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/DiscoveryConstants.java
+++ b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/DiscoveryConstants.java
@@ -377,4 +377,11 @@ public class DiscoveryConstants {
* Authorization Server.
*/
public static final String MTLS_ENDPOINT_ALIASES = "mtls_endpoint_aliases";
+
+ /**
+ * authorization_details_types_supported.
+ * OPTIONAL. JSON array containing the authorization details types the AS supports.
+ * @see rfc9396
+ */
+ public static final String AUTHORIZATION_DETAILS_TYPES_SUPPORTED = "authorization_details_types_supported";
}
diff --git a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/OIDProviderConfigResponse.java b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/OIDProviderConfigResponse.java
index d249651a23..78020c06d4 100644
--- a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/OIDProviderConfigResponse.java
+++ b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/OIDProviderConfigResponse.java
@@ -85,6 +85,7 @@ public class OIDProviderConfigResponse {
private Boolean tlsClientCertificateBoundAccessTokens;
private String mtlsTokenEndpoint;
private String mtlsPushedAuthorizationRequestEndpoint;
+ private String[] authorizationDetailsTypesSupported;
private static final String MUTUAL_TLS_ALIASES_ENABLED = "OAuth.MutualTLSAliases.Enabled";
@@ -530,6 +531,16 @@ public void setMtlsPushedAuthorizationRequestEndpoint(String mtlsPushedAuthoriza
this.mtlsPushedAuthorizationRequestEndpoint = mtlsPushedAuthorizationRequestEndpoint;
}
+ public String[] getAuthorizationDetailsTypesSupported() {
+
+ return this.authorizationDetailsTypesSupported;
+ }
+
+ public void setAuthorizationDetailsTypesSupported(String[] authorizationDetailsTypesSupported) {
+
+ this.authorizationDetailsTypesSupported = authorizationDetailsTypesSupported;
+ }
+
public Map getConfigMap() {
Map configMap = new HashMap();
configMap.put(DiscoveryConstants.ISSUER.toLowerCase(), this.issuer);
@@ -604,6 +615,8 @@ public Map getConfigMap() {
this.mtlsPushedAuthorizationRequestEndpoint);
configMap.put(DiscoveryConstants.MTLS_ENDPOINT_ALIASES, mtlsAliases);
}
+ configMap.put(DiscoveryConstants.AUTHORIZATION_DETAILS_TYPES_SUPPORTED,
+ this.authorizationDetailsTypesSupported);
return configMap;
}
}
diff --git a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
index 5da33e3c60..76c4e3ef40 100644
--- a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
+++ b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
@@ -32,6 +32,7 @@
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.OAuth2Constants;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import java.net.URISyntaxException;
@@ -150,6 +151,13 @@ public OIDProviderConfigResponse buildOIDProviderConfig(OIDProviderRequest reque
.contains(OAuth2Constants.TokenBinderType.CERTIFICATE_BASED_TOKEN_BINDER));
providerConfig.setMtlsTokenEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSTokenEPUrl());
providerConfig.setMtlsPushedAuthorizationRequestEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSParEPUrl());
+
+ final Set supportedTypes = AuthorizationDetailsProcessorFactory.getInstance()
+ .getSupportedAuthorizationDetailTypes();
+ if (supportedTypes != null && !supportedTypes.isEmpty()) {
+ final int size = supportedTypes.size();
+ providerConfig.setAuthorizationDetailsTypesSupported(supportedTypes.toArray(new String[size]));
+ }
return providerConfig;
}
}
diff --git a/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java b/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
index 0f25922434..c4aa460249 100644
--- a/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
+++ b/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
@@ -37,10 +37,12 @@
import org.wso2.carbon.identity.discovery.internal.OIDCDiscoveryDataHolder;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import static org.mockito.ArgumentMatchers.anyString;
@@ -67,6 +69,9 @@ public class ProviderConfigBuilderTest {
@Mock
private OIDProviderRequest mockOidProviderRequest;
+//
+// @Mock
+// private AuthorizationDetailsProcessorFactory mockAuthorizationDetailsProcessorFactory;
@BeforeMethod
public void setUp() throws Exception {
@@ -84,7 +89,9 @@ public void testBuildOIDProviderConfig() throws Exception {
OAuthServerConfiguration mockOAuthServerConfiguration = mock(OAuthServerConfiguration.class);
oAuthServerConfiguration.when(
OAuthServerConfiguration::getInstance).thenReturn(mockOAuthServerConfiguration);
- try (MockedStatic oAuth2Util = mockStatic(OAuth2Util.class);) {
+ try (MockedStatic oAuth2Util = mockStatic(OAuth2Util.class);
+ MockedStatic factoryMock =
+ mockStatic(AuthorizationDetailsProcessorFactory.class)) {
OIDCDiscoveryDataHolder mockOidcDiscoveryDataHolder = spy(new OIDCDiscoveryDataHolder());
mockOidcDiscoveryDataHolder.setClaimManagementService(mockClaimMetadataManagementService);
@@ -107,6 +114,13 @@ public void testBuildOIDProviderConfig() throws Exception {
.thenReturn(JWSAlgorithm.RS256);
when(mockOidProviderRequest.getTenantDomain()).thenReturn(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
+
+ AuthorizationDetailsProcessorFactory processorFactoryMock =
+ spy(AuthorizationDetailsProcessorFactory.class);
+ when(processorFactoryMock.getSupportedAuthorizationDetailTypes()).thenReturn(new HashSet() {{
+ add("test_type");
+ }});
+ factoryMock.when(AuthorizationDetailsProcessorFactory::getInstance).thenReturn(processorFactoryMock);
assertNotNull(providerConfigBuilder.buildOIDProviderConfig(mockOidProviderRequest));
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
index 37709e48b2..801e33d460 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
@@ -179,7 +179,6 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.oauth.rar
- provided
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
index 6c3a897d52..6ac40579b5 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
@@ -2608,8 +2608,7 @@ private String populateOauthParameters(OAuth2Parameters params, OAuthMessage oAu
final String authorizationDetailsJson = oauthRequest
.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS);
- params.setAuthorizationDetails(AuthorizationDetailsUtils
- .generateAndAssignUniqueIDs(authorizationDetailsJson));
+ params.setAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
}
handleMaxAgeParameter(oauthRequest, params);
@@ -4849,10 +4848,12 @@ private void validateAuthorizationDetailsBeforeConsent(final OAuthMessage oAuthM
.getValidatedAuthorizationDetails(oAuthAuthzReqMessageContext);
// update oAuth2Parameters with validated authorization details
- oAuth2Parameters.setAuthorizationDetails(validatedAuthorizationDetails);
+ oAuth2Parameters.setAuthorizationDetails(AuthorizationDetailsUtils
+ .assignUniqueIDsToAuthorizationDetails(validatedAuthorizationDetails));
// Update the authorization message context with validated authorization details
- oAuthAuthzReqMessageContext.setAuthorizationDetails(validatedAuthorizationDetails);
+ oAuthAuthzReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
+ .assignUniqueIDsToAuthorizationDetails(validatedAuthorizationDetails));
oAuthMessage.getSessionDataCacheEntry().setAuthzReqMsgCtx(oAuthAuthzReqMessageContext);
if (LoggerUtils.isDiagnosticLogsEnabled()) {
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
index d5ab7bb26e..6d74b5ce8c 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtil.java
@@ -1102,7 +1102,8 @@ public static void storeOAuthScopeConsent(AuthenticatedUser user, OAuth2Paramete
}
try {
Set userApprovedScopesSet = params.getConsentRequiredScopes();
- if (CollectionUtils.isNotEmpty(userApprovedScopesSet)) {
+ if (CollectionUtils.isNotEmpty(userApprovedScopesSet) ||
+ AuthorizationDetailsUtils.isRichAuthorizationRequest(params)) {
if (log.isDebugEnabled()) {
log.debug("Storing user consent for approved scopes : " + userApprovedScopesSet.stream()
.collect(Collectors.joining(" ")) + " of client : " + params.getClientId());
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index b651d1161b..f9e8deb6bf 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.133-SNAPSHOT
+ 7.0.150-SNAPSHOT
4.0.0
@@ -44,17 +44,17 @@
provided
-
- com.google.auto.service
- auto-service
-
-
com.fasterxml.jackson.core
jackson-databind
provided
+
+ io.vertx
+ vertx-json-schema
+
+
org.testng
@@ -123,8 +123,9 @@
**/*Constants.class
- **/model/**
**/dto/**
+ **/exception/**
+ **/model/**
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
new file mode 100644
index 0000000000..b476f62030
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.json.DecodeException;
+import io.vertx.core.json.JsonObject;
+import io.vertx.json.schema.Draft;
+import io.vertx.json.schema.JsonSchema;
+import io.vertx.json.schema.JsonSchemaOptions;
+import io.vertx.json.schema.JsonSchemaValidationException;
+import io.vertx.json.schema.OutputFormat;
+import io.vertx.json.schema.OutputUnit;
+import io.vertx.json.schema.SchemaRepository;
+import io.vertx.json.schema.Validator;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG;
+
+/**
+ * The {@code AuthorizationDetailsSchemaValidator} is responsible for validating authorization details
+ * against a provided JSON schema.
+ *
+ * This class supports both validation of custom schemas provided as input and validation of default schemas
+ * based on the DRAFT202012 standard.
+ *
+ * Typical usage:
+ *
+ * AuthorizationDetailsSchemaValidator validator = AuthorizationDetailsSchemaValidator.getInstance();
+ * boolean isValid = validator.isSchemaCompliant(schemaString, authorizationDetail);
+ *
+ *
+ * Refer to
+ * json-schema for detailed information on the JSON documents structure.
+ *
+ * @see AuthorizationDetail
+ * @see JsonSchema
+ */
+public class AuthorizationDetailsSchemaValidator {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsSchemaValidator.class);
+
+ private static final String ADDITIONAL_PROPERTIES = "additionalProperties";
+ private static final String BASE_URI = "https://wso2.com/identity-server/schemas";
+
+ private static volatile AuthorizationDetailsSchemaValidator instance;
+ private final JsonSchemaOptions jsonSchemaOptions;
+ private final SchemaRepository schemaRepository;
+
+ private AuthorizationDetailsSchemaValidator() {
+
+ this.jsonSchemaOptions = new JsonSchemaOptions()
+ .setBaseUri(BASE_URI)
+ .setDraft(Draft.DRAFT202012)
+ .setOutputFormat(OutputFormat.Basic);
+
+ this.schemaRepository = SchemaRepository.create(this.jsonSchemaOptions)
+ .preloadMetaSchema(Vertx.vertx().fileSystem());
+ }
+
+ public static AuthorizationDetailsSchemaValidator getInstance() {
+
+ if (instance == null) {
+ synchronized (AuthorizationDetailsSchemaValidator.class) {
+ if (instance == null) {
+ instance = new AuthorizationDetailsSchemaValidator();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Validates whether the given schema is compliant with the JSON schema DRAFT202012 standard.
+ *
+ * @param schema the JSON schema as a string.
+ * @return true if the schema is valid, false if the schema is invalid or empty.
+ * @throws AuthorizationDetailsProcessingException if the validation fails or an error occurs during validation.
+ */
+ public boolean isValidSchema(final String schema) throws AuthorizationDetailsProcessingException {
+
+ if (StringUtils.isEmpty(schema)) {
+ log.debug("Schema validation failed. Schema cannot be null");
+ return false;
+ }
+
+ final OutputUnit outputUnit = this.buildOutputUnit(null, this.parseJsonString(schema));
+ try {
+ // Validates the schema itself against the DRAFT202012 schema standard
+ outputUnit.checkValidity();
+ } catch (JsonSchemaValidationException e) {
+ logDebugIfEnabled(String.format("Validation failed against DRAFT202012 schema for input: %s. Caused by, ",
+ schema), e);
+ throw new AuthorizationDetailsProcessingException(String.format(SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT,
+ buildSchemaValidationErrorMessage(outputUnit, e)), e);
+ }
+ return true;
+ }
+
+ private OutputUnit buildOutputUnit(final JsonObject jsonSchema, final JsonObject jsonInput) {
+
+ // Validate the jsonSchema if present, otherwise validate the schema itself against json-schema DRAFT202012
+ final Validator validator = (jsonSchema != null)
+ ? this.schemaRepository.validator(JsonSchema.of(jsonSchema), this.jsonSchemaOptions)
+ : this.schemaRepository.validator(this.jsonSchemaOptions.getDraft().getIdentifier());
+
+ return validator.validate(jsonInput);
+ }
+
+ /**
+ * Converts a JSON string into a {@link JsonObject}. If the input is invalid, throws an exception.
+ *
+ * @param jsonString The input JSON string to be converted.
+ * @return A {@link JsonObject} created from the input string.
+ * @throws AuthorizationDetailsProcessingException if the input string is not valid JSON.
+ */
+ private JsonObject parseJsonString(final String jsonString) throws AuthorizationDetailsProcessingException {
+
+ try {
+ return new JsonObject(jsonString);
+ } catch (DecodeException e) {
+ this.logDebugIfEnabled(String.format("Failed to parse the JSON input: '%s'. Caused by, ", jsonString), e);
+ throw new AuthorizationDetailsProcessingException(
+ String.format("%s. Invalid Json input received.", VALIDATION_FAILED_ERR_MSG), e);
+ }
+ }
+
+ private String buildSchemaValidationErrorMessage(final OutputUnit outputUnit,
+ final JsonSchemaValidationException ex) {
+
+ // Extract the last validation error if available, otherwise use exception message.
+ if (outputUnit == null || CollectionUtils.isEmpty(outputUnit.getErrors())) {
+ return ex.getMessage();
+ }
+ final OutputUnit lastError = outputUnit.getErrors().get(outputUnit.getErrors().size() - 1);
+ return lastError.getInstanceLocation() + StringUtils.SPACE + lastError.getError();
+ }
+
+ /**
+ * Validates whether the given authorization detail complies with the provided JSON schema.
+ *
+ * @param schema the JSON schema as a string.
+ * @param authorizationDetail the authorization detail to be validated.
+ * @return true if the authorization detail is schema compliant, false if schema or authorizationDetail is invalid.
+ * @throws AuthorizationDetailsProcessingException if the validation fails or an error occurs during validation.
+ */
+ public boolean isSchemaCompliant(final String schema, final AuthorizationDetail authorizationDetail)
+ throws AuthorizationDetailsProcessingException {
+
+ if (StringUtils.isEmpty(schema) || authorizationDetail == null) {
+ log.debug("Schema validation failed. Inputs cannot be null");
+ return false;
+ }
+
+ final JsonObject jsonSchema = this.parseJsonString(schema);
+ jsonSchema.put(ADDITIONAL_PROPERTIES, false); // Ensure no unknown fields are allowed
+
+ final OutputUnit outputUnit =
+ this.buildOutputUnit(jsonSchema, this.parseJsonString(authorizationDetail.toJsonString()));
+ try {
+ // Validates the authorization detail against the schema
+ outputUnit.checkValidity();
+ } catch (JsonSchemaValidationException e) {
+ logDebugIfEnabled(String.format("Schema validation failed for authorization details type: %s. Caused by, ",
+ authorizationDetail.getType()), e);
+ throw new AuthorizationDetailsProcessingException(String.format(TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT,
+ authorizationDetail.getType(), buildSchemaValidationErrorMessage(outputUnit, e)), e);
+ }
+ return true;
+ }
+
+ /**
+ * Logs a debug message along with the exception if debug logging is enabled.
+ *
+ * @param message The debug message to log.
+ * @param ex The exception to log along with the message.
+ */
+ private void logDebugIfEnabled(final String message, final Exception ex) {
+
+ if (log.isDebugEnabled()) {
+ log.debug(message, ex);
+ }
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
index 5c467f47bf..be49e2c822 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
@@ -18,11 +18,11 @@
package org.wso2.carbon.identity.oauth2.rar.dao;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import java.sql.SQLException;
-import java.util.List;
import java.util.Set;
/**
@@ -36,13 +36,13 @@ public interface AuthorizationDetailsDAO {
/**
* Adds user consented authorization details to the database.
*
- * @param authorizationDetailsConsentDTOs List of user consented authorization details DTOs.
+ * @param authorizationDetailsConsentDTOs A set of user consented authorization details DTOs.
* {@link AuthorizationDetailsConsentDTO }
* @return An array of positive integers indicating the number of rows affected for each batch operation,
* or negative integers if any of the batch operations fail.
* @throws SQLException If a database access error occurs.
*/
- int[] addUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
+ int[] addUserConsentedAuthorizationDetails(Set authorizationDetailsConsentDTOs)
throws SQLException;
/**
@@ -56,18 +56,6 @@ int[] addUserConsentedAuthorizationDetails(List
Set getUserConsentedAuthorizationDetails(String consentId, int tenantId)
throws SQLException;
- /**
- * Updates user consented authorization details in the database.
- *
- * @param authorizationDetailsConsentDTOs A list of user consented authorization details DTOs.
- * {@link AuthorizationDetailsConsentDTO}
- * @return An array of integers indicating the number of rows affected for each batch operation.
- * Positive values indicate success, negative values indicate failure.
- * @throws SQLException If a database access error occurs.
- */
- int[] updateUserConsentedAuthorizationDetails(List authorizationDetailsConsentDTOs)
- throws SQLException;
-
/**
* Deletes user consented authorization details from the database.
*
@@ -81,13 +69,13 @@ int[] updateUserConsentedAuthorizationDetails(List authorizationDetailsTokenDTOs)
+ int[] addAccessTokenAuthorizationDetails(Set authorizationDetailsTokenDTOs)
throws SQLException;
/**
@@ -111,6 +99,28 @@ Set getAccessTokenAuthorizationDetails(String acce
*/
int deleteAccessTokenAuthorizationDetails(String accessTokenId, int tenantId) throws SQLException;
+ /**
+ * Adds authorization details against a given OAuth2 code.
+ *
+ * @param authorizationDetailsCodeDTOs A list of code authorization details DTOs to store.
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] addOAuth2CodeAuthorizationDetails(Set authorizationDetailsCodeDTOs)
+ throws SQLException;
+
+ /**
+ * Retrieves authorization code authorization details from the database.
+ *
+ * @param authorizationCode The value of the authorization code.
+ * @param tenantId The tenant ID.
+ * @return A set of authorization code authorization details DTOs.
+ * @throws SQLException If a database access error occurs.
+ */
+ Set getOAuth2CodeAuthorizationDetails(String authorizationCode, int tenantId)
+ throws SQLException;
+
/**
* Retrieves the consent ID associated with a specific user ID and application ID.
*
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index 224a4c7e11..a50f8d5f2c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -19,6 +19,7 @@
package org.wso2.carbon.identity.oauth2.rar.dao;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
@@ -27,7 +28,6 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
/**
@@ -43,11 +43,12 @@ public class AuthorizationDetailsDAOImpl implements AuthorizationDetailsDAO {
*/
@Override
public int[] addUserConsentedAuthorizationDetails(
- final List authorizationDetailsConsentDTOs) throws SQLException {
+ final Set authorizationDetailsConsentDTOs) throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
- final PreparedStatement ps =
- connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+ PreparedStatement ps = connection.getMetaData().getDatabaseProductName().contains("H2")
+ ? connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS_H2)
+ : connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
ps.setString(1, consentDTO.getConsentId());
@@ -81,7 +82,7 @@ public Set getUserConsentedAuthorizationDetails(
final Set authorizationDetailsConsentDTOs = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
- final int typeId = rs.getInt(2);
+ final String typeId = rs.getString(2);
final String authorizationDetail = rs.getString(3);
final boolean isConsentActive = rs.getBoolean(4);
@@ -93,31 +94,6 @@ public Set getUserConsentedAuthorizationDetails(
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public int[] updateUserConsentedAuthorizationDetails(
- final List authorizationDetailsConsentDTOs) throws SQLException {
-
-// todo: This won't update the expected element. Hence, need to revisit the update logic
- return null;
-
-// try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
-// final PreparedStatement ps =
-// connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
-//
-// for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
-// ps.setString(1, consentDTO.getAuthorizationDetail().toJsonString());
-// ps.setBoolean(2, consentDTO.isConsentActive());
-// ps.setString(3, consentDTO.getConsentId());
-// ps.setInt(4, consentDTO.getTenantId());
-// ps.addBatch();
-// }
-// return ps.executeBatch();
-// }
- }
-
/**
* {@inheritDoc}
*/
@@ -139,7 +115,7 @@ public int deleteUserConsentedAuthorizationDetails(final String consentId, final
* {@inheritDoc}
*/
@Override
- public int[] addAccessTokenAuthorizationDetails(final List
+ public int[] addAccessTokenAuthorizationDetails(final Set
authorizationDetailsTokenDTOs) throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
@@ -161,8 +137,9 @@ public int[] addAccessTokenAuthorizationDetails(final List getAccessTokenAuthorizationDetails(
- final String accessTokenId, final int tenantId) throws SQLException {
+ public Set getAccessTokenAuthorizationDetails(final String accessTokenId,
+ final int tenantId)
+ throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
@@ -175,7 +152,7 @@ public Set getAccessTokenAuthorizationDetails(
final Set authorizationDetailsTokenDTO = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
- final int typeId = rs.getInt(2);
+ final String typeId = rs.getString(2);
final String authorizationDetail = rs.getString(3);
authorizationDetailsTokenDTO.add(
@@ -203,6 +180,58 @@ public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, fin
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int[] addOAuth2CodeAuthorizationDetails(final Set authorizationDetailsCodeDTOs)
+ throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsCodeDTO authorizationDetailsCodeDTO : authorizationDetailsCodeDTOs) {
+ ps.setString(1, authorizationDetailsCodeDTO.getAuthorizationCodeId());
+ ps.setString(2, authorizationDetailsCodeDTO.getAuthorizationDetail().toJsonString());
+ ps.setString(3, authorizationDetailsCodeDTO.getAuthorizationDetail().getType());
+ ps.setInt(4, authorizationDetailsCodeDTO.getTenantId());
+ ps.setInt(5, authorizationDetailsCodeDTO.getTenantId());
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set getOAuth2CodeAuthorizationDetails(final String authorizationCode,
+ final int tenantId) throws SQLException {
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ final PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.GET_OAUTH2_CODE_AUTHORIZATION_DETAILS_BY_CODE)) {
+
+ ps.setString(1, authorizationCode);
+ ps.setInt(2, tenantId);
+ try (ResultSet rs = ps.executeQuery()) {
+
+ final Set authorizationDetailsCodeDTOs = new HashSet<>();
+ while (rs.next()) {
+ final String codeId = rs.getString(1);
+ final String typeId = rs.getString(2);
+ final String authorizationDetail = rs.getString(3);
+
+ authorizationDetailsCodeDTOs.add(new AuthorizationDetailsCodeDTO(
+ codeId, typeId, authorizationDetail, tenantId));
+ }
+ return authorizationDetailsCodeDTOs;
+ }
+ }
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
index 9cbed27365..cc03a89d62 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
@@ -31,12 +31,14 @@ private SQLQueries() {
public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
"(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
- "VALUES (?, ? FORMAT JSON, ?," +
- "(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ "VALUES (?, ?, ?," +
+ "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
- public static final String UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
- "UPDATE IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
- "SET AUTHORIZATION_DETAILS=? CONSENT=? WHERE CONSENT_ID=? AND TENANT_ID=?";
+ public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS_H2 =
+ "INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
+ "(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
+ "VALUES (?, ? FORMAT JSON, ?," +
+ "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
public static final String GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
@@ -49,7 +51,7 @@ private SQLQueries() {
"INSERT INTO IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
"(TOKEN_ID, AUTHORIZATION_DETAILS, TYPE_ID, TENANT_ID) " +
"VALUES (?, ? FORMAT JSON, " +
- "(SELECT ID FROM IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
public static final String DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
"DELETE FROM IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS WHERE TOKEN_ID=? AND TENANT_ID=?";
@@ -58,6 +60,18 @@ private SQLQueries() {
"SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS FROM IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
"WHERE TOKEN_ID=? AND TENANT_ID=?";
+ public static final String ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS =
+ "INSERT INTO IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS" +
+ "(CODE_ID, AUTHORIZATION_DETAILS, TYPE_ID, TENANT_ID) " +
+ "VALUES (?, ? FORMAT JSON, " +
+ "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+
+ public static final String GET_OAUTH2_CODE_AUTHORIZATION_DETAILS_BY_CODE =
+ "SELECT IOAC.CODE_ID, IOACAD.TYPE_ID, IOACAD.AUTHORIZATION_DETAILS " +
+ "FROM IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS IOACAD " +
+ "INNER JOIN IDN_OAUTH2_AUTHORIZATION_CODE IOAC ON IOACAD.CODE_ID = IOAC.CODE_ID " +
+ "WHERE IOAC.AUTHORIZATION_CODE=? AND IOACAD.TENANT_ID=?";
+
public static final String GET_IDN_OAUTH2_USER_CONSENT_CONSENT_ID =
"SELECT CONSENT_ID FROM IDN_OAUTH2_USER_CONSENT WHERE USER_ID=? AND APP_ID=? AND TENANT_ID=?";
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsCodeDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsCodeDTO.java
new file mode 100644
index 0000000000..4cbf2d1b57
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsCodeDTO.java
@@ -0,0 +1,50 @@
+package org.wso2.carbon.identity.oauth2.rar.dto;
+
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+
+/**
+ * Data Transfer Object (DTO) for representing authorization details along with authorization code.
+ * This class extends {@link AuthorizationDetailsDTO} to include additional fields for authorization code ID.
+ */
+public class AuthorizationDetailsCodeDTO extends AuthorizationDetailsDTO {
+
+ final String codeId;
+
+ /**
+ * Constructs an {@link AuthorizationDetailsCodeDTO} with all required fields.
+ *
+ * @param codeId the authorization code ID associated with the authorization detail.
+ * @param typeId the type ID of the authorization detail.
+ * @param authorizationDetail the {@link AuthorizationDetail} object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsCodeDTO(final String codeId, final String typeId,
+ final String authorizationDetail, final int tenantId) {
+
+ super(null, typeId, authorizationDetail, tenantId);
+ this.codeId = codeId;
+ }
+
+ /**
+ * Constructs an {@link AuthorizationDetailsCodeDTO} with essential fields.
+ *
+ * @param codeId the authorization code ID associated with the authorization detail.
+ * @param authorizationDetail the {@link AuthorizationDetail} object.
+ * @param tenantId the tenant ID.
+ */
+ public AuthorizationDetailsCodeDTO(final String codeId, final AuthorizationDetail authorizationDetail,
+ final int tenantId) {
+
+ super(authorizationDetail, tenantId);
+ this.codeId = codeId;
+ }
+
+ /**
+ * Gets the authorization code ID associated with the authorization detail.
+ *
+ * @return the authorization code ID.
+ */
+ public String getAuthorizationCodeId() {
+ return this.codeId;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
index c70619615f..0af6fb9db5 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsConsentDTO.java
@@ -21,7 +21,7 @@ public class AuthorizationDetailsConsentDTO extends AuthorizationDetailsDTO {
* @param isConsentActive the consent status.
* @param tenantId the tenant ID.
*/
- public AuthorizationDetailsConsentDTO(final String id, final String consentId, final int typeId,
+ public AuthorizationDetailsConsentDTO(final String id, final String consentId, final String typeId,
final String authorizationDetailJson,
final boolean isConsentActive, final int tenantId) {
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
index fe6a85b8ef..00b705d29e 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
@@ -13,7 +13,7 @@
public class AuthorizationDetailsDTO {
final String id;
- final int typeId;
+ final String typeId;
final AuthorizationDetail authorizationDetail;
final int tenantId;
@@ -25,7 +25,7 @@ public class AuthorizationDetailsDTO {
* @param authorizationDetail the authorization detail object.
* @param tenantId the tenant ID.
*/
- public AuthorizationDetailsDTO(final String id, final int typeId, final AuthorizationDetail authorizationDetail,
+ public AuthorizationDetailsDTO(final String id, final String typeId, final AuthorizationDetail authorizationDetail,
final int tenantId) {
this.id = id;
@@ -42,7 +42,7 @@ public AuthorizationDetailsDTO(final String id, final int typeId, final Authoriz
* @param authorizationDetailJson the JSON string of the authorization detail.
* @param tenantId the tenant ID.
*/
- public AuthorizationDetailsDTO(final String id, final int typeId, final String authorizationDetailJson,
+ public AuthorizationDetailsDTO(final String id, final String typeId, final String authorizationDetailJson,
final int tenantId) {
this(id, typeId, AuthorizationDetailsCommonUtils
@@ -57,7 +57,7 @@ public AuthorizationDetailsDTO(final String id, final int typeId, final String a
*/
public AuthorizationDetailsDTO(final AuthorizationDetail authorizationDetail, final int tenantId) {
- this(null, 0, authorizationDetail, tenantId);
+ this(null, null, authorizationDetail, tenantId);
}
/**
@@ -74,7 +74,7 @@ public String getId() {
*
* @return the type ID of the authorization detail.
*/
- public int getTypeId() {
+ public String getTypeId() {
return this.typeId;
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
index a75d7b8681..4167d1159c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsTokenDTO.java
@@ -19,7 +19,7 @@ public class AuthorizationDetailsTokenDTO extends AuthorizationDetailsDTO {
* @param authorizationDetail the {@link AuthorizationDetail} object.
* @param tenantId the tenant ID.
*/
- public AuthorizationDetailsTokenDTO(final String id, final String accessTokenId, final int typeId,
+ public AuthorizationDetailsTokenDTO(final String id, final String accessTokenId, final String typeId,
final String authorizationDetail, final int tenantId) {
super(id, typeId, authorizationDetail, tenantId);
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
similarity index 86%
rename from components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
rename to components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
index 3ccc2784cc..5ed8d48ff6 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/exception/AuthorizationDetailsProcessingException.java
@@ -1,15 +1,15 @@
package org.wso2.carbon.identity.oauth2.rar.exception;
-import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException;
+import org.wso2.carbon.identity.base.IdentityException;
/**
* Exception class to represent failures related to Rich Authorization Requests in OAuth 2.0 clients.
*
* This exception is thrown when there are errors in processing authorization details during the OAuth 2.0
- * authorization flow. It extends the {@link IdentityOAuth2ClientException} class, providing more specific
+ * authorization flow. It extends the {@link IdentityException} class, providing more specific
* context for authorization-related issues.
*/
-public class AuthorizationDetailsProcessingException extends IdentityOAuth2ClientException {
+public class AuthorizationDetailsProcessingException extends IdentityException {
private static final long serialVersionUID = -206212512259482200L;
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
index d34bfedb27..e1e9c3040a 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
@@ -28,20 +28,23 @@
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_ARRAY;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_OBJECT;
+
/**
* Utility class for handling OAuth2 Rich Authorization Requests.
*/
public class AuthorizationDetailsCommonUtils {
private static final Log log = LogFactory.getLog(AuthorizationDetailsCommonUtils.class);
- private static final String empty_json = "{}";
- private static final String empty_json_array = "[]";
- private static final ObjectMapper objectMapper = createDefaultObjectMapper();
+
+ private static volatile ObjectMapper objectMapper;
private AuthorizationDetailsCommonUtils() {
// Private constructor to prevent instantiation
@@ -122,7 +125,7 @@ public static String toJSON(
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing AuthorizationDetails to String. Caused by, ", e);
}
- return empty_json_array;
+ return EMPTY_JSON_ARRAY;
}
/**
@@ -150,7 +153,7 @@ public static String toJSON(
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing AuthorizationDetail to String. Caused by, ", e);
}
- return empty_json;
+ return EMPTY_JSON_OBJECT;
}
/**
@@ -175,19 +178,7 @@ public static Map toMap(
return objectMapper.convertValue(authorizationDetail, new TypeReference>() {
});
}
- return new HashMap<>();
- }
-
- /**
- * Creates a singleton instance of {@link ObjectMapper}.
- *
- * @return the singleton {@link ObjectMapper} instance.
- */
- private static ObjectMapper createDefaultObjectMapper() {
-
- final ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
- return objectMapper;
+ return Collections.emptyMap();
}
/**
@@ -198,6 +189,14 @@ private static ObjectMapper createDefaultObjectMapper() {
* @return a configured {@link ObjectMapper} instance.
*/
public static ObjectMapper getDefaultObjectMapper() {
+ if (objectMapper == null) {
+ synchronized (AuthorizationDetailsCommonUtils.class) {
+ if (objectMapper == null) {
+ objectMapper = new ObjectMapper();
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+ }
+ }
return objectMapper;
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsConstants.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsConstants.java
index 62128f272d..45375fb806 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsConstants.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsConstants.java
@@ -23,15 +23,20 @@
*/
public final class AuthorizationDetailsConstants {
- private AuthorizationDetailsConstants() {
- // Private constructor to prevent instantiation
- }
-
public static final String AUTHORIZATION_DETAILS = "authorization_details";
public static final String AUTHORIZATION_DETAILS_ID_PREFIX = "authorization_detail_id_";
public static final String PARAM_SEPARATOR = "&&";
-
- public static final String TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT = "%s is not a supported authorization details type";
+ public static final String TYPE_NOT_SUPPORTED_ERR_FORMAT = "%s is an unknown authorization details type value";
+ public static final String TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT =
+ "The payload of the authorization details type '%s' contains errors: %s";
+ public static final String SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT =
+ "The schema of the authorization details type contains errors: %s";
public static final String VALIDATION_FAILED_ERR_MSG = "Authorization details validation failed";
public static final String VALIDATION_FAILED_ERR_CODE = "invalid_authorization_details";
+ public static final String EMPTY_JSON_OBJECT = "{}";
+ public static final String EMPTY_JSON_ARRAY = "[]";
+
+ private AuthorizationDetailsConstants() {
+ // Private constructor to prevent instantiation
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
new file mode 100644
index 0000000000..b078f7ea08
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.commons.lang3.StringUtils;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.util.TestDAOUtils;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_SCHEMA;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
+
+/**
+ * Test class for {@link AuthorizationDetailsSchemaValidator}.
+ */
+public class AuthorizationDetailsSchemaValidatorTest {
+
+ private AuthorizationDetailsSchemaValidator uut;
+
+ @BeforeClass
+ public void setUp() throws JsonProcessingException {
+
+ this.uut = AuthorizationDetailsSchemaValidator.getInstance();
+ }
+
+ @Test
+ public void shouldReturnTrue_whenAuthorizationDetailIsSchemaCompliant()
+ throws AuthorizationDetailsProcessingException {
+
+ AuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
+ testAuthorizationDetail.setType(TEST_TYPE);
+
+ assertTrue(this.uut.isSchemaCompliant(TEST_SCHEMA, testAuthorizationDetail));
+ }
+
+ @Test
+ public void shouldReturnFalse_whenSchemaIsEmpty() throws AuthorizationDetailsProcessingException {
+
+ assertFalse(this.uut.isSchemaCompliant(StringUtils.EMPTY, new TestDAOUtils.TestAuthorizationDetail()));
+ assertFalse(this.uut.isSchemaCompliant(TEST_SCHEMA, null));
+ }
+
+ @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class})
+ public void shouldThrowAuthorizationDetailsProcessingException_whenJsonSchemaIsInvalid()
+ throws AuthorizationDetailsProcessingException {
+
+ this.uut.isSchemaCompliant("{", new TestDAOUtils.TestAuthorizationDetail());
+ }
+
+ @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class})
+ public void shouldThrowAuthorizationDetailsProcessingException_whenAuthorizationDetailIsNotSchemaCompliant()
+ throws AuthorizationDetailsProcessingException {
+
+ AuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
+ testAuthorizationDetail.setType(TEST_TYPE);
+ testAuthorizationDetail.setActions(Arrays.asList("initiate", "cancel"));
+
+ assertTrue(this.uut.isSchemaCompliant(TEST_SCHEMA, testAuthorizationDetail));
+ }
+
+ @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class})
+ public void shouldThrowAuthorizationDetailsProcessingException_whenSchemaIsInvalid1()
+ throws AuthorizationDetailsProcessingException {
+
+ final String invalidSchema = "{\"type\":\"object\",\"required\":[\"type\"]," +
+ "\"properties\":{\"type\":{\"type\":\"string\"},\"creditorName\":\"string\"}}";
+
+ assertTrue(this.uut.isValidSchema(TEST_SCHEMA));
+ assertFalse(this.uut.isValidSchema(StringUtils.EMPTY));
+ assertFalse(this.uut.isValidSchema(invalidSchema));
+ }
+
+ @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class})
+ public void shouldThrowAuthorizationDetailsProcessingException_whenSchemaIsInvalid2()
+ throws AuthorizationDetailsProcessingException {
+
+ final String invalidSchema = "{\"type\":\"object\",\"required\":[\"type\"]," +
+ "\"properties\":[{\"type\":{\"type\":\"string\"}}]}";
+
+ assertFalse(this.uut.isValidSchema(invalidSchema));
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index e507d24f25..cc35612769 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.dao;
import org.mockito.MockedStatic;
@@ -7,18 +25,24 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.util.TestDAOUtils;
+import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_AUTHORIZATION_CODE;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_CODE_ID;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_CONSENT_ID;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_DB_NAME;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TENANT_ID;
@@ -47,12 +71,13 @@ public void tearDown() throws SQLException {
@BeforeMethod
public void setUpBeforeMethod() throws SQLException {
+
this.identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
.thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
}
- @Test(priority = 0)
+ @Test
public void testAddUserConsentedAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
@@ -66,7 +91,7 @@ public void testAddUserConsentedAuthorizationDetails() throws SQLException {
AuthorizationDetailsConsentDTO consentDTO =
new AuthorizationDetailsConsentDTO(TEST_CONSENT_ID, testAuthorizationDetail, true, TEST_TENANT_ID);
- int[] result = uut.addUserConsentedAuthorizationDetails(Collections.singletonList(consentDTO));
+ int[] result = uut.addUserConsentedAuthorizationDetails(Collections.singleton(consentDTO));
assertEquals(1, result.length);
}
@@ -97,7 +122,7 @@ public void testDeleteUserConsentedAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
}
- @Test(priority = 0)
+ @Test
public void testAddAccessTokenAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
@@ -111,7 +136,7 @@ public void testAddAccessTokenAuthorizationDetails() throws SQLException {
AuthorizationDetailsTokenDTO tokenDTO =
new AuthorizationDetailsTokenDTO(TEST_TOKEN_ID, testAuthorizationDetail, TEST_TENANT_ID);
- int[] result = uut.addAccessTokenAuthorizationDetails(Collections.singletonList(tokenDTO));
+ int[] result = uut.addAccessTokenAuthorizationDetails(Collections.singleton(tokenDTO));
assertEquals(1, result.length);
}
@@ -139,4 +164,74 @@ public void testDeleteAccessTokenAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
}
+
+ @Test
+ public void testAddOAuth2CodeAuthorizationDetails() throws SQLException {
+ assertEquals(0, this.uut.getOAuth2CodeAuthorizationDetails(TEST_CODE_ID, TEST_TENANT_ID).size());
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+
+ AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
+ testAuthorizationDetail.setType(TEST_TYPE);
+
+ AuthorizationDetailsCodeDTO codeDTO =
+ new AuthorizationDetailsCodeDTO(TEST_CODE_ID, testAuthorizationDetail, TEST_TENANT_ID);
+
+ int[] result = uut.addOAuth2CodeAuthorizationDetails(Collections.singleton(codeDTO));
+
+ assertEquals(1, result.length);
+ }
+
+ @Test(priority = 1)
+ public void testGetOAuth2CodeAuthorizationDetails() throws SQLException {
+ Set codeDTOs =
+ this.uut.getOAuth2CodeAuthorizationDetails(TEST_AUTHORIZATION_CODE, TEST_TENANT_ID);
+
+ assertEquals(1, codeDTOs.size());
+ codeDTOs.forEach(dto -> {
+ assertEquals(TEST_CODE_ID, dto.getAuthorizationCodeId());
+ assertNotNull(dto.getAuthorizationDetail());
+ assertEquals(TEST_TYPE, dto.getAuthorizationDetail().getType());
+ });
+ }
+
+ @Test(priority = 3, expectedExceptions = {SQLException.class})
+ public void shouldThrowSQLException_whenAddingConsentedAuthorizationDetailsFails() throws SQLException {
+
+ try (Connection connectionMock = Mockito.spy(Connection.class)) {
+
+ Mockito.when(connectionMock.getMetaData()).thenThrow(SQLException.class);
+ identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(connectionMock);
+ uut.addUserConsentedAuthorizationDetails(Collections.emptySet());
+ }
+ }
+
+ @Test(priority = 3, expectedExceptions = {SQLException.class})
+ public void shouldThrowSQLException_whenGettingConsentedAuthorizationDetailsFails() throws SQLException {
+
+ try (Connection connectionMock = Mockito.spy(Connection.class)) {
+
+ Mockito.when(connectionMock.prepareStatement(anyString())).thenThrow(SQLException.class);
+ identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(connectionMock);
+ uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID);
+ }
+ }
+
+ @Test
+ public void testGetConsentIdByUserIdAndAppId() throws SQLException {
+
+ assertNotNull(this.uut.getConsentIdByUserIdAndAppId("valid_user_id", "valid_app_id", TEST_TENANT_ID));
+ }
+
+ @Test
+ public void shouldReturnNull_whenUserIdOrAppIdInvalid() throws SQLException {
+
+ assertNull(this.uut.getConsentIdByUserIdAndAppId("invlid_user_id", "invalid_app_id", TEST_TENANT_ID));
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
index ccf61b834c..d556e4e9e2 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.util;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -20,6 +38,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_ARRAY;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_OBJECT;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_NAME;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
/**
@@ -38,7 +59,7 @@ public void setUp() throws JsonProcessingException {
// mock
doThrow(JsonProcessingException.class)
- .when(this.mockObjectMapper).writeValueAsString(any(TestAuthorizationDetail.class));
+ .when(this.mockObjectMapper).writeValueAsString(any(TestDAOUtils.TestAuthorizationDetail.class));
doThrow(JsonProcessingException.class).when(this.mockObjectMapper).writeValueAsString(any(Set.class));
}
@@ -60,7 +81,7 @@ public Object[][] provideAuthorizationDetailsCommonUtilsTestData(Method testMeth
case "shouldReturnCorrectType_whenJSONIsValid":
return new Object[][]{
{AuthorizationDetail.class},
- {TestAuthorizationDetail.class}
+ {TestDAOUtils.TestAuthorizationDetail.class}
};
}
return null;
@@ -95,42 +116,53 @@ public void shouldReturnCorrectType_whenJSONIsVa
@Test
public void shouldReturnCorrectJson_whenAuthorizationDetailsAreValid() {
- AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ TestDAOUtils.TestAuthorizationDetail inputAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
inputAuthorizationDetail.setType(TEST_TYPE);
+ inputAuthorizationDetail.setName(TEST_NAME);
+
+ final String authorizationDetails = AuthorizationDetailsCommonUtils
+ .toJSON(Sets.newHashSet(inputAuthorizationDetail), objectMapper);
- assertTrue(AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail), objectMapper)
- .contains(TEST_TYPE));
- assertEquals("[]", AuthorizationDetailsCommonUtils.toJSON((Set) null, objectMapper));
- assertEquals("[]",
+ assertTrue(authorizationDetails.contains(TEST_TYPE));
+ assertTrue(authorizationDetails.contains(TEST_NAME));
+ assertEquals(EMPTY_JSON_ARRAY,
+ AuthorizationDetailsCommonUtils.toJSON((Set) null, objectMapper));
+ assertEquals(EMPTY_JSON_ARRAY,
AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail), mockObjectMapper));
}
@Test
public void shouldReturnCorrectJson_whenAuthorizationDetailIsValid() {
- AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ TestDAOUtils.TestAuthorizationDetail inputAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
inputAuthorizationDetail.setType(TEST_TYPE);
+ inputAuthorizationDetail.setName(TEST_NAME);
- assertTrue(AuthorizationDetailsCommonUtils.toJSON(inputAuthorizationDetail, objectMapper).contains(TEST_TYPE));
- assertEquals("{}", AuthorizationDetailsCommonUtils.toJSON((TestAuthorizationDetail) null, objectMapper));
- assertEquals("{}", AuthorizationDetailsCommonUtils.toJSON(new TestAuthorizationDetail(), mockObjectMapper));
+ final String authorizationDetail =
+ AuthorizationDetailsCommonUtils.toJSON(inputAuthorizationDetail, objectMapper);
+
+ assertTrue(authorizationDetail.contains(TEST_TYPE));
+ assertTrue(authorizationDetail.contains(TEST_NAME));
+ assertEquals(EMPTY_JSON_OBJECT,
+ AuthorizationDetailsCommonUtils.toJSON((TestDAOUtils.TestAuthorizationDetail) null, objectMapper));
+ assertEquals(EMPTY_JSON_OBJECT,
+ AuthorizationDetailsCommonUtils.toJSON(new TestDAOUtils.TestAuthorizationDetail(), mockObjectMapper));
}
@Test
public void shouldReturnMap_whenAuthorizationDetailIsValid() {
- AuthorizationDetail inputAuthorizationDetail = new TestAuthorizationDetail();
+ TestDAOUtils.TestAuthorizationDetail inputAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
inputAuthorizationDetail.setType(TEST_TYPE);
- Map actualMap = AuthorizationDetailsCommonUtils.toMap(inputAuthorizationDetail, objectMapper);
+ inputAuthorizationDetail.setName(TEST_NAME);
+ Map map = AuthorizationDetailsCommonUtils.toMap(inputAuthorizationDetail, objectMapper);
- assertTrue(actualMap.containsKey("type"));
- assertEquals(TEST_TYPE, String.valueOf(actualMap.get("type")));
- assertEquals(1, actualMap.keySet().size());
+ assertTrue(map.containsKey("type"));
+ assertTrue(map.containsKey("name"));
+ assertEquals(TEST_TYPE, String.valueOf(map.get("type")));
+ assertEquals(TEST_NAME, String.valueOf(map.get("name")));
+ assertEquals(2, map.keySet().size());
assertFalse(AuthorizationDetailsCommonUtils.toMap(null, objectMapper).containsKey(TEST_TYPE));
}
-
- private static class TestAuthorizationDetail extends AuthorizationDetail {
- // Test authorization detail class which extends AuthorizationDetail
- }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
index b8e276837a..9cd3712a5a 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestConstants.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.util;
/**
@@ -5,13 +23,19 @@
*/
public class TestConstants {
- private TestConstants() {
- // Private constructor to prevent instantiation
- }
-
+ public static final String TEST_AUTHORIZATION_CODE = "b1b833f0-f605-4f5c-add6-38ea8ce1b969";
+ public static final String TEST_CODE_ID = "81197bc6-63f3-4c0f-90dd-1588076ab50f";
public static final String TEST_CONSENT_ID = "52481ccd-0927-4d17-8cfc-5110fc4aa009";
public static final String TEST_DB_NAME = "TEST_IAM_RAR_DATABASE";
public static final int TEST_TENANT_ID = 1234;
public static final String TEST_TOKEN_ID = "e1fea951-a3b5-4347-bd73-b18b3feecd54";
public static final String TEST_TYPE = "test_type_v1";
+ public static final String TEST_NAME = "test_name_v1";
+ public static final String TEST_SCHEMA = "{\"type\":\"object\",\"required\":[\"type\"],\"properties\":" +
+ "{\"type\":{\"type\":\"string\",\"enum\":[\"test_type_v1\"]},\"actions\":{\"type\":\"array\"," +
+ "\"items\":{\"type\":\"string\",\"enum\":[\"initiate\"]}}}}";
+
+ private TestConstants() {
+ // Private constructor to prevent instantiation
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
index 8c354b8217..fe2e3b0dd8 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
@@ -1,7 +1,26 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.util;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.StringUtils;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import java.nio.file.Paths;
import java.sql.Connection;
@@ -17,6 +36,7 @@ public class TestDAOUtils {
private static final Map dataSourceMap = new HashMap<>();
public static void initializeDataSource(String databaseName, String scriptPath) throws SQLException {
+
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUsername("username");
@@ -30,6 +50,7 @@ public static void initializeDataSource(String databaseName, String scriptPath)
}
public static Connection getConnection(String database) throws SQLException {
+
if (dataSourceMap.get(database) != null) {
return dataSourceMap.get(database).getConnection();
}
@@ -37,10 +58,27 @@ public static Connection getConnection(String database) throws SQLException {
}
public static String getFilePath(String fileName) {
+
if (StringUtils.isNotBlank(fileName)) {
return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbScripts", fileName)
.toString();
}
return null;
}
+
+ /**
+ * Test authorization detail class which extends AuthorizationDetail
+ */
+ public static class TestAuthorizationDetail extends AuthorizationDetail {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
index 65c28adf66..7ab96e2b44 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
@@ -1,4 +1,4 @@
-CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES(
+CREATE TABLE IF NOT EXISTS AUTHORIZATION_DETAILS_TYPES(
ID INTEGER NOT NULL AUTO_INCREMENT,
TYPE VARCHAR(255) NOT NULL,
CURSOR_KEY INTEGER DEFAULT 1,
@@ -25,5 +25,47 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS (
TENANT_ID INTEGER DEFAULT -1
);
-INSERT INTO IDN_OAUTH2_AUTHORIZATION_DETAILS_TYPES (TYPE, NAME, DESCRIPTION, JSON_SCHEMA, TENANT_ID)
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ TYPE_ID CHAR(36) NOT NULL,
+ AUTHORIZATION_DETAILS JSON NOT NULL,
+ CODE_ID VARCHAR (255),
+ TENANT_ID INTEGER
+);
+
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_CODE (
+ CODE_ID VARCHAR (255),
+ AUTHORIZATION_CODE VARCHAR (2048),
+ CONSUMER_KEY_ID INTEGER,
+ CALLBACK_URL VARCHAR (2048),
+ SCOPE VARCHAR(2048),
+ AUTHZ_USER VARCHAR (100),
+ TENANT_ID INTEGER,
+ USER_DOMAIN VARCHAR(50),
+ TIME_CREATED TIMESTAMP,
+ VALIDITY_PERIOD BIGINT,
+ STATE VARCHAR (25) DEFAULT 'ACTIVE',
+ TOKEN_ID VARCHAR(255),
+ SUBJECT_IDENTIFIER VARCHAR(255),
+ PKCE_CODE_CHALLENGE VARCHAR (255),
+ PKCE_CODE_CHALLENGE_METHOD VARCHAR(128),
+ AUTHORIZATION_CODE_HASH VARCHAR (512),
+ IDP_ID INTEGER DEFAULT -1 NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENT (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ USER_ID VARCHAR(255) NOT NULL,
+ APP_ID CHAR(36) NOT NULL,
+ TENANT_ID INTEGER NOT NULL DEFAULT -1,
+ CONSENT_ID VARCHAR(255) NOT NULL
+);
+
+INSERT INTO AUTHORIZATION_DETAILS_TYPES (TYPE, NAME, DESCRIPTION, JSON_SCHEMA, TENANT_ID)
VALUES ('test_type_v1', 'Test Type', 'Test Type V1', '{}', 1234);
+
+INSERT INTO IDN_OAUTH2_AUTHORIZATION_CODE (CODE_ID, AUTHORIZATION_CODE, IDP_ID)
+VALUES ('81197bc6-63f3-4c0f-90dd-1588076ab50f', 'b1b833f0-f605-4f5c-add6-38ea8ce1b969', 1);
+
+INSERT INTO IDN_OAUTH2_USER_CONSENT (USER_ID, APP_ID, TENANT_ID, CONSENT_ID)
+VALUES ('valid_user_id', 'valid_app_id', 1234, '52481ccd-0927-4d17-8cfc-5110fc4aa009');
\ No newline at end of file
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
index f2065912fc..74edf1ba2c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/testng.xml
@@ -20,8 +20,9 @@
-
+
+
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 8ea9ad8a35..005cd7ab0e 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -265,7 +265,6 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.oauth.rar
- provided
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/util/ResponseTypeHandlerUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/util/ResponseTypeHandlerUtil.java
index 535b629e05..fcedf5cc7b 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/util/ResponseTypeHandlerUtil.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/util/ResponseTypeHandlerUtil.java
@@ -299,6 +299,9 @@ public static AuthzCodeDO generateAuthorizationCode(OAuthAuthzReqMessageContext
OAuthTokenPersistenceFactory.getInstance().getAuthorizationCodeDAO()
.insertAuthorizationCode(authorizationCode, authorizationReqDTO.getConsumerKey(), appTenant,
authorizationReqDTO.getCallbackUrl(), authzCodeDO);
+
+ OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService()
+ .storeAuthorizationCodeAuthorizationDetails(authzCodeDO, oauthAuthzMsgCtx);
} else {
OAuthTokenPersistenceFactory.getInstance().getAuthorizationCodeDAO()
.insertAuthorizationCode(authorizationCode, authorizationReqDTO.getConsumerKey(),
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java
index c562585c65..c365269099 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java
@@ -33,6 +33,7 @@
import org.osgi.service.component.annotations.ReferencePolicy;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager;
+import org.wso2.carbon.identity.api.resource.mgt.AuthorizationDetailsTypeManager;
import org.wso2.carbon.identity.application.authentication.framework.ApplicationAuthenticationService;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationDataPublisher;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationMethodNameTranslator;
@@ -84,6 +85,8 @@
import org.wso2.carbon.identity.oauth2.keyidprovider.KeyIDProvider;
import org.wso2.carbon.identity.oauth2.listener.TenantCreationEventListener;
import org.wso2.carbon.identity.oauth2.model.ResourceAccessControlKey;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.rar.token.AccessTokenResponseRARHandler;
import org.wso2.carbon.identity.oauth2.rar.token.IntrospectionRARDataProvider;
import org.wso2.carbon.identity.oauth2.rar.token.JWTAccessTokenRARClaimProvider;
@@ -1621,4 +1624,71 @@ protected void unregisterConfigurationManager(ConfigurationManager configuration
}
OAuth2ServiceComponentHolder.getInstance().setConfigurationManager(null);
}
+
+ /**
+ * Registers the {@link AuthorizationDetailsTypeManager} service.
+ *
+ * @param typeManager The {@code AuthorizationDetailsTypeManager} instance.
+ */
+ @Reference(
+ name = "org.wso2.carbon.identity.api.resource.mgt.AuthorizationDetailsTypeManager",
+ service = AuthorizationDetailsTypeManager.class,
+ cardinality = ReferenceCardinality.MANDATORY,
+ policy = ReferencePolicy.DYNAMIC,
+ unbind = "unregisterAuthorizationDetailsTypeManager"
+ )
+ protected void registerAuthorizationDetailsTypeManager(AuthorizationDetailsTypeManager typeManager) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Registering the AuthorizationDetailsTypeManager service.");
+ }
+ OAuth2ServiceComponentHolder.getInstance().setAuthorizationDetailsTypeManager(typeManager);
+ }
+
+
+ /**
+ * Unset the {@link AuthorizationDetailsTypeManager} service.
+ *
+ * @param typeManager The {@code AuthorizationDetailsTypeManager} instance.
+ */
+ protected void unregisterAuthorizationDetailsTypeManager(AuthorizationDetailsTypeManager typeManager) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Unregistering the AuthorizationDetailsTypeManager service.");
+ }
+ OAuth2ServiceComponentHolder.getInstance().setAuthorizationDetailsTypeManager(null);
+ }
+
+ /**
+ * Registers the {@link AuthorizationDetailsProcessor} service.
+ *
+ * @param processor The {@code AuthorizationDetailsProcessor} instance.
+ */
+ @Reference(
+ name = "org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor",
+ service = AuthorizationDetailsProcessor.class,
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC,
+ unbind = "unregisterAuthorizationDetailsProcessor"
+ )
+ protected void registerAuthorizationDetailsProcessor(AuthorizationDetailsProcessor processor) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Registering the AuthorizationDetailsProcessor service.");
+ }
+ AuthorizationDetailsProcessorFactory.getInstance().setAuthorizationDetailsProcessors(processor);
+ }
+
+ /**
+ * Unset the {@link AuthorizationDetailsProcessor} service.
+ *
+ * @param processor The {@code AuthorizationDetailsProcessor} instance.
+ */
+ protected void unregisterAuthorizationDetailsProcessor(AuthorizationDetailsProcessor processor) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Unregistering the AuthorizationDetailsProcessor service.");
+ }
+ AuthorizationDetailsProcessorFactory.getInstance().setAuthorizationDetailsProcessors(null);
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
index 28845ea0ce..e1abdeae23 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
@@ -19,6 +19,7 @@
package org.wso2.carbon.identity.oauth2.internal;
import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager;
+import org.wso2.carbon.identity.api.resource.mgt.AuthorizationDetailsTypeManager;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationDataPublisher;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationMethodNameTranslator;
import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService;
@@ -127,6 +128,7 @@ public class OAuth2ServiceComponentHolder {
private ConfigurationManager configurationManager;
private AuthorizationDetailsService authorizationDetailsService;
private AuthorizationDetailsValidator authorizationDetailsValidator;
+ private AuthorizationDetailsTypeManager authorizationDetailsTypeManager;
private OAuth2ServiceComponentHolder() {
@@ -384,7 +386,7 @@ public IdpManager getIdpManager() {
return idpManager;
}
-
+
/**
* Set UserSessionManagementService Instance.
*
@@ -919,4 +921,22 @@ public AuthorizationDetailsValidator getAuthorizationDetailsValidator() {
}
return this.authorizationDetailsValidator;
}
+
+ /**
+ * Get an {@link AuthorizationDetailsTypeManager} instance.
+ *
+ * @return A {@link AuthorizationDetailsTypeManager} singleton instance.
+ */
+ public AuthorizationDetailsTypeManager getAuthorizationDetailsTypeManager() {
+
+ return this.authorizationDetailsTypeManager;
+ }
+
+ /**
+ * set an {@link AuthorizationDetailsTypeManager} instance.
+ */
+ public void setAuthorizationDetailsTypeManager(AuthorizationDetailsTypeManager authorizationDetailsTypeManager) {
+
+ this.authorizationDetailsTypeManager = authorizationDetailsTypeManager;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
index 1170f33070..f870ae85d1 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
@@ -8,10 +8,12 @@
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.AuthzCodeDO;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.rar.dao.AuthorizationDetailsDAO;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
@@ -22,15 +24,13 @@
import java.sql.SQLException;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.getAuthorizationDetailsConsentDTOs;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.getAuthorizationDetailsTypesMap;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.isRichAuthorizationRequest;
/**
@@ -48,11 +48,11 @@ public class AuthorizationDetailsService {
private static final Log log = LogFactory.getLog(AuthorizationDetailsService.class);
private final AuthorizationDetailsDAO authorizationDetailsDAO;
- private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
+ private final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory;
/**
* Default constructor that initializes the service with the default {@link AuthorizationDetailsDAO} and
- * {@link AuthorizationDetailsProviderFactory}.
+ * {@link AuthorizationDetailsProcessorFactory}.
*
* This constructor uses the default DAO provided by the {@link OAuthTokenPersistenceFactory}
* to handle the persistence of authorization details.
@@ -61,7 +61,7 @@ public class AuthorizationDetailsService {
public AuthorizationDetailsService() {
this(
- AuthorizationDetailsProviderFactory.getInstance(),
+ AuthorizationDetailsProcessorFactory.getInstance(),
OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO()
);
}
@@ -69,16 +69,16 @@ public AuthorizationDetailsService() {
/**
* Constructor that initializes the service with a given {@link AuthorizationDetailsDAO}.
*
- * @param authorizationDetailsProviderFactory Factory instance for providing authorization details.
- * @param authorizationDetailsDAO The {@link AuthorizationDetailsDAO} instance to be used for
- * handling authorization details persistence. Must not be {@code null}.
+ * @param authorizationDetailsProcessorFactory Factory instance for providing authorization details.
+ * @param authorizationDetailsDAO The {@link AuthorizationDetailsDAO} instance to be used for
+ * handling authorization details persistence. Must not be {@code null}.
*/
- public AuthorizationDetailsService(final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory,
+ public AuthorizationDetailsService(final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory,
final AuthorizationDetailsDAO authorizationDetailsDAO) {
this.authorizationDetailsDAO = Objects
.requireNonNull(authorizationDetailsDAO, "AuthorizationDetailsDAO must not be null");
- this.authorizationDetailsProviderFactory = Objects.requireNonNull(authorizationDetailsProviderFactory,
+ this.authorizationDetailsProcessorFactory = Objects.requireNonNull(authorizationDetailsProcessorFactory,
"AuthorizationDetailsProviderFactory must not be null");
}
@@ -109,7 +109,7 @@ public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authe
final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
.getTrimmedAuthorizationDetails(userConsentedAuthorizationDetails);
- final List authorizationDetailsConsentDTOs =
+ final Set authorizationDetailsConsentDTOs =
getAuthorizationDetailsConsentDTOs(consentId.get(), trimmedAuthorizationDetails, tenantId);
this.authorizationDetailsDAO.addUserConsentedAuthorizationDetails(authorizationDetailsConsentDTOs);
@@ -124,33 +124,6 @@ public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authe
}
}
- public void updateUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final String clientId, final OAuth2Parameters oAuth2Parameters,
- final AuthorizationDetails userConsentedAuthorizationDetails)
- throws OAuthSystemException {
-
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
- return;
- }
-
- try {
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
-
- if (consentId.isPresent()) {
-
- final List authorizationDetailsConsentDTOs =
- getAuthorizationDetailsConsentDTOs(consentId.get(),
- userConsentedAuthorizationDetails, tenantId);
-
- this.authorizationDetailsDAO.updateUserConsentedAuthorizationDetails(authorizationDetailsConsentDTOs);
- }
- } catch (SQLException | IdentityOAuth2Exception e) {
- log.error("Error occurred while updating user consented authorization details. Caused by, ", e);
- throw new OAuthSystemException("Error occurred while updating authorization details", e);
- }
- }
-
/**
* Deletes user-consented authorization details.
*
@@ -224,13 +197,109 @@ public boolean isUserAlreadyConsentedForAuthorizationDetails(final Authenticated
return this.getConsentRequiredAuthorizationDetails(authenticatedUser, oAuth2Parameters).getDetails().isEmpty();
}
+ public AuthorizationDetails getConsentRequiredAuthorizationDetails(final AuthenticatedUser authenticatedUser,
+ final OAuth2Parameters oAuth2Parameters)
+ throws IdentityOAuth2Exception {
+
+ if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ log.debug("Request is not a rich authorization request. Skipping the authorization details retrieval.");
+ return new AuthorizationDetails();
+ }
+
+ final Map> consentedAuthorizationDetailsByType =
+ this.getUserConsentedAuthorizationDetailsByType(authenticatedUser, oAuth2Parameters);
+
+ final Set consentRequiredAuthorizationDetails = new HashSet<>();
+ oAuth2Parameters.getAuthorizationDetails().stream()
+ .filter(requestedDetail ->
+ !this.isUserConsentedAuthorizationDetail(requestedDetail, consentedAuthorizationDetailsByType))
+ .forEach(consentRequiredAuthorizationDetails::add);
+
+ return new AuthorizationDetails(consentRequiredAuthorizationDetails);
+ }
+
+ private Map> getUserConsentedAuthorizationDetailsByType(
+ final AuthenticatedUser authenticatedUser, final OAuth2Parameters oAuth2Parameters)
+ throws IdentityOAuth2Exception {
+
+ return getAuthorizationDetailsTypesMap(
+ this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters));
+ }
+
+ /**
+ * Checks if the user has already consented to the requested authorization detail.
+ *
+ * This method validates if the requested authorization detail is part of the consented authorization details.
+ * It uses the appropriate provider to compare the requested detail with the existing consented details.
+ *
+ * @param requestedAuthorizationDetail the authorization detail to be checked
+ * @param consentedAuthorizationDetailsByType a map of consented authorization details grouped by type
+ * @return {@code true} if the user has consented to the requested authorization detail, {@code false} otherwise
+ */
+ private boolean isUserConsentedAuthorizationDetail(
+ final AuthorizationDetail requestedAuthorizationDetail,
+ final Map> consentedAuthorizationDetailsByType) {
+
+ final String requestedType = requestedAuthorizationDetail.getType();
+ if (!consentedAuthorizationDetailsByType.containsKey(requestedType)) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("User hasn't consented for the requested authorization details type '%s'.",
+ requestedType));
+ }
+ return false;
+ }
+
+ final Optional optProcessor =
+ this.authorizationDetailsProcessorFactory.getAuthorizationDetailsProcessorByType(requestedType);
+
+ if (optProcessor.isPresent()) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Validating equality of requested and existing authorization details " +
+ "using processor class: " + optProcessor.get().getClass().getSimpleName());
+ }
+
+ final AuthorizationDetails existingAuthorizationDetails =
+ new AuthorizationDetails(consentedAuthorizationDetailsByType.get(requestedType));
+ boolean isEqualOrSubset = optProcessor.get()
+ .isEqualOrSubset(requestedAuthorizationDetail, existingAuthorizationDetails);
+
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Verifying if the user has already consented to the requested " +
+ "authorization details type: '%s'. Result: %b", requestedType, isEqualOrSubset));
+ }
+ return isEqualOrSubset;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("No AuthorizationDetailsProcessor implementation found for type: %s. " +
+ "Proceeding with user consent.", requestedType));
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves the user consented authorization details for a given user and OAuth2 parameters.
+ *
+ * @param authenticatedUser The authenticated user.
+ * @param oAuth2Parameters The OAuth2 parameters.
+ * @return The user consented authorization details.
+ * @throws IdentityOAuth2Exception If an error occurs while retrieving the details.
+ */
+ public AuthorizationDetails getUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
+ final OAuth2Parameters oAuth2Parameters)
+ throws IdentityOAuth2Exception {
+
+ final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
+ return this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters.getClientId(), tenantId);
+ }
+
/**
* Retrieves the user consented authorization details for a given user, client, and tenant.
*
* @param authenticatedUser The authenticated user.
* @param clientId The client ID.
* @param tenantId The tenant ID.
- * @return The user consented authorization details.
+ * @return The user consented authorization details, or {@code null} if no consent is found.
* @throws IdentityOAuth2Exception If an error occurs while retrieving the details.
*/
public AuthorizationDetails getUserConsentedAuthorizationDetails(
@@ -238,39 +307,62 @@ public AuthorizationDetails getUserConsentedAuthorizationDetails(
throws IdentityOAuth2Exception {
try {
- final Set consentedAuthorizationDetails = new HashSet<>();
final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
if (consentId.isPresent()) {
- final Set consentedAuthorizationDetailsDTOs =
- this.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId.get(), tenantId);
-
- consentedAuthorizationDetailsDTOs
+ final Set consentedAuthorizationDetails = new HashSet<>();
+ this.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId.get(), tenantId)
.stream()
.filter(AuthorizationDetailsConsentDTO::isConsentActive)
.map(AuthorizationDetailsConsentDTO::getAuthorizationDetail)
.forEach(consentedAuthorizationDetails::add);
+ return new AuthorizationDetails(consentedAuthorizationDetails);
}
- return new AuthorizationDetails(consentedAuthorizationDetails);
} catch (SQLException e) {
log.error("Error occurred while retrieving user consented authorization details. Caused by, ", e);
throw new IdentityOAuth2Exception("Unable to retrieve user consented authorization details", e);
}
+ return null;
}
/**
- * Retrieves the user consented authorization details for a given user and OAuth2 parameters.
+ * Retrieves the consent ID for the given user, client, and tenant.
*
* @param authenticatedUser The authenticated user.
- * @param oAuth2Parameters The OAuth2 parameters.
- * @return The user consented authorization details.
- * @throws IdentityOAuth2Exception If an error occurs while retrieving the details.
+ * @param clientId The client ID.
+ * @param tenantId The tenant ID.
+ * @return An {@link Optional} containing the consent ID if present.
+ * @throws IdentityOAuth2Exception if an error occurs related to OAuth2 identity.
*/
- public AuthorizationDetails getUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final OAuth2Parameters oAuth2Parameters)
+ private Optional getConsentId(final AuthenticatedUser authenticatedUser, final String clientId,
+ final int tenantId)
throws IdentityOAuth2Exception {
- final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- return this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters.getClientId(), tenantId);
+ final String userId = AuthorizationDetailsUtils.getIdFromAuthenticatedUser(authenticatedUser);
+ final String appId = AuthorizationDetailsUtils.getApplicationResourceIdFromClientId(clientId);
+
+ return this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
+ }
+
+ /**
+ * Retrieves the consent ID by user ID and application ID.
+ *
+ * @param userId The user ID.
+ * @param appId The application ID.
+ * @param tenantId The tenant ID.
+ * @return An {@link Optional} containing the consent ID if present.
+ * @throws IdentityOAuth2Exception if an error occurs while retrieving the consent ID.
+ */
+ public Optional getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
+ throws IdentityOAuth2Exception {
+
+ try {
+ return Optional
+ .ofNullable(this.authorizationDetailsDAO.getConsentIdByUserIdAndAppId(userId, appId, tenantId));
+ } catch (SQLException e) {
+ log.error(String.format("Error occurred while retrieving user consent by " +
+ "userId: %s and appId: %s. Caused by, ", userId, appId), e);
+ throw new IdentityOAuth2Exception("Error occurred while retrieving user consent", e);
+ }
}
/**
@@ -320,25 +412,6 @@ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessToken
this.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthAuthzReqMessageContext.getAuthorizationDetails());
}
- /**
- * Stores the authorization details for a given access token and OAuth token request context.
- *
- * @param accessTokenDO The access token data object.
- * @param oAuthTokenReqMessageContext The OAuth token request message context.
- * @throws IdentityOAuth2Exception If an error occurs while storing the details.
- */
- public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessTokenDO,
- final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
- throws IdentityOAuth2Exception {
-
- if (!isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
- log.debug("Request is not a rich authorization request. Skipping storage of token authorization details.");
- return;
- }
-
- this.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthTokenReqMessageContext.getAuthorizationDetails());
- }
-
/**
* Stores the authorization details for a given access token and authorization details.
*
@@ -354,7 +427,7 @@ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessToken
final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
.getTrimmedAuthorizationDetails(authorizationDetails);
- final List authorizationDetailsTokenDTOs = AuthorizationDetailsUtils
+ final Set authorizationDetailsTokenDTOs = AuthorizationDetailsUtils
.getAccessTokenAuthorizationDetailsDTOs(accessTokenDO, trimmedAuthorizationDetails);
// Storing the authorization details.
@@ -396,27 +469,6 @@ public void storeOrReplaceAccessTokenAuthorizationDetails(
oAuthTokenReqMessageContext.getAuthorizationDetails());
}
- /**
- * Replaces the authorization details for an old access token with the details of a new access token.
- *
- * @param oldAccessTokenId The old access token ID.
- * @param newAccessTokenDO The new access token data object.
- * @param oAuthTokenReqMessageContext The OAuth token request message context.
- * @throws IdentityOAuth2Exception If an error occurs while replacing the details.
- */
- public void replaceAccessTokenAuthorizationDetails(final String oldAccessTokenId,
- final AccessTokenDO newAccessTokenDO,
- final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
- throws IdentityOAuth2Exception {
-
- if (!isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
- log.debug("Request is not a rich authorization request. Skipping replacement of authorization details.");
- return;
- }
- this.deleteAccessTokenAuthorizationDetails(oldAccessTokenId, newAccessTokenDO.getTenantID());
- this.storeAccessTokenAuthorizationDetails(newAccessTokenDO, oAuthTokenReqMessageContext);
- }
-
/**
* Deletes the authorization details associated with a given access token.
*
@@ -439,120 +491,107 @@ public void deleteAccessTokenAuthorizationDetails(final String accessTokenId, fi
}
/**
- * Retrieves the consent ID for the given user, client, and tenant.
+ * Replaces the authorization details for an old access token with the details of a new access token.
*
- * @param authenticatedUser The authenticated user.
- * @param clientId The client ID.
- * @param tenantId The tenant ID.
- * @return An {@link Optional} containing the consent ID if present.
- * @throws IdentityOAuth2Exception if an error occurs related to OAuth2 identity.
+ * @param oldAccessTokenId The old access token ID.
+ * @param newAccessTokenDO The new access token data object.
+ * @param oAuthTokenReqMessageContext The OAuth token request message context.
+ * @throws IdentityOAuth2Exception If an error occurs while replacing the details.
*/
- private Optional getConsentId(final AuthenticatedUser authenticatedUser, final String clientId,
- final int tenantId)
+ public void replaceAccessTokenAuthorizationDetails(final String oldAccessTokenId,
+ final AccessTokenDO newAccessTokenDO,
+ final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
throws IdentityOAuth2Exception {
- final String userId = AuthorizationDetailsUtils.getIdFromAuthenticatedUser(authenticatedUser);
- final String appId = AuthorizationDetailsUtils.getApplicationResourceIdFromClientId(clientId);
-
- return this.getConsentIdByUserIdAndAppId(userId, appId, tenantId);
+ if (!isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
+ log.debug("Request is not a rich authorization request. Skipping replacement of authorization details.");
+ return;
+ }
+ this.deleteAccessTokenAuthorizationDetails(oldAccessTokenId, newAccessTokenDO.getTenantID());
+ this.storeAccessTokenAuthorizationDetails(newAccessTokenDO, oAuthTokenReqMessageContext);
}
/**
- * Retrieves the consent ID by user ID and application ID.
+ * Stores the authorization details for a given access token and OAuth token request context.
*
- * @param userId The user ID.
- * @param appId The application ID.
- * @param tenantId The tenant ID.
- * @return An {@link Optional} containing the consent ID if present.
- * @throws IdentityOAuth2Exception if an error occurs while retrieving the consent ID.
+ * @param accessTokenDO The access token data object.
+ * @param oAuthTokenReqMessageContext The OAuth token request message context.
+ * @throws IdentityOAuth2Exception If an error occurs while storing the details.
*/
- public Optional getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
+ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessTokenDO,
+ final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
throws IdentityOAuth2Exception {
- try {
- return Optional
- .ofNullable(this.authorizationDetailsDAO.getConsentIdByUserIdAndAppId(userId, appId, tenantId));
- } catch (SQLException e) {
- log.error(String.format("Error occurred while retrieving user consent by " +
- "userId: %s and appId: %s. Caused by, ", userId, appId), e);
- throw new IdentityOAuth2Exception("Error occurred while retrieving user consent", e);
+ if (!isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
+ log.debug("Request is not a rich authorization request. Skipping storage of token authorization details.");
+ return;
}
+
+ this.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthTokenReqMessageContext.getAuthorizationDetails());
}
- public AuthorizationDetails getConsentRequiredAuthorizationDetails(final AuthenticatedUser authenticatedUser,
- final OAuth2Parameters oAuth2Parameters)
+ /**
+ * Stores the authorization details for a given authorization code and OAuth authorization request context.
+ *
+ * @param authzCodeDO The authorization code data object.
+ * @param oAuthAuthzReqMessageContext The OAuth authorization request message context.
+ * @throws IdentityOAuth2Exception If an error occurs while storing the details.
+ */
+ public void storeAuthorizationCodeAuthorizationDetails(
+ final AuthzCodeDO authzCodeDO, final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
throws IdentityOAuth2Exception {
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
- log.debug("Request is not a rich authorization request. Skipping the authorization details retrieval.");
- return new AuthorizationDetails();
+ if (!isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
+ log.debug("Request is not a rich authorization request. Skipping storage of code authorization details.");
+ return;
}
- final Map> consentedAuthorizationDetailsByType =
- getUserConsentedAuthorizationDetailsByType(authenticatedUser, oAuth2Parameters);
+ try {
+ final int tenantId =
+ OAuth2Util.getTenantId(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain());
- final Set consentRequiredAuthorizationDetails = new HashSet<>();
- oAuth2Parameters.getAuthorizationDetails().stream()
- .filter(requestedDetail ->
- !this.isUserConsentedAuthorizationDetail(consentedAuthorizationDetailsByType, requestedDetail))
- .forEach(consentRequiredAuthorizationDetails::add);
+ final Set authorizationDetailsCodeDTOs =
+ AuthorizationDetailsUtils.getCodeAuthorizationDetailsDTOs(authzCodeDO,
+ oAuthAuthzReqMessageContext.getAuthorizationDetails(), tenantId);
- return new AuthorizationDetails(consentRequiredAuthorizationDetails);
- }
-
- private Map> getUserConsentedAuthorizationDetailsByType(
- final AuthenticatedUser authenticatedUser, final OAuth2Parameters oAuth2Parameters)
- throws IdentityOAuth2Exception {
+ // Storing the authorization details.
+ this.authorizationDetailsDAO.addOAuth2CodeAuthorizationDetails(authorizationDetailsCodeDTOs);
- return this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters)
- .stream()
- .collect(Collectors.groupingBy(AuthorizationDetail::getType,
- Collectors.mapping(Function.identity(), Collectors.toSet())));
+ if (log.isDebugEnabled()) {
+ log.debug("Successfully stored authorization code authorization details for code ID: " +
+ authzCodeDO.getAuthzCodeId());
+ }
+ } catch (SQLException e) {
+ log.error("Error occurred while storing authorization code authorization details. Caused by, ", e);
+ throw new IdentityOAuth2Exception("Error occurred while storing authz code authorization details", e);
+ }
}
/**
- * Checks if the user has already consented to the requested authorization detail.
- *
- * This method validates if the requested authorization detail is part of the consented authorization details.
- * It uses the appropriate provider to compare the requested detail with the existing consented details.
+ * Retrieves the authorization details associated with a given authorization code Id.
*
- * @param consentedAuthorizationDetailsByType a map of consented authorization details grouped by type
- * @param requestedAuthorizationDetail the authorization detail to be checked
- * @return {@code true} if the user has consented to the requested authorization detail, {@code false} otherwise
+ * @param codeId The authorization code ID.
+ * @param tenantId The tenant ID.
+ * @return The authorization code authorization details.
+ * @throws IdentityOAuth2Exception If an error occurs while retrieving the details.
*/
- public boolean isUserConsentedAuthorizationDetail(
- final Map> consentedAuthorizationDetailsByType,
- final AuthorizationDetail requestedAuthorizationDetail) {
-
- if (!consentedAuthorizationDetailsByType.containsKey(requestedAuthorizationDetail.getType())) {
- log.debug("Request is not a rich authorization request. Skipping the validation.");
- return false;
- }
-
- final Optional provider = this.authorizationDetailsProviderFactory
- .getProviderByType(requestedAuthorizationDetail.getType());
- if (provider.isPresent()) {
+ public AuthorizationDetails getAuthorizationCodeAuthorizationDetails(final String codeId, final int tenantId)
+ throws IdentityOAuth2Exception {
- if (log.isDebugEnabled()) {
- log.debug("Validating equality of requested and existing authorization details " +
- "using provider class: " + provider.get().getClass().getSimpleName());
- }
+ try {
+ final Set authorizationDetailsCodeDTOs =
+ this.authorizationDetailsDAO.getOAuth2CodeAuthorizationDetails(codeId, tenantId);
- final AuthorizationDetails existingAuthorizationDetails = new AuthorizationDetails(
- consentedAuthorizationDetailsByType.get(requestedAuthorizationDetail.getType()));
- boolean isEqualOrSubset = provider.get()
- .isEqualOrSubset(requestedAuthorizationDetail, existingAuthorizationDetails);
+ final Set codeAuthorizationDetails = new HashSet<>();
+ authorizationDetailsCodeDTOs
+ .stream()
+ .map(AuthorizationDetailsCodeDTO::getAuthorizationDetail)
+ .forEach(codeAuthorizationDetails::add);
- if (log.isDebugEnabled() && isEqualOrSubset) {
- log.debug("User has already consented for the requested authorization details type: "
- + requestedAuthorizationDetail.getType());
- }
- return isEqualOrSubset;
- }
- if (log.isDebugEnabled()) {
- log.debug(String.format("Ignores unsupported authorization details type: %s",
- requestedAuthorizationDetail.getType()));
+ return new AuthorizationDetails(codeAuthorizationDetails);
+ } catch (SQLException e) {
+ log.error("Error occurred while retrieving authz code authorization details. Caused by, ", e);
+ throw new IdentityOAuth2Exception("Unable to retrieve authz code authorization details", e);
}
- return true;
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessor.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessor.java
index 44b68875a4..569751a9ba 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessor.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessor.java
@@ -27,13 +27,11 @@
/**
* The {@code AuthorizationDetailsProcessor} interface defines a contract for implementing
- * different types of authorization detail providers in a Service Provider Interface (SPI) setup.
+ * different types of authorization detail providers in an OSGI setup.
*
* Implementing classes are expected to provide mechanisms to validate, enrich, and identify
* authorization details specific to various types.
*
- *
- * @see Java SPI
*/
public interface AuthorizationDetailsProcessor {
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
new file mode 100644
index 0000000000..a8798b42e2
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.core;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtException;
+import org.wso2.carbon.identity.application.common.model.AuthorizationDetailsType;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * A factory class to manage and provide instances of {@link AuthorizationDetailsProcessor} Service Provider Interface.
+ * This class follows the Singleton pattern to ensure only one instance is created.
+ * It uses {@link ServiceLoader} to dynamically load and manage {@link AuthorizationDetailsProcessor} implementations.
+ * Example usage:
+ *
{@code
+ * // Get a specific provider by type
+ * AuthorizationDetailsProviderFactory.getInstance()
+ * .getProviderByType("customer_information")
+ * .ifPresentOrElse(
+ * p -> log.debug("Provider for type " + type + ": " + p.getClass().getName()),
+ * () -> log.debug("No provider found for type " + type)
+ * );
+ * }
+ *
+ * @see AuthorizationDetailsProcessor AuthorizationDetailsService
+ * @see
+ * Request Parameter "authorization_details"
+ */
+public class AuthorizationDetailsProcessorFactory {
+
+ private static final Log log = LogFactory.getLog(AuthorizationDetailsProcessorFactory.class);
+ private static volatile AuthorizationDetailsProcessorFactory instance;
+ private final Map authorizationDetailsProcessors;
+
+ /**
+ * Private constructor to initialize the factory.
+ * This constructor is intentionally private to prevent direct instantiation of the
+ * {@code AuthorizationDetailsProviderFactory} class.
+ * Instead, use the {@link #getInstance()} method to obtain the singleton instance.
+ */
+ private AuthorizationDetailsProcessorFactory() {
+
+ this.authorizationDetailsProcessors = new HashMap<>();
+ }
+
+ /**
+ * Provides the singleton instance of {@code AuthorizationDetailsProviderFactory}.
+ *
+ * @return Singleton instance of {@code AuthorizationDetailsProviderFactory}.
+ */
+ public static AuthorizationDetailsProcessorFactory getInstance() {
+
+ if (instance == null) {
+ synchronized (AuthorizationDetailsProcessorFactory.class) {
+ if (instance == null) {
+ instance = new AuthorizationDetailsProcessorFactory();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Returns the {@link AuthorizationDetailsProcessor} provider for the given type.
+ *
+ * @param type A supported authorization details type.
+ * @return {@link Optional} containing the {@link AuthorizationDetailsProcessor} if present, otherwise empty.
+ * @see AuthorizationDetailsProcessor#getType() getAuthorizationDetailsType
+ */
+ public Optional getAuthorizationDetailsProcessorByType(final String type) {
+
+ return Optional.ofNullable(this.authorizationDetailsProcessors.get(type));
+ }
+
+ /**
+ * Checks if a given type has a valid service provider implementation.
+ *
+ * @param type The type to check.
+ * @return {@code true} if the type is supported, {@code false} otherwise.
+ * @see AuthorizationDetailsProcessor AuthorizationDetailsService
+ */
+ public boolean isSupportedAuthorizationDetailsType(final String type) {
+
+ return this.getSupportedAuthorizationDetailTypes().contains(type);
+ }
+
+ /**
+ * Returns an {@link Collections#unmodifiableSet} containing all supported authorization details types.
+ * A type is considered "supported" if it has been registered by invoking the
+ * POST: /api/server/v1/api-resources
endpoint.
+ *
+ * @return An unmodifiable set of supported authorization details types.
+ */
+ public Set getSupportedAuthorizationDetailTypes() {
+
+ final String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ try {
+ return OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsTypeManager()
+ .getAuthorizationDetailsTypes(StringUtils.EMPTY, tenantDomain)
+ .stream()
+ .map(AuthorizationDetailsType::getType)
+ .collect(Collectors.toUnmodifiableSet());
+ } catch (APIResourceMgtException e) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Error occurred while retrieving supported authorization details types " +
+ "for tenant: %s. Caused by, ", tenantDomain), e);
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ /**
+ * Caches the provided {@link AuthorizationDetailsProcessor} instance by associating it with its corresponding
+ * authorization details type. This allows efficient retrieval and reuse of processors based on their type.
+ * The type of the authorization details processor is obtained using
+ * {@link AuthorizationDetailsProcessor#getType()}
+ *
+ * @param authorizationDetailsProcessor Processor instance to be cached, keyed by its authorization details type.
+ */
+ public void setAuthorizationDetailsProcessors(final AuthorizationDetailsProcessor authorizationDetailsProcessor) {
+
+ if (authorizationDetailsProcessor != null && StringUtils.isNotBlank(authorizationDetailsProcessor.getType())) {
+ final String type = authorizationDetailsProcessor.getType();
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Registering AuthorizationDetailsProcessor %s against type %s",
+ authorizationDetailsProcessor.getClass().getSimpleName(), type));
+ }
+ this.authorizationDetailsProcessors.put(type, authorizationDetailsProcessor);
+ }
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
deleted file mode 100644
index 64ca86d097..0000000000
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProviderFactory.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. 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.oauth2.rar.core;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-/**
- * A factory class to manage and provide instances of {@link AuthorizationDetailsProcessor} Service Provider Interface.
- * This class follows the Singleton pattern to ensure only one instance is created.
- * It uses {@link ServiceLoader} to dynamically load and manage {@link AuthorizationDetailsProcessor} implementations.
- * Example usage:
- *
{@code
- * // Get a specific provider by type
- * AuthorizationDetailsProviderFactory.getInstance()
- * .getProviderByType("customer_information")
- * .ifPresentOrElse(
- * p -> log.debug("Provider for type " + type + ": " + p.getClass().getName()),
- * () -> log.debug("No provider found for type " + type)
- * );
- * }
- *
- * @see AuthorizationDetailsProcessor AuthorizationDetailsService
- * @see
- * Request Parameter "authorization_details"
- */
-public class AuthorizationDetailsProviderFactory {
-
- private static volatile AuthorizationDetailsProviderFactory instance;
- private final Map supportedAuthorizationDetailsTypes;
-
- /**
- * Private constructor to initialize the factory.
- * This constructor is intentionally private to prevent direct instantiation of the
- * {@code AuthorizationDetailsProviderFactory} class.
- * Instead, use the {@link #getInstance()} method to obtain the singleton instance.
- */
- private AuthorizationDetailsProviderFactory() {
-
- this.supportedAuthorizationDetailsTypes = this.loadSupportedAuthorizationDetailsTypes();
- }
-
- /**
- * Loads supported authorization details Processors from the provided {@link ServiceLoader}.
- *
- * @return Map of authorization details types with their corresponding SPI services.
- */
- private Map loadSupportedAuthorizationDetailsTypes() {
-
- final ServiceLoader serviceLoader = ServiceLoader
- .load(AuthorizationDetailsProcessor.class, this.getClass().getClassLoader());
-
- return StreamSupport.stream(serviceLoader.spliterator(), false)
- .collect(Collectors.toMap(AuthorizationDetailsProcessor::getType, Function.identity()));
- }
-
- /**
- * Provides the singleton instance of {@code AuthorizationDetailsProviderFactory}.
- *
- * @return Singleton instance of {@code AuthorizationDetailsProviderFactory}.
- */
- public static AuthorizationDetailsProviderFactory getInstance() {
-
- if (instance == null) {
- synchronized (AuthorizationDetailsProviderFactory.class) {
- if (instance == null) {
- instance = new AuthorizationDetailsProviderFactory();
- }
- }
- }
- return instance;
- }
-
- /**
- * Returns the {@link AuthorizationDetailsProcessor} provider for the given type.
- *
- * @param type A supported authorization details type.
- * @return {@link Optional} containing the {@link AuthorizationDetailsProcessor} if present, otherwise empty.
- * @see AuthorizationDetailsProcessor#getType() getAuthorizationDetailsType
- */
- public Optional getProviderByType(final String type) {
-
- return Optional.ofNullable(this.supportedAuthorizationDetailsTypes.get(type));
- }
-
- /**
- * Checks if a given type has a valid service provider implementation.
- *
- * @param type The type to check.
- * @return {@code true} if the type is supported, {@code false} otherwise.
- * @see AuthorizationDetailsProcessor AuthorizationDetailsService
- */
- public boolean isSupportedAuthorizationDetailsType(final String type) {
-
- return this.supportedAuthorizationDetailsTypes.containsKey(type);
- }
-
- /**
- * Returns a {@link Collections#unmodifiableSet} of all supported authorization details types.
- * To be included as a supported authorization details type, there must be a custom implementation
- * of the {@link AuthorizationDetailsProcessor} Service Provider Interface (SPI) available in the classpath
- * for the specified type.
- *
- * @return A set of supported authorization details types.
- */
- public Set getSupportedAuthorizationDetailTypes() {
-
- return Collections.unmodifiableSet(this.supportedAuthorizationDetailsTypes.keySet());
- }
-}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
index 998ea794ac..893647091c 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetailsContext.java
@@ -19,6 +19,7 @@
package org.wso2.carbon.identity.oauth2.rar.model;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.application.common.model.AuthorizationDetailsType;
import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
@@ -40,10 +41,31 @@ public class AuthorizationDetailsContext {
private final AuthenticatedUser authenticatedUser;
private final AuthorizationDetail authorizationDetail;
+ private final AuthorizationDetailsType authorizationDetailsType;
private final HttpServletRequestWrapper httpServletRequestWrapper;
private final OAuthAppDO oAuthAppDO;
private final String[] scopes;
+ /**
+ * Constructs a new {@code AuthorizationDetailsContext}.
+ *
+ * @param authorizationDetail the specific {@link AuthorizationDetail} to be validated.
+ * @param oAuthAuthzReqMessageContext the {@link OAuthAuthzReqMessageContext} instance which represent
+ * the authorization request context.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail,
+ final AuthorizationDetailsType authorizationDetailsType,
+ final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
+
+ this(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getUser(),
+ authorizationDetail,
+ authorizationDetailsType,
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getHttpServletRequestWrapper(),
+ (OAuthAppDO) oAuthAuthzReqMessageContext.getProperty(OAUTH_APP_PROPERTY),
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getScopes());
+ }
+
/**
* Constructs a new {@code AuthorizationDetailsContext}.
*
@@ -59,36 +81,21 @@ public class AuthorizationDetailsContext {
*/
public AuthorizationDetailsContext(final AuthenticatedUser authenticatedUser,
final AuthorizationDetail authorizationDetail,
+ final AuthorizationDetailsType authorizationDetailsType,
final HttpServletRequestWrapper httpServletRequestWrapper,
final OAuthAppDO oAuthAppDO,
final String[] scopes) {
this.authenticatedUser = Objects.requireNonNull(authenticatedUser, "authenticatedUser cannot be null");
this.authorizationDetail = Objects.requireNonNull(authorizationDetail, "authorizationDetail cannot be null");
- this.httpServletRequestWrapper = Objects
- .requireNonNull(httpServletRequestWrapper, "httpServletRequestWrapper cannot be null");
+ this.authorizationDetailsType =
+ Objects.requireNonNull(authorizationDetailsType, "authorizationDetailsType cannot be null");
+ this.httpServletRequestWrapper =
+ Objects.requireNonNull(httpServletRequestWrapper, "httpServletRequestWrapper cannot be null");
this.oAuthAppDO = Objects.requireNonNull(oAuthAppDO, "oAuthAppDO cannot be null");
this.scopes = Objects.requireNonNull(scopes, "scopes cannot be null");
}
- /**
- * Constructs a new {@code AuthorizationDetailsContext}.
- *
- * @param authorizationDetail the specific {@link AuthorizationDetail} to be validated.
- * @param oAuthAuthzReqMessageContext the {@link OAuthAuthzReqMessageContext} instance which represent
- * the authorization request context.
- * @throws NullPointerException if any of the arguments are {@code null}.
- */
- public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail,
- final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
-
- this(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getUser(),
- authorizationDetail,
- oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getHttpServletRequestWrapper(),
- (OAuthAppDO) oAuthAuthzReqMessageContext.getProperty(OAUTH_APP_PROPERTY),
- oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getScopes());
- }
-
/**
* Constructs a new {@code AuthorizationDetailsContext}.
*
@@ -98,10 +105,12 @@ public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail
* @throws NullPointerException if any of the arguments are {@code null}.
*/
public AuthorizationDetailsContext(final AuthorizationDetail authorizationDetail,
+ final AuthorizationDetailsType authorizationDetailsType,
final OAuthTokenReqMessageContext oAuthTokenReqMessageContext) {
this(oAuthTokenReqMessageContext.getAuthorizedUser(),
authorizationDetail,
+ authorizationDetailsType,
oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getHttpServletRequestWrapper(),
(OAuthAppDO) oAuthTokenReqMessageContext.getProperty(OAUTH_APP_PROPERTY),
oAuthTokenReqMessageContext.getScope());
@@ -116,12 +125,21 @@ public AuthorizationDetail getAuthorizationDetail() {
return this.authorizationDetail;
}
+ /**
+ * Returns the {@code AuthorizationDetailsType} instance.
+ *
+ * @return the {@link AuthorizationDetailsType} instance.
+ */
+ public AuthorizationDetailsType getAuthorizationDetailsType() {
+ return this.authorizationDetailsType;
+ }
+
/**
* Returns the OAuth application details.
*
* @return the {@link OAuthAppDO} instance.
*/
- public OAuthAppDO getoAuthAppDO() {
+ public OAuthAppDO getOAuthAppDO() {
return this.oAuthAppDO;
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
index e6d3f97244..150cf8de51 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
@@ -10,6 +10,7 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
@@ -56,20 +57,25 @@ public Map getIntrospectionData(
final OAuth2TokenValidationRequestDTO tokenValidationRequestDTO,
final OAuth2IntrospectionResponseDTO introspectionResponseDTO) throws IdentityOAuth2Exception {
- final Map introspectionData = new HashMap<>();
- final OAuth2TokenValidationMessageContext tokenValidationMessageContext =
- generateOAuth2TokenValidationMessageContext(tokenValidationRequestDTO, introspectionResponseDTO);
+ try {
+ final OAuth2TokenValidationMessageContext tokenValidationMessageContext =
+ generateOAuth2TokenValidationMessageContext(tokenValidationRequestDTO, introspectionResponseDTO);
+ final Map introspectionData = new HashMap<>();
- if (Objects.nonNull(tokenValidationMessageContext)) {
+ if (Objects.nonNull(tokenValidationMessageContext)) {
- final AuthorizationDetails validatedAuthorizationDetails = this.authorizationDetailsValidator
- .getValidatedAuthorizationDetails(tokenValidationMessageContext);
- if (AuthorizationDetailsUtils.isRichAuthorizationRequest(validatedAuthorizationDetails)) {
+ final AuthorizationDetails validatedAuthorizationDetails = this.authorizationDetailsValidator
+ .getValidatedAuthorizationDetails(tokenValidationMessageContext);
- introspectionData.put(AUTHORIZATION_DETAILS, validatedAuthorizationDetails.toSet());
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(validatedAuthorizationDetails)) {
+ introspectionData.put(AUTHORIZATION_DETAILS, validatedAuthorizationDetails.toSet());
+ }
}
+ return introspectionData;
+ } catch (AuthorizationDetailsProcessingException e) {
+ log.error("Authorization details validation failed. Caused by, ", e);
+ throw new IdentityOAuth2Exception("Authorization details validation failed", e);
}
- return introspectionData;
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index ade73ab635..634da17875 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -13,26 +13,33 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.AuthzCodeDO;
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthTokenRequest;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
-import java.util.List;
+import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.toSet;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS_ID_PREFIX;
/**
@@ -55,55 +62,58 @@ public static boolean isRichAuthorizationRequest(final OAuthAuthzReqMessageConte
}
/**
- * Determines if the given {@link OAuthAuthzRequest} object contains {@code authorization_details}.
+ * Determines if the request is a rich authorization request using provided {@link AuthorizationDetails} object.
+ *
+ * This method checks if the specified {@link AuthorizationDetails} instance is not {@code null}
+ * and has a non-empty details set.
*
- * @param oauthRequest The OAuth Authorization Request to check.
- * @return {@code true} if the OAuth authorization request contains a non-blank authorization details parameter,
+ * @param authorizationDetails The {@link AuthorizationDetails} to check.
+ * @return {@code true} if the {@link AuthorizationDetails} is not {@code null} and has a non-empty details set,
* {@code false} otherwise.
*/
- public static boolean isRichAuthorizationRequest(final OAuthAuthzRequest oauthRequest) {
+ public static boolean isRichAuthorizationRequest(final AuthorizationDetails authorizationDetails) {
- return StringUtils.isNotBlank(oauthRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ return !isEmpty(authorizationDetails);
}
/**
- * Determines if the given {@link CarbonOAuthTokenRequest} object contains {@code authorization_details}.
+ * Determines if the provided {@link AuthorizationDetails} object is empty or not.
+ *
+ * This method checks if the specified {@link AuthorizationDetails} instance is not {@code null}
+ * and has a non-empty details set.
*
- * @param carbonOAuthTokenRequest The OAuth Token Request to check.
- * @return {@code true} if the OAuth token request contains a non-blank authorization details parameter,
+ * @param authorizationDetails The {@link AuthorizationDetails} to check.
+ * @return {@code true} if the {@link AuthorizationDetails} is not {@code null} and has a non-empty details set,
* {@code false} otherwise.
*/
- public static boolean isRichAuthorizationRequest(final CarbonOAuthTokenRequest carbonOAuthTokenRequest) {
+ public static boolean isEmpty(final AuthorizationDetails authorizationDetails) {
- return StringUtils
- .isNotBlank(carbonOAuthTokenRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
+ return authorizationDetails == null || authorizationDetails.getDetails().isEmpty();
}
/**
- * Determines if the request is a rich authorization request using provided {@link AuthorizationDetails} object.
- *
- * This method checks if the specified {@link AuthorizationDetails} instance is not {@code null}
- * and has a non-empty details set.
+ * Determines if the given {@link OAuthAuthzRequest} object contains {@code authorization_details}.
*
- * @param authorizationDetails The {@link AuthorizationDetails} to check.
- * @return {@code true} if the {@link AuthorizationDetails} is not {@code null} and has a non-empty details set,
+ * @param oauthRequest The OAuth Authorization Request to check.
+ * @return {@code true} if the OAuth authorization request contains a non-blank authorization details parameter,
* {@code false} otherwise.
*/
- public static boolean isRichAuthorizationRequest(final AuthorizationDetails authorizationDetails) {
+ public static boolean isRichAuthorizationRequest(final OAuthAuthzRequest oauthRequest) {
- return authorizationDetails != null && !authorizationDetails.getDetails().isEmpty();
+ return StringUtils.isNotBlank(oauthRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
}
/**
- * Determines if the given {@link OAuth2Parameters} object contains {@link AuthorizationDetails}.
+ * Determines if the given {@link CarbonOAuthTokenRequest} object contains {@code authorization_details}.
*
- * @param oAuth2Parameters The requested OAuth2Parameters to check.
- * @return {@code true} if the OAuth2Parameters contains non-empty authorization details set,
+ * @param carbonOAuthTokenRequest The OAuth Token Request to check.
+ * @return {@code true} if the OAuth token request contains a non-blank authorization details parameter,
* {@code false} otherwise.
*/
- public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Parameters) {
+ public static boolean isRichAuthorizationRequest(final CarbonOAuthTokenRequest carbonOAuthTokenRequest) {
- return isRichAuthorizationRequest(oAuth2Parameters.getAuthorizationDetails());
+ return StringUtils
+ .isNotBlank(carbonOAuthTokenRequest.getParam(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
}
/**
@@ -121,18 +131,6 @@ public static boolean isRichAuthorizationRequest(final OAuthTokenReqMessageConte
.getOauth2AccessTokenReqDTO().getAuthorizationDetails());
}
- /**
- * Determines if the given {@link OAuth2AuthorizeReqDTO} object contains {@link AuthorizationDetails}.
- *
- * @param oAuth2AuthorizeReqDTO The requested oAuth2AuthorizeReqDTO to check.
- * @return {@code true} if the oAuth2AuthorizeReqDTO contains non-empty authorization details set,
- * {@code false} otherwise.
- */
- public static boolean isRichAuthorizationRequest(final OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO) {
-
- return isRichAuthorizationRequest(oAuth2AuthorizeReqDTO.getAuthorizationDetails());
- }
-
/**
* Retrieves the application resource ID from the client ID.
*
@@ -169,7 +167,7 @@ public static String getIdFromAuthenticatedUser(final AuthenticatedUser authenti
}
/**
- * Generates a list of {@link AuthorizationDetailsConsentDTO} from the provided consent ID,
+ * Generates a set of {@link AuthorizationDetailsConsentDTO} from the provided consent ID,
* authorization details, and tenant ID.
*
* @param consentId The consent ID.
@@ -177,30 +175,48 @@ public static String getIdFromAuthenticatedUser(final AuthenticatedUser authenti
* @param tenantId The tenant ID.
* @return A list of {@link AuthorizationDetailsConsentDTO}.
*/
- public static List getAuthorizationDetailsConsentDTOs(
+ public static Set getAuthorizationDetailsConsentDTOs(
final String consentId, final AuthorizationDetails userConsentedAuthorizationDetails, final int tenantId) {
return userConsentedAuthorizationDetails.stream()
.map(detail -> new AuthorizationDetailsConsentDTO(consentId, detail, true, tenantId))
- .collect(Collectors.toList());
+ .collect(toSet());
}
/**
- * Generates a list of {@link AuthorizationDetailsTokenDTO} from the provided access token and
+ * Generates a set of {@link AuthorizationDetailsTokenDTO} from the provided access token and
* authorization details.
*
* @param accessTokenDO The access token data object.
* @param authorizationDetails The user-consented authorization details.
* @return A list of {@link AuthorizationDetailsTokenDTO}.
*/
- public static List getAccessTokenAuthorizationDetailsDTOs(
+ public static Set getAccessTokenAuthorizationDetailsDTOs(
final AccessTokenDO accessTokenDO, final AuthorizationDetails authorizationDetails) {
return authorizationDetails
.stream()
.map(authorizationDetail -> new AuthorizationDetailsTokenDTO(
accessTokenDO.getTokenId(), authorizationDetail, accessTokenDO.getTenantID()))
- .collect(Collectors.toList());
+ .collect(toSet());
+ }
+
+ /**
+ * Generates a set of {@link AuthorizationDetailsCodeDTO} from the provided access token and
+ * authorization details.
+ *
+ * @param authzCodeDO The authorization code data object.
+ * @param authorizationDetails The user-consented authorization details.
+ * @return A list of {@link AuthorizationDetailsTokenDTO}.
+ */
+ public static Set getCodeAuthorizationDetailsDTOs(
+ final AuthzCodeDO authzCodeDO, final AuthorizationDetails authorizationDetails, final int tenantId) {
+
+ return authorizationDetails
+ .stream()
+ .map(authorizationDetail ->
+ new AuthorizationDetailsCodeDTO(authzCodeDO.getAuthzCodeId(), authorizationDetail, tenantId))
+ .collect(toSet());
}
/**
@@ -222,16 +238,31 @@ public static AuthorizationDetails extractAuthorizationDetailsFromRequest(
final Set consentedAuthorizationDetailIDs = httpServletRequest.getParameterMap().keySet().stream()
.filter(parameterName -> parameterName.startsWith(AUTHORIZATION_DETAILS_ID_PREFIX))
.map(parameterName -> parameterName.substring(AUTHORIZATION_DETAILS_ID_PREFIX.length()))
- .collect(Collectors.toSet());
+ .collect(toSet());
// Filter and collect the consented authorization details
- final Set consentedAuthorizationDetails = oAuth2Parameters.getAuthorizationDetails()
+ final AuthorizationDetails consentedAuthorizationDetails = new AuthorizationDetails(oAuth2Parameters
+ .getAuthorizationDetails()
.stream()
.filter(authorizationDetail -> consentedAuthorizationDetailIDs.contains(authorizationDetail.getId()))
- .collect(Collectors.toSet());
+ .collect(toSet()));
log.debug("User consented authorization details extracted successfully.");
- return new AuthorizationDetails(consentedAuthorizationDetails);
+
+ oAuth2Parameters.setAuthorizationDetails(consentedAuthorizationDetails);
+ return consentedAuthorizationDetails;
+ }
+
+ /**
+ * Determines if the given {@link OAuth2Parameters} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuth2Parameters The requested OAuth2Parameters to check.
+ * @return {@code true} if the OAuth2Parameters contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Parameters) {
+
+ return isRichAuthorizationRequest(oAuth2Parameters.getAuthorizationDetails());
}
/**
@@ -251,7 +282,7 @@ public static AuthorizationDetails getDisplayableAuthorizationDetails(
authorizationDetail.setId(protectedAuthorizationDetail.getId());
authorizationDetail.setConsentDescription(protectedAuthorizationDetail.getConsentDescription());
return authorizationDetail;
- }).collect(Collectors.toSet());
+ }).collect(toSet());
return new AuthorizationDetails(displayableAuthorizationDetails);
}
@@ -352,6 +383,34 @@ public static void setRARPropertiesToAuthzRequestContext(
IdentityTenantUtil.getTenantId(oAuth2AuthorizeReqDTO.getTenantDomain())
);
- oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
+ if (authorizationDetails != null) {
+ oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
+ }
+ }
+
+ /**
+ * Determines if the given {@link OAuth2AuthorizeReqDTO} object contains {@link AuthorizationDetails}.
+ *
+ * @param oAuth2AuthorizeReqDTO The requested oAuth2AuthorizeReqDTO to check.
+ * @return {@code true} if the oAuth2AuthorizeReqDTO contains non-empty authorization details set,
+ * {@code false} otherwise.
+ */
+ public static boolean isRichAuthorizationRequest(final OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO) {
+
+ return isRichAuthorizationRequest(oAuth2AuthorizeReqDTO.getAuthorizationDetails());
+ }
+
+ /**
+ * Converts a list of AuthorizationDetails into a map with the type as the key.
+ *
+ * @param authorizationDetails {@link AuthorizationDetails} instance to be converted.
+ * @return A map where the key is the type and the value is the corresponding AuthorizationDetails object.
+ */
+ public static Map> getAuthorizationDetailsTypesMap(
+ final AuthorizationDetails authorizationDetails) {
+
+ return authorizationDetails == null ? Collections.emptyMap()
+ : authorizationDetails.stream()
+ .collect(groupingBy(AuthorizationDetail::getType, mapping(identity(), toSet())));
}
-}
+}
\ No newline at end of file
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
index 3ea9e29085..809bcfdd49 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
@@ -18,9 +18,13 @@
package org.wso2.carbon.identity.oauth2.rar.validator;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.oauth2.common.message.types.GrantType;
+import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
+import org.wso2.carbon.identity.application.common.model.AuthorizationDetailsType;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
@@ -28,26 +32,32 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsSchemaValidator;
import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
-import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
-import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.TYPE_NOT_SUPPORTED_ERR_FORMAT;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG;
+
/**
* Default implementation class responsible for validating {@link AuthorizationDetails} in different
* OAuth2 message contexts.
@@ -55,23 +65,26 @@
public class DefaultAuthorizationDetailsValidator implements AuthorizationDetailsValidator {
private static final Log log = LogFactory.getLog(DefaultAuthorizationDetailsValidator.class);
- private final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory;
+ private final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory;
private final AuthorizationDetailsService authorizationDetailsService;
+ private final AuthorizationDetailsSchemaValidator authorizationDetailsSchemaValidator;
public DefaultAuthorizationDetailsValidator() {
-
this(
- AuthorizationDetailsProviderFactory.getInstance(),
- OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService()
+ AuthorizationDetailsProcessorFactory.getInstance(),
+ OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsService(),
+ AuthorizationDetailsSchemaValidator.getInstance()
);
}
public DefaultAuthorizationDetailsValidator(
- final AuthorizationDetailsProviderFactory authorizationDetailsProviderFactory,
- final AuthorizationDetailsService authorizationDetailsService) {
+ final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory,
+ final AuthorizationDetailsService authorizationDetailsService,
+ final AuthorizationDetailsSchemaValidator authorizationDetailsSchemaValidator) {
- this.authorizationDetailsProviderFactory = authorizationDetailsProviderFactory;
+ this.authorizationDetailsProcessorFactory = authorizationDetailsProcessorFactory;
this.authorizationDetailsService = authorizationDetailsService;
+ this.authorizationDetailsSchemaValidator = authorizationDetailsSchemaValidator;
}
/**
@@ -83,12 +96,12 @@ public AuthorizationDetails getValidatedAuthorizationDetails(final OAuthAuthzReq
throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
try {
+
return this.getValidatedAuthorizationDetails(
oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getConsumerKey(),
- OAuth2Util.getTenantId(oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain()),
+ oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getTenantDomain(),
oAuthAuthzReqMessageContext.getAuthorizationReqDTO().getAuthorizationDetails(),
- authorizationDetail ->
- new AuthorizationDetailsContext(authorizationDetail, oAuthAuthzReqMessageContext)
+ (detail, type) -> new AuthorizationDetailsContext(detail, type, oAuthAuthzReqMessageContext)
);
} catch (IdentityOAuth2Exception e) {
log.error("Unable find the tenant ID of the domain: " +
@@ -107,29 +120,104 @@ public AuthorizationDetails getValidatedAuthorizationDetails(final OAuthTokenReq
final OAuth2AccessTokenReqDTO accessTokenReqDTO = oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO();
- if (GrantType.AUTHORIZATION_CODE.toString().equals(accessTokenReqDTO.getGrantType())) {
+ if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(accessTokenReqDTO.getAuthorizationDetails())) {
if (log.isDebugEnabled()) {
- log.debug("Skipping the authorization_details validation for authorization code flow " +
- "as this validation has already happened in the authorize flow.");
+ log.debug("Client application does not request new authorization details. " +
+ "Returning previously validated authorization details.");
}
return oAuthTokenReqMessageContext.getAuthorizationDetails();
}
- if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(accessTokenReqDTO.getAuthorizationDetails())) {
+ if (GrantType.AUTHORIZATION_CODE.toString().equals(accessTokenReqDTO.getGrantType())) {
if (log.isDebugEnabled()) {
- log.debug("Client application does not request new authorization details. " +
- "Returning previously validated authorization details.");
-
+ log.debug("Skipping the authorization_details validation for authorization code flow " +
+ "as this validation has already happened in the authorize flow.");
}
return oAuthTokenReqMessageContext.getAuthorizationDetails();
}
- return this.getValidatedAuthorizationDetails(
+ final AuthorizationDetails validatedAuthorizationDetails = this.getValidatedAuthorizationDetails(
accessTokenReqDTO.getClientId(),
- oAuthTokenReqMessageContext.getTenantID(),
+ accessTokenReqDTO.getTenantDomain(),
accessTokenReqDTO.getAuthorizationDetails(),
- authorizationDetail -> new AuthorizationDetailsContext(authorizationDetail, oAuthTokenReqMessageContext)
+ (detail, type) -> new AuthorizationDetailsContext(detail, type, oAuthTokenReqMessageContext)
);
+
+ if (GrantType.REFRESH_TOKEN.toString().equals(accessTokenReqDTO.getGrantType())) {
+ return new AuthorizationDetails(this.filterConsentedAuthorizationDetails(validatedAuthorizationDetails,
+ oAuthTokenReqMessageContext.getAuthorizationDetails()));
+ }
+
+ return validatedAuthorizationDetails;
+ }
+
+ /**
+ * Validates whether the user has consented to the requested authorization details.
+ *
+ * @param requestedAuthorizationDetails The requested authorization details.
+ * @param consentedAuthorizationDetails The consented authorization details.
+ * @throws AuthorizationDetailsProcessingException If validation fails.
+ */
+ private Set filterConsentedAuthorizationDetails(
+ final AuthorizationDetails requestedAuthorizationDetails,
+ final AuthorizationDetails consentedAuthorizationDetails)
+ throws AuthorizationDetailsProcessingException {
+
+ final Set validAuthorizationDetails = new HashSet<>();
+ if (AuthorizationDetailsUtils.isEmpty(requestedAuthorizationDetails)) {
+ log.debug("No authorization details requested. Using all consented authorization details.");
+ validAuthorizationDetails.addAll(consentedAuthorizationDetails.getDetails());
+ return validAuthorizationDetails;
+ }
+
+ if (AuthorizationDetailsUtils.isEmpty(consentedAuthorizationDetails)) {
+ log.debug("Invalid request. No consented authorization details found.");
+ throw new AuthorizationDetailsProcessingException(VALIDATION_FAILED_ERR_MSG);
+ }
+
+ // Map consented authorization details by type for quick lookup
+ final Map> consentedAuthorizationDetailsByType =
+ AuthorizationDetailsUtils.getAuthorizationDetailsTypesMap(consentedAuthorizationDetails);
+
+ for (AuthorizationDetail requestedAuthorizationDetail : requestedAuthorizationDetails.getDetails()) {
+
+ final String requestedType = requestedAuthorizationDetail.getType();
+ if (!consentedAuthorizationDetailsByType.containsKey(requestedType)) {
+ if (log.isDebugEnabled()) {
+ log.debug("User hasn't consented to the requested authorization details type: " + requestedType);
+ }
+ throw new AuthorizationDetailsProcessingException(VALIDATION_FAILED_ERR_MSG);
+ }
+
+ final Optional optProcessor =
+ this.authorizationDetailsProcessorFactory.getAuthorizationDetailsProcessorByType(requestedType);
+
+ if (optProcessor.isPresent()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Validating equality of requested and existing authorization details using processor: "
+ + optProcessor.get().getClass().getSimpleName());
+ }
+ final AuthorizationDetails existingAuthorizationDetails =
+ new AuthorizationDetails(consentedAuthorizationDetailsByType.get(requestedType));
+
+ // If the requested authorization details match the consented ones, add to the valid set
+ if (optProcessor.get().isEqualOrSubset(requestedAuthorizationDetail, existingAuthorizationDetails)) {
+ validAuthorizationDetails.add(requestedAuthorizationDetail);
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("User hasn't consented to requested authorization details type: " + requestedType);
+ }
+ throw new AuthorizationDetailsProcessingException(VALIDATION_FAILED_ERR_MSG);
+ }
+ } else {
+ // Cannot process, returning all consented authorization details
+ if (CollectionUtils.isNotEmpty(consentedAuthorizationDetailsByType.get(requestedType))) {
+ validAuthorizationDetails.addAll(consentedAuthorizationDetailsByType.get(requestedType));
+ }
+ consentedAuthorizationDetailsByType.put(requestedType, Collections.emptySet());
+ }
+ }
+ return validAuthorizationDetails;
}
/**
@@ -149,9 +237,9 @@ public AuthorizationDetails getValidatedAuthorizationDetails(
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(accessTokenAuthorizationDetails)) {
final Set authorizedAuthorizationDetails =
- this.getAuthorizedAuthorizationDetails(
+ this.getValidatedAuthorizationDetails(
accessTokenDO.getConsumerKey(),
- accessTokenDO.getTenantID(),
+ IdentityTenantUtil.getTenantDomain(accessTokenDO.getTenantID()),
accessTokenAuthorizationDetails);
return new AuthorizationDetails(authorizedAuthorizationDetails);
}
@@ -162,59 +250,92 @@ public AuthorizationDetails getValidatedAuthorizationDetails(
return new AuthorizationDetails();
}
+ private Set getValidatedAuthorizationDetails(
+ final String clientId, final String tenantDomain, final AuthorizationDetails authorizationDetails)
+ throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+
+ return this.getSchemaCompliantAuthorizationDetails(authorizationDetails,
+ this.getAuthorizedAuthorizationDetailsTypes(clientId, tenantDomain));
+ }
+
/**
* Validates the authorization details for OAuthTokenReqMessageContext.
*
* @param clientId The client ID.
- * @param tenantId The tenant ID.
+ * @param tenantDomain The tenant domain.
* @param authorizationDetails The set of authorization details to validate.
* @param contextProvider A lambda function to create the AuthorizationDetailsContext.
* @return An {@link AuthorizationDetails} object containing the validated authorization details.
* @throws AuthorizationDetailsProcessingException if validation fails.
*/
private AuthorizationDetails getValidatedAuthorizationDetails(
- final String clientId, final int tenantId, final AuthorizationDetails authorizationDetails,
- final Function contextProvider)
+ final String clientId, final String tenantDomain, final AuthorizationDetails authorizationDetails,
+ BiFunction contextProvider)
throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
+ final Map authorizedDetailsTypes =
+ this.getAuthorizedAuthorizationDetailsTypes(clientId, tenantDomain);
+
final Set validatedAuthorizationDetails = new HashSet<>();
for (final AuthorizationDetail authorizationDetail :
- this.getAuthorizedAuthorizationDetails(clientId, tenantId, authorizationDetails)) {
+ this.getSchemaCompliantAuthorizationDetails(authorizationDetails, authorizedDetailsTypes)) {
- if (!isSupportedAuthorizationDetailType(authorizationDetail.getType())) {
- throw new AuthorizationDetailsProcessingException(String.format(AuthorizationDetailsConstants
- .TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT, authorizationDetail.getType()));
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Validation started for authorization detail of type: " + authorizationDetail.getType());
- }
-
- final AuthorizationDetailsContext authorizationDetailsContext = contextProvider.apply(authorizationDetail);
+ final AuthorizationDetailsContext authorizationDetailsContext = contextProvider
+ .apply(authorizationDetail, authorizedDetailsTypes.get(authorizationDetail.getType()));
if (this.isValidAuthorizationDetail(authorizationDetailsContext)) {
- validatedAuthorizationDetails.add(getEnrichedAuthorizationDetail(authorizationDetailsContext));
+ validatedAuthorizationDetails.add(this.getEnrichedAuthorizationDetail(authorizationDetailsContext));
}
}
-
return new AuthorizationDetails(validatedAuthorizationDetails);
}
- private Set getAuthorizedAuthorizationDetails(
- final String clientId, final int tenantId, final AuthorizationDetails authorizationDetails) {
+ /**
+ * Retrieves the set of authorized authorization types for the given client and tenant domain.
+ *
+ * @param clientId The client ID.
+ * @param tenantDomain The tenant domain.
+ * @return A set of strings representing the authorized authorization types.
+ */
+ private Map getAuthorizedAuthorizationDetailsTypes(final String clientId,
+ final String tenantDomain)
+ throws IdentityOAuth2ServerException {
- final Set authorizedAuthorizationDetailsTypes =
- this.getAuthorizedAuthorizationDetailsTypes(clientId, tenantId);
+ try {
+ final String appId = AuthorizationDetailsUtils.getApplicationResourceIdFromClientId(clientId);
+ final List authorizationDetailsTypes = OAuth2ServiceComponentHolder.getInstance()
+ .getAuthorizedAPIManagementService().getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
- return authorizationDetails.stream()
- .filter(authorizationDetail ->
- authorizedAuthorizationDetailsTypes.contains(authorizationDetail.getType()))
- .collect(Collectors.toSet());
+ if (CollectionUtils.isEmpty(authorizationDetailsTypes)) {
+ return Collections.emptyMap();
+ }
+ return authorizationDetailsTypes.stream()
+ .collect(Collectors.toMap(AuthorizationDetailsType::getType, Function.identity()));
+ } catch (IdentityOAuth2Exception | IdentityApplicationManagementException e) {
+ log.error("Unable to retrieve authorized authorization details types. Caused by, ", e);
+ throw new IdentityOAuth2ServerException("Unable to retrieve authorized authorization details types", e);
+ }
}
- private boolean isSupportedAuthorizationDetailType(final String authorizationDetailType) {
+ private Set getSchemaCompliantAuthorizationDetails(
+ final AuthorizationDetails authorizationDetails,
+ final Map authorizedDetailsTypes)
+ throws AuthorizationDetailsProcessingException {
+
+ final Set schemaCompliantAuthorizationDetails = new HashSet<>();
+ for (final AuthorizationDetail authorizationDetail : authorizationDetails.getDetails()) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Schema validation started for authorization details type: " + authorizationDetail.getType());
+ }
+
+ this.assertAuthorizationDetailTypeSupported(authorizationDetail.getType());
- return this.authorizationDetailsProviderFactory.isSupportedAuthorizationDetailsType(authorizationDetailType);
+ if (this.isSchemaCompliant(authorizationDetail.getType(), authorizationDetail, authorizedDetailsTypes)) {
+ schemaCompliantAuthorizationDetails.add(authorizationDetail);
+ }
+ }
+ return schemaCompliantAuthorizationDetails;
}
/**
@@ -226,23 +347,26 @@ private boolean isSupportedAuthorizationDetailType(final String authorizationDet
private boolean isValidAuthorizationDetail(final AuthorizationDetailsContext authorizationDetailsContext)
throws AuthorizationDetailsProcessingException, IdentityOAuth2ServerException {
- Optional optionalProvider = this.authorizationDetailsProviderFactory
- .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType());
+ final String type = authorizationDetailsContext.getAuthorizationDetail().getType();
+ final Optional optProcessor =
+ this.authorizationDetailsProcessorFactory.getAuthorizationDetailsProcessorByType(type);
- if (optionalProvider.isPresent()) {
-
- final ValidationResult validationResult = optionalProvider.get().validate(authorizationDetailsContext);
- if (log.isDebugEnabled() && validationResult.isInvalid()) {
-
- log.debug(String.format("Authorization details validation failed for type %s. Caused by, %s",
- authorizationDetailsContext.getAuthorizationDetail().getType(), validationResult.getReason()));
+ if (optProcessor.isPresent()) {
+ final ValidationResult validationResult = optProcessor.get().validate(authorizationDetailsContext);
+ if (validationResult.isInvalid()) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Authorization details validation failed for type: %s. Caused by, %s",
+ type, validationResult.getReason()));
+ }
+ return false;
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("An authorization details processor implementation is not found for type: " + type);
}
- return validationResult.isValid();
}
- throw new AuthorizationDetailsProcessingException(String.format(
- AuthorizationDetailsConstants.TYPE_NOT_SUPPORTED_ERR_MSG_FORMAT,
- authorizationDetailsContext.getAuthorizationDetail().getType()));
+ return true;
}
/**
@@ -254,35 +378,40 @@ private boolean isValidAuthorizationDetail(final AuthorizationDetailsContext aut
private AuthorizationDetail getEnrichedAuthorizationDetail(
final AuthorizationDetailsContext authorizationDetailsContext) {
- return this.authorizationDetailsProviderFactory
- .getProviderByType(authorizationDetailsContext.getAuthorizationDetail().getType())
+ return this.authorizationDetailsProcessorFactory
+ .getAuthorizationDetailsProcessorByType(authorizationDetailsContext.getAuthorizationDetail().getType())
.map(authorizationDetailsProcessor -> authorizationDetailsProcessor.enrich(authorizationDetailsContext))
// If provider is missing, return the original authorization detail instance
.orElse(authorizationDetailsContext.getAuthorizationDetail());
}
- /**
- * Retrieves the set of authorized authorization types for the given client and tenant domain.
- *
- * @param clientId The client ID.
- * @param tenantId The tenant ID.
- * @return A set of strings representing the authorized authorization types.
- */
- private Set getAuthorizedAuthorizationDetailsTypes(final String clientId, final int tenantId) {
-
-// try {
-// final String appId = OAuth2Util
-// .getApplicationResourceIDByClientId(clientID, tenantDomain, this.applicationMgtService);
-//
-//// OAuth2ServiceComponentHolder.getInstance().getAuthorizedAPIManagementService()
-// .getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
-// } catch (IdentityOAuth2Exception e) {
-// throw new RuntimeException(e);
-// }
- Set authorizedAuthorizationDetailsTypes = new HashSet<>();
- authorizedAuthorizationDetailsTypes.add("payment_initiation");
- return authorizedAuthorizationDetailsTypes;
+ private void assertAuthorizationDetailTypeSupported(final String type)
+ throws AuthorizationDetailsProcessingException {
+
+ if (!this.authorizationDetailsProcessorFactory.isSupportedAuthorizationDetailsType(type)) {
+ throw new AuthorizationDetailsProcessingException(String.format(TYPE_NOT_SUPPORTED_ERR_FORMAT, type));
+ }
}
+ private boolean isSchemaCompliant(final String type, final AuthorizationDetail authorizationDetail,
+ final Map authorizedDetailsTypes)
+ throws AuthorizationDetailsProcessingException {
+
+ if (!authorizedDetailsTypes.containsKey(type)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Ignoring unauthorized authorization details type: " + type);
+ }
+ return false;
+ }
+ if (this.authorizationDetailsSchemaValidator
+ .isSchemaCompliant(authorizedDetailsTypes.get(type).getSchema(), authorizationDetail)) {
+ return true;
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Ignoring non-schema-compliant authorization details type: " + type);
+ }
+ return false;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
index 323160f2c4..9321ba42a0 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
@@ -1240,18 +1240,41 @@ private boolean isFederatedUser(OAuthTokenReqMessageContext tokReqMsgCtx) {
return tokReqMsgCtx.getAuthorizedUser().isFederatedUser();
}
+ /**
+ * Sets the Rich Authorization Requests (RAR) properties for token generation.
+ * It retrieves the user-consented authorization details or fallback to code authorization details
+ * based on the provided OAuth token request context.
+ *
+ * @param oAuthTokenReqMessageContext Context of the OAuth token request message.
+ * @throws IdentityOAuth2Exception If an error occurs while retrieving authorization details.
+ */
protected void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
throws IdentityOAuth2Exception {
- final int tenantId = OAuth2Util
- .getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
+ final int tenantId =
+ OAuth2Util.getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
+
+ if (log.isDebugEnabled()) {
+ log.debug("Retrieving user consented authorization details for user: "
+ + oAuthTokenReqMessageContext.getAuthorizedUser().getLoggableMaskedUserId());
+ }
- final AuthorizationDetails userConsentedAuthorizationDetails =
- this.authorizationDetailsService.getUserConsentedAuthorizationDetails(
+ AuthorizationDetails authorizationDetails = this.authorizationDetailsService
+ .getUserConsentedAuthorizationDetails(
oAuthTokenReqMessageContext.getAuthorizedUser(),
oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId(),
tenantId);
- oAuthTokenReqMessageContext.setAuthorizationDetails(userConsentedAuthorizationDetails);
+ // Fallback to code authorization details if user consent is unavailable
+ if (authorizationDetails == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("No user consent is available. Fetching authorization details for code: " +
+ oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode());
+ }
+
+ authorizationDetails = this.authorizationDetailsService.getAuthorizationCodeAuthorizationDetails(
+ oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode(), tenantId);
+ }
+ oAuthTokenReqMessageContext.setAuthorizationDetails(authorizationDetails);
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
index 4c72935ff5..143ee3fb9a 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -11,20 +11,26 @@
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.common.testng.WithCarbonHome;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
import org.wso2.carbon.identity.oauth2.rar.dao.AuthorizationDetailsDAO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
+import org.wso2.carbon.identity.oauth2.rar.model.ValidationResult;
import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import java.sql.SQLException;
import java.util.Collections;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
@@ -32,12 +38,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertNull;
import static org.wso2.carbon.identity.oauth2.TestConstants.ACESS_TOKEN_ID;
import static org.wso2.carbon.identity.oauth2.TestConstants.CLIENT_ID;
import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_DOMAIN;
@@ -78,7 +86,8 @@ public void tearDown() {
}
@BeforeMethod()
- public void setUpMethod() throws SQLException {
+ public void setUpMethod()
+ throws SQLException, IdentityOAuth2ServerException, AuthorizationDetailsProcessingException {
this.authorizationDetailsDAOMock = Mockito.mock(AuthorizationDetailsDAO.class);
when(this.authorizationDetailsDAOMock.getConsentIdByUserIdAndAppId(TEST_USER_ID, TEST_APP_ID, TENANT_ID))
@@ -92,13 +101,23 @@ public void setUpMethod() throws SQLException {
.thenReturn(Collections.singleton(new AuthorizationDetailsTokenDTO(ACESS_TOKEN_ID,
this.authorizationDetail, TENANT_ID)));
- uut = new AuthorizationDetailsService(this.providerFactoryMock, this.authorizationDetailsDAOMock);
+ AuthorizationDetailsProcessor processor = Mockito.mock(AuthorizationDetailsProcessor.class);
+ when(processor.isEqualOrSubset(any(AuthorizationDetail.class), any(AuthorizationDetails.class)))
+ .thenReturn(true);
+ when(processor.enrich(any(AuthorizationDetailsContext.class))).thenReturn(this.authorizationDetail);
+ when(processor.getType()).thenReturn(TEST_TYPE);
+ when(processor.validate(any(AuthorizationDetailsContext.class))).thenReturn(ValidationResult.valid());
+
+ when(this.processorFactoryMock.getAuthorizationDetailsProcessorByType(TEST_TYPE))
+ .thenReturn(Optional.of(processor));
+
+ uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock);
}
@BeforeMethod(onlyForGroups = {"error-flow-tests"}, dependsOnMethods = {"setUpMethod"})
public void setUpErrorMethod() throws SQLException {
- when(this.authorizationDetailsDAOMock.addUserConsentedAuthorizationDetails(anyList()))
+ when(this.authorizationDetailsDAOMock.addUserConsentedAuthorizationDetails(anySet()))
.thenThrow(SQLException.class);
when(this.authorizationDetailsDAOMock.deleteUserConsentedAuthorizationDetails(anyString(), anyInt()))
.thenThrow(SQLException.class);
@@ -106,12 +125,12 @@ public void setUpErrorMethod() throws SQLException {
.thenThrow(SQLException.class);
when(this.authorizationDetailsDAOMock.getAccessTokenAuthorizationDetails(anyString(), anyInt()))
.thenThrow(SQLException.class);
- when(this.authorizationDetailsDAOMock.addAccessTokenAuthorizationDetails(anyList()))
+ when(this.authorizationDetailsDAOMock.addAccessTokenAuthorizationDetails(anySet()))
.thenThrow(SQLException.class);
when(this.authorizationDetailsDAOMock.deleteAccessTokenAuthorizationDetails(anyString(), anyInt()))
.thenThrow(SQLException.class);
- uut = new AuthorizationDetailsService(this.providerFactoryMock, this.authorizationDetailsDAOMock);
+ uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock);
}
@Test
@@ -121,7 +140,7 @@ public void shouldNotAddUserConsentedAuthorizationDetails_ifNotRichAuthorization
uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
new OAuth2Parameters(), authorizationDetails);
- verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anySet());
}
@Test
@@ -134,7 +153,7 @@ public void shouldNotAddUserConsentedAuthorizationDetails_whenConsentIsNotFound(
uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
- verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anySet());
}
@Test
@@ -144,7 +163,7 @@ public void shouldAddUserConsentedAuthorizationDetails_ifRichAuthorizationReques
uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
- verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anySet());
}
@Test
@@ -186,7 +205,7 @@ public void shouldReplaceUserConsentedAuthorizationDetails_ifRichAuthorizationRe
verify(authorizationDetailsDAOMock, times(1))
.deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID);
- verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anySet());
}
@Test
@@ -202,13 +221,12 @@ public void shouldReturnFalse_ifAuthorizationDetailsAlreadyConsented() throws Id
}
@Test
- public void shouldReturnEmptyAuthorizationDetails_whenConsentIsInvalid() throws IdentityOAuth2Exception {
+ public void shouldReturnNull_whenConsentIsInvalid() throws IdentityOAuth2Exception {
AuthenticatedUser invalidUser = new AuthenticatedUser();
invalidUser.setUserId("invalid-user-id");
- assertTrue(uut.getUserConsentedAuthorizationDetails(invalidUser, CLIENT_ID, TENANT_ID)
- .getDetails().isEmpty());
+ assertNull(uut.getUserConsentedAuthorizationDetails(invalidUser, CLIENT_ID, TENANT_ID));
}
@Test
@@ -249,7 +267,7 @@ public void shouldNotAddAccessTokenAuthorizationDetails_ifNotRichAuthorizationRe
uut.storeAccessTokenAuthorizationDetails(accessTokenDO, new OAuthAuthzReqMessageContext(null));
- verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anySet());
}
@Test
@@ -261,7 +279,7 @@ public void shouldAddAccessTokenAuthorizationDetails_ifRichAuthorizationRequest(
uut.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthAuthzReqMessageContext);
- verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anySet());
}
@Test
@@ -271,7 +289,7 @@ public void shouldNotReplaceAccessTokenAuthorizationDetails_ifNotRichAuthorizati
uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, accessTokenDO,
new OAuthTokenReqMessageContext(new OAuth2AccessTokenReqDTO()));
- verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anySet());
verify(authorizationDetailsDAOMock, times(0)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
}
@@ -284,7 +302,7 @@ public void shouldNotDeleteAccessTokenAuthorizationDetails_whenOldAccessTokenIsM
uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, null, messageContext);
- verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anySet());
verify(authorizationDetailsDAOMock, times(0)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
}
@@ -297,7 +315,7 @@ public void shouldReplaceAccessTokenAuthorizationDetails_whenOldAccessTokenIsPre
uut.storeOrReplaceAccessTokenAuthorizationDetails(accessTokenDO, accessTokenDO, messageContext);
- verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anySet());
verify(authorizationDetailsDAOMock, times(1)).deleteAccessTokenAuthorizationDetails(anyString(), anyInt());
}
@@ -313,7 +331,7 @@ public void shouldReplaceAccessTokenAuthorizationDetails_ifRichAuthorizationRequ
verify(authorizationDetailsDAOMock, times(1))
.deleteAccessTokenAuthorizationDetails(oldAccessTokenId, TENANT_ID);
- verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anyList());
+ verify(authorizationDetailsDAOMock, times(1)).addAccessTokenAuthorizationDetails(anySet());
}
@Test
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
index c5bcda4332..ec9f84b1d0 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
@@ -10,6 +10,7 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
@@ -36,7 +37,7 @@ public class IntrospectionRARDataProviderTest extends AuthorizationDetailsBaseTe
private IntrospectionRARDataProvider uut;
@BeforeClass
- public void setUpClass() throws IdentityOAuth2Exception {
+ public void setUpClass() throws IdentityOAuth2Exception, AuthorizationDetailsProcessingException {
this.validatorMock = Mockito.mock(AuthorizationDetailsValidator.class);
when(validatorMock.getValidatedAuthorizationDetails(any(OAuth2TokenValidationMessageContext.class)))
@@ -55,7 +56,7 @@ public void setUpClass() throws IdentityOAuth2Exception {
@Test(priority = 1)
public void shouldNotReturnAuthorizationDetails_ifNotRichAuthorizationRequest()
- throws IdentityOAuth2Exception {
+ throws IdentityOAuth2Exception, AuthorizationDetailsProcessingException {
when(validatorMock.getValidatedAuthorizationDetails(any(OAuth2TokenValidationMessageContext.class)))
.thenReturn(new AuthorizationDetails());
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
index 5108f23f0a..7159bda1be 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
@@ -8,9 +8,10 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsSchemaValidator;
import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
-import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProviderFactory;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants;
@@ -49,9 +50,11 @@ public class AuthorizationDetailsBaseTest {
protected AccessTokenDO accessTokenDO;
protected OAuth2AccessTokenReqDTO accessTokenReqDTO;
- protected AuthorizationDetailsProviderFactory providerFactoryMock;
+ protected AuthorizationDetailsProcessorFactory processorFactoryMock;
protected AuthorizationDetailsService serviceMock;
+ protected AuthorizationDetailsSchemaValidator schemaValidatorMock;
+
public AuthorizationDetailsBaseTest() {
this.authorizationDetail = new AuthorizationDetail();
@@ -95,6 +98,8 @@ public AuthorizationDetailsBaseTest() {
mockAuthorizationDetailsProviderFactory();
this.serviceMock = mock(AuthorizationDetailsService.class);
+
+ this.schemaValidatorMock = spy(AuthorizationDetailsSchemaValidator.class);
}
public static void assertAuthorizationDetailsPresent(final Map attributes) {
@@ -111,13 +116,13 @@ public static void assertAuthorizationDetailsMissing(final Map a
private void mockAuthorizationDetailsProviderFactory() {
- this.providerFactoryMock = spy(AuthorizationDetailsProviderFactory.class);
+ this.processorFactoryMock = spy(AuthorizationDetailsProcessorFactory.class);
try {
- Field privateField = AuthorizationDetailsProviderFactory.class
- .getDeclaredField("supportedAuthorizationDetailsTypes");
+ Field privateField = AuthorizationDetailsProcessorFactory.class
+ .getDeclaredField("authorizationDetailsProcessors");
privateField.setAccessible(true);
- privateField.set(this.providerFactoryMock, new HashMap() {{
+ privateField.set(this.processorFactoryMock, new HashMap() {{
put(TEST_TYPE, getAuthorizationDetailsProcessorMock());
}});
} catch (Exception e) {
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
index 6b14dc1bf7..2849f2976b 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
@@ -24,7 +24,7 @@ public void setUp() throws IdentityOAuth2Exception {
when(serviceMock.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID))
.thenReturn(authorizationDetails);
- this.uut = new DefaultAuthorizationDetailsValidator(providerFactoryMock, serviceMock);
+ this.uut = new DefaultAuthorizationDetailsValidator(processorFactoryMock, serviceMock, schemaValidatorMock);
}
@Test
diff --git a/pom.xml b/pom.xml
index e8930fc7c1..fad419f78c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -413,6 +413,12 @@
auto-service
${com.google.auto.service.version}
+
+
+ io.vertx
+ vertx-json-schema
+ ${vertx.json.schema.version}
+
@@ -561,6 +567,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.oauth.rar
+ provided
${project.version}
@@ -1011,6 +1018,7 @@
5.2
9.2
1.1.1
+ 4.5.10
5.1.2
From c3c9fe9d7ae63309b8a082082b366de6a788eef6 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Wed, 9 Oct 2024 10:08:00 +0530
Subject: [PATCH 06/28] Add unit tests to discovery endpoint
---
.../builders/ProviderConfigBuilderTest.java | 27 +++++++++-------
.../pom.xml | 31 +++----------------
.../dao/AuthorizationDetailsDAOImplTest.java | 3 ++
.../AuthorizationDetailsCommonUtilsTest.java | 1 -
.../org.wso2.carbon.identity.oauth/pom.xml | 2 ++
.../rar/util/AuthorizationDetailsUtils.java | 3 +-
pom.xml | 2 +-
7 files changed, 26 insertions(+), 43 deletions(-)
diff --git a/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java b/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
index c4aa460249..f5f14813a8 100644
--- a/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
+++ b/components/org.wso2.carbon.identity.discovery/src/test/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilderTest.java
@@ -42,11 +42,12 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.List;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.spy;
@@ -69,9 +70,6 @@ public class ProviderConfigBuilderTest {
@Mock
private OIDProviderRequest mockOidProviderRequest;
-//
-// @Mock
-// private AuthorizationDetailsProcessorFactory mockAuthorizationDetailsProcessorFactory;
@BeforeMethod
public void setUp() throws Exception {
@@ -90,7 +88,7 @@ public void testBuildOIDProviderConfig() throws Exception {
oAuthServerConfiguration.when(
OAuthServerConfiguration::getInstance).thenReturn(mockOAuthServerConfiguration);
try (MockedStatic oAuth2Util = mockStatic(OAuth2Util.class);
- MockedStatic factoryMock =
+ MockedStatic factoryMockedStatic =
mockStatic(AuthorizationDetailsProcessorFactory.class)) {
OIDCDiscoveryDataHolder mockOidcDiscoveryDataHolder = spy(new OIDCDiscoveryDataHolder());
@@ -115,12 +113,10 @@ public void testBuildOIDProviderConfig() throws Exception {
when(mockOidProviderRequest.getTenantDomain()).thenReturn(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
- AuthorizationDetailsProcessorFactory processorFactoryMock =
- spy(AuthorizationDetailsProcessorFactory.class);
- when(processorFactoryMock.getSupportedAuthorizationDetailTypes()).thenReturn(new HashSet() {{
- add("test_type");
- }});
- factoryMock.when(AuthorizationDetailsProcessorFactory::getInstance).thenReturn(processorFactoryMock);
+ AuthorizationDetailsProcessorFactory factoryMock = spy(AuthorizationDetailsProcessorFactory.class);
+ doReturn(Collections.emptySet()).when(factoryMock).getSupportedAuthorizationDetailTypes();
+ factoryMockedStatic.when(AuthorizationDetailsProcessorFactory::getInstance).thenReturn(factoryMock);
+
assertNotNull(providerConfigBuilder.buildOIDProviderConfig(mockOidProviderRequest));
}
}
@@ -208,7 +204,9 @@ public void testBuildOIDProviderConfig4() throws Exception {
MockedStatic oidcDiscoveryDataHolder =
mockStatic(OIDCDiscoveryDataHolder.class);
MockedStatic oAuth2Util = mockStatic(OAuth2Util.class);
- MockedStatic discoveryUtil = mockStatic(DiscoveryUtil.class);) {
+ MockedStatic discoveryUtil = mockStatic(DiscoveryUtil.class);
+ MockedStatic factoryMockedStatic =
+ mockStatic(AuthorizationDetailsProcessorFactory.class)) {
OAuthServerConfiguration mockOAuthServerConfiguration = mock(OAuthServerConfiguration.class);
oAuthServerConfiguration.when(
OAuthServerConfiguration::getInstance).thenReturn(mockOAuthServerConfiguration);
@@ -237,9 +235,14 @@ public void testBuildOIDProviderConfig4() throws Exception {
when(mockOidProviderRequest.getTenantDomain()).thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
when(mockOAuthServerConfiguration.getUserInfoJWTSignatureAlgorithm()).thenReturn(idTokenSignatureAlgorithm);
+ AuthorizationDetailsProcessorFactory factoryMock = spy(AuthorizationDetailsProcessorFactory.class);
+ doReturn(Collections.singleton("test_type")).when(factoryMock).getSupportedAuthorizationDetailTypes();
+ factoryMockedStatic.when(AuthorizationDetailsProcessorFactory::getInstance).thenReturn(factoryMock);
+
OIDProviderConfigResponse response = providerConfigBuilder.buildOIDProviderConfig(mockOidProviderRequest);
assertNotNull(response);
assertEquals(response.getIssuer(), dummyIdIssuer);
+ assertEquals(response.getAuthorizationDetailsTypesSupported()[0], "test_type");
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index f9e8deb6bf..ab38e1b73d 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.150-SNAPSHOT
+ 7.0.162-SNAPSHOT
4.0.0
@@ -85,13 +85,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 8
-
-
com.github.spotbugs
@@ -105,6 +98,7 @@
org.apache.maven.plugins
maven-surefire-plugin
+ ${maven.surefire.plugin.version}
src/test/resources/testng.xml
@@ -119,6 +113,7 @@
org.jacoco
jacoco-maven-plugin
+ ${jacoco.version}
@@ -135,31 +130,13 @@
prepare-agent
-
- default-instrument
-
- instrument
-
-
-
- default-restore-instrumented-classes
-
- restore-instrumented-classes
-
-
default-report
- prepare-package
+ verify
report
-
- default-report-integration
-
- report-integration
-
-
default-check
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index cc35612769..fb27e90a4c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -49,6 +49,9 @@
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TOKEN_ID;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
+/**
+ * Test class for {@link AuthorizationDetailsDAO}.
+ */
public class AuthorizationDetailsDAOImplTest {
private MockedStatic identityDatabaseUtilMock;
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
index d556e4e9e2..238be9a7b7 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
@@ -57,7 +57,6 @@ public void setUp() throws JsonProcessingException {
this.objectMapper = AuthorizationDetailsCommonUtils.getDefaultObjectMapper();
this.mockObjectMapper = Mockito.spy(this.objectMapper);
- // mock
doThrow(JsonProcessingException.class)
.when(this.mockObjectMapper).writeValueAsString(any(TestDAOUtils.TestAuthorizationDetail.class));
doThrow(JsonProcessingException.class).when(this.mockObjectMapper).writeValueAsString(any(Set.class));
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 64f746df3b..dd724b1977 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -265,6 +265,8 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.oauth.rar
+ compile
+ 7.0.162-SNAPSHOT
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index 634da17875..ef32dcc622 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -21,7 +21,6 @@
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
-import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetailsContext;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
@@ -413,4 +412,4 @@ public static Map> getAuthorizationDetailsTypes
: authorizationDetails.stream()
.collect(groupingBy(AuthorizationDetail::getType, mapping(identity(), toSet())));
}
-}
\ No newline at end of file
+}
diff --git a/pom.xml b/pom.xml
index 71930900b1..e70893ea39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -950,7 +950,7 @@
[1.0.1, 2.0.0)
- 7.3.62
+ 7.3.75-SNAPSHOT
[5.25.234, 8.0.0)
From 7e5ac327fbda3bf85e82518381964f721da0f371 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 25 Oct 2024 17:00:25 +0530
Subject: [PATCH 07/28] Change schema type to CLOB
---
.../AuthorizationDetailsSchemaValidator.java | 61 ++++++++++++-------
.../rar/dao/AuthorizationDetailsDAOImpl.java | 5 +-
.../identity/oauth2/rar/dao/SQLQueries.java | 22 +++----
.../rar/dto/AuthorizationDetailsDTO.java | 36 ++++++++---
.../oauth2/rar/model/AuthorizationDetail.java | 36 ++++++-----
.../rar/model/AuthorizationDetails.java | 10 +--
.../util/AuthorizationDetailsCommonUtils.java | 40 +++++-------
...thorizationDetailsSchemaValidatorTest.java | 33 ++++++++++
.../dao/AuthorizationDetailsDAOImplTest.java | 4 +-
.../AuthorizationDetailsCommonUtilsTest.java | 48 ++++-----------
.../src/test/resources/dbScripts/h2.sql | 10 +--
.../rar/util/AuthorizationDetailsUtils.java | 20 ++----
.../DefaultAuthorizationDetailsValidator.java | 8 +--
13 files changed, 171 insertions(+), 162 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
index b476f62030..904cc76fe2 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidator.java
@@ -30,12 +30,15 @@
import io.vertx.json.schema.SchemaRepository;
import io.vertx.json.schema.Validator;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import java.util.Map;
+
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.VALIDATION_FAILED_ERR_MSG;
@@ -107,13 +110,15 @@ public boolean isValidSchema(final String schema) throws AuthorizationDetailsPro
return false;
}
- final OutputUnit outputUnit = this.buildOutputUnit(null, this.parseJsonString(schema));
+ final OutputUnit outputUnit = this.buildOutputUnit(null, this.parseJsonObject(schema));
try {
// Validates the schema itself against the DRAFT202012 schema standard
outputUnit.checkValidity();
} catch (JsonSchemaValidationException e) {
- logDebugIfEnabled(String.format("Validation failed against DRAFT202012 schema for input: %s. Caused by, ",
- schema), e);
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Validation failed against DRAFT202012 schema for input: %s. Caused by, ",
+ schema), e);
+ }
throw new AuthorizationDetailsProcessingException(String.format(SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT,
buildSchemaValidationErrorMessage(outputUnit, e)), e);
}
@@ -137,14 +142,16 @@ private OutputUnit buildOutputUnit(final JsonObject jsonSchema, final JsonObject
* @return A {@link JsonObject} created from the input string.
* @throws AuthorizationDetailsProcessingException if the input string is not valid JSON.
*/
- private JsonObject parseJsonString(final String jsonString) throws AuthorizationDetailsProcessingException {
+ private JsonObject parseJsonObject(final String jsonString) throws AuthorizationDetailsProcessingException {
try {
return new JsonObject(jsonString);
} catch (DecodeException e) {
- this.logDebugIfEnabled(String.format("Failed to parse the JSON input: '%s'. Caused by, ", jsonString), e);
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Failed to parse the JSON input: '%s'. Caused by, ", jsonString), e);
+ }
throw new AuthorizationDetailsProcessingException(
- String.format("%s. Invalid Json input received.", VALIDATION_FAILED_ERR_MSG), e);
+ String.format("%s. Invalid JSON input received.", VALIDATION_FAILED_ERR_MSG), e);
}
}
@@ -175,33 +182,45 @@ public boolean isSchemaCompliant(final String schema, final AuthorizationDetail
return false;
}
- final JsonObject jsonSchema = this.parseJsonString(schema);
- jsonSchema.put(ADDITIONAL_PROPERTIES, false); // Ensure no unknown fields are allowed
+ return this.isSchemaCompliant(this.parseJsonObject(schema), authorizationDetail);
+ }
+
+ public boolean isSchemaCompliant(final JsonObject schema, final AuthorizationDetail authorizationDetail)
+ throws AuthorizationDetailsProcessingException {
+
+ if (schema == null || authorizationDetail == null) {
+ log.debug("Schema validation failed. Inputs cannot be null");
+ return false;
+ }
final OutputUnit outputUnit =
- this.buildOutputUnit(jsonSchema, this.parseJsonString(authorizationDetail.toJsonString()));
+ this.buildOutputUnit(schema, this.parseJsonObject(authorizationDetail.toJsonString()));
+
try {
// Validates the authorization detail against the schema
outputUnit.checkValidity();
} catch (JsonSchemaValidationException e) {
- logDebugIfEnabled(String.format("Schema validation failed for authorization details type: %s. Caused by, ",
- authorizationDetail.getType()), e);
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Schema validation failed for authorization details type: %s. Caused by, ",
+ authorizationDetail.getType()), e);
+ }
throw new AuthorizationDetailsProcessingException(String.format(TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT,
- authorizationDetail.getType(), buildSchemaValidationErrorMessage(outputUnit, e)), e);
+ authorizationDetail.getType(), this.buildSchemaValidationErrorMessage(outputUnit, e)), e);
}
return true;
}
- /**
- * Logs a debug message along with the exception if debug logging is enabled.
- *
- * @param message The debug message to log.
- * @param ex The exception to log along with the message.
- */
- private void logDebugIfEnabled(final String message, final Exception ex) {
+ public boolean isSchemaCompliant(final Map schema, final AuthorizationDetail authorizationDetail)
+ throws AuthorizationDetailsProcessingException {
- if (log.isDebugEnabled()) {
- log.debug(message, ex);
+ if (MapUtils.isEmpty(schema) || authorizationDetail == null) {
+ log.debug("Schema validation failed. Inputs cannot be null");
+ return false;
}
+
+ final JsonObject jsonSchema = new JsonObject(schema);
+ jsonSchema.put(ADDITIONAL_PROPERTIES, false); // Ensure no unknown fields are allowed
+
+ return this.isSchemaCompliant(jsonSchema, authorizationDetail);
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index a50f8d5f2c..fc9682292e 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -46,9 +46,8 @@ public int[] addUserConsentedAuthorizationDetails(
final Set authorizationDetailsConsentDTOs) throws SQLException {
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
- PreparedStatement ps = connection.getMetaData().getDatabaseProductName().contains("H2")
- ? connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS_H2)
- : connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+ PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
ps.setString(1, consentDTO.getConsentId());
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
index cc03a89d62..3582c3babf 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
@@ -28,17 +28,13 @@ private SQLQueries() {
// Private constructor to prevent instantiation
}
- public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
- "INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
- "(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
- "VALUES (?, ?, ?," +
- "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ private static final String SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE =
+ "SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE = ? AND TENANT_ID = ?";
- public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS_H2 =
+ public static final String ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
"(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
- "VALUES (?, ? FORMAT JSON, ?," +
- "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ "VALUES (?, ?, ?, (" + SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE + "), ?)";
public static final String GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
@@ -50,8 +46,7 @@ private SQLQueries() {
public static final String ADD_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS " +
"(TOKEN_ID, AUTHORIZATION_DETAILS, TYPE_ID, TENANT_ID) " +
- "VALUES (?, ? FORMAT JSON, " +
- "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ "VALUES (?, ?, (" + SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE + "), ?)";
public static final String DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS =
"DELETE FROM IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS WHERE TOKEN_ID=? AND TENANT_ID=?";
@@ -63,14 +58,13 @@ private SQLQueries() {
public static final String ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS =
"INSERT INTO IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS" +
"(CODE_ID, AUTHORIZATION_DETAILS, TYPE_ID, TENANT_ID) " +
- "VALUES (?, ? FORMAT JSON, " +
- "(SELECT ID FROM AUTHORIZATION_DETAILS_TYPES WHERE TYPE=? AND TENANT_ID=?), ?)";
+ "VALUES (?, ?, (" + SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE + "), ?)";
public static final String GET_OAUTH2_CODE_AUTHORIZATION_DETAILS_BY_CODE =
"SELECT IOAC.CODE_ID, IOACAD.TYPE_ID, IOACAD.AUTHORIZATION_DETAILS " +
- "FROM IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS IOACAD " +
+ "FROM IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS IOACAD " +
"INNER JOIN IDN_OAUTH2_AUTHORIZATION_CODE IOAC ON IOACAD.CODE_ID = IOAC.CODE_ID " +
- "WHERE IOAC.AUTHORIZATION_CODE=? AND IOACAD.TENANT_ID=?";
+ "WHERE IOAC.AUTHORIZATION_CODE=? AND IOACAD.TENANT_ID=?";
public static final String GET_IDN_OAUTH2_USER_CONSENT_CONSENT_ID =
"SELECT CONSENT_ID FROM IDN_OAUTH2_USER_CONSENT WHERE USER_ID=? AND APP_ID=? AND TENANT_ID=?";
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
index 00b705d29e..77b711d377 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dto/AuthorizationDetailsDTO.java
@@ -1,9 +1,26 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.dto;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
-import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils;
-import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.fromJSON;
/**
* Data Transfer Object (DTO) for representing authorization details.
@@ -20,10 +37,10 @@ public class AuthorizationDetailsDTO {
/**
* Constructs an AuthorizationDetailsDTO with all fields.
*
- * @param id the ID of the authorization detail DTO.
- * @param typeId the type ID of the authorization detail.
+ * @param id the ID of the authorization detail DTO.
+ * @param typeId the type ID of the authorization detail.
* @param authorizationDetail the authorization detail object.
- * @param tenantId the tenant ID.
+ * @param tenantId the tenant ID.
*/
public AuthorizationDetailsDTO(final String id, final String typeId, final AuthorizationDetail authorizationDetail,
final int tenantId) {
@@ -37,16 +54,15 @@ public AuthorizationDetailsDTO(final String id, final String typeId, final Autho
/**
* Constructs an AuthorizationDetailsDTO from authorization detail JSON string.
*
- * @param id the ID of the authorization detail DTO.
- * @param typeId the type ID of the authorization detail.
+ * @param id the ID of the authorization detail DTO.
+ * @param typeId the type ID of the authorization detail.
* @param authorizationDetailJson the JSON string of the authorization detail.
- * @param tenantId the tenant ID.
+ * @param tenantId the tenant ID.
*/
public AuthorizationDetailsDTO(final String id, final String typeId, final String authorizationDetailJson,
final int tenantId) {
- this(id, typeId, AuthorizationDetailsCommonUtils
- .fromJSON(authorizationDetailJson, AuthorizationDetail.class, getDefaultObjectMapper()), tenantId);
+ this(id, typeId, fromJSON(authorizationDetailJson, AuthorizationDetail.class), tenantId);
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
index 9d3c87af10..f86599976b 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetail.java
@@ -31,8 +31,6 @@
import java.util.Map;
import java.util.function.Function;
-import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
-
/**
* Represents an individual authorization details object which specifies the authorization requirements for a
* specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
@@ -76,8 +74,6 @@ public class AuthorizationDetail implements Serializable {
private static final long serialVersionUID = -3928636285264078857L;
- @JsonProperty("_id")
- private String id;
private String type;
private List locations;
private List actions;
@@ -86,7 +82,11 @@ public class AuthorizationDetail implements Serializable {
private String identifier;
private List privileges;
private Map details;
- private String consentDescription;
+
+ @JsonProperty("_id")
+ private String id;
+ @JsonProperty("_description")
+ private String description;
/**
* Gets the unique ID of the authorization detail.
@@ -234,7 +234,7 @@ public void setDetails(final Map details) {
public void setDetail(final String key, final Object value) {
if (this.details == null) {
- setDetails(new HashMap<>());
+ this.setDetails(new HashMap<>());
}
this.details.put(key, value);
}
@@ -247,21 +247,21 @@ public void setDetail(final String key, final Object value) {
*
* @return A string representing the consent description of the {@code authorization_details}.
*/
- public String getConsentDescription() {
- return this.consentDescription;
+ public String getDescription() {
+ return this.description;
}
/**
* Sets a human-readable sentence that describes the {@code authorization_details}. This sentence is used to
* display to the user and obtain their consent for the current {@link AuthorizationDetail AuthorizationDetail}.
*
- * @param consentDescription A string representing the description of the authorization detail.
- * This description should be clear and understandable to the user,
- * explaining what they are consenting to.
+ * @param description A string representing the description of the authorization detail.
+ * This description should be clear and understandable to the user,
+ * explaining what they are consenting to.
*/
- public void setConsentDescription(final String consentDescription) {
+ public void setDescription(final String description) {
- this.consentDescription = consentDescription;
+ this.description = description;
}
/**
@@ -286,10 +286,9 @@ public void setConsentDescription(final String consentDescription) {
* @param defaultFunction the Function that provides a default value if the consent description is not present
* @return the consent description if present, otherwise the value from the Function
*/
- public String getConsentDescriptionOrDefault(Function defaultFunction) {
+ public String getDescriptionOrDefault(Function defaultFunction) {
- return StringUtils.isNotEmpty(this.getConsentDescription()) ?
- this.getConsentDescription() : defaultFunction.apply(this);
+ return StringUtils.isNotEmpty(this.getDescription()) ? this.getDescription() : defaultFunction.apply(this);
}
/**
@@ -299,7 +298,7 @@ public String getConsentDescriptionOrDefault(Function toMap() {
- return AuthorizationDetailsCommonUtils.toMap(this, getDefaultObjectMapper());
+ return AuthorizationDetailsCommonUtils.toMap(this);
}
@Override
@@ -323,7 +322,6 @@ public String toString() {
", identifier=" + this.identifier +
", privileges=" + this.privileges +
", details=" + this.details +
- ", consentDescription=" + this.consentDescription +
'}';
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
index 11c16e87fb..df1391e49d 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/model/AuthorizationDetails.java
@@ -31,8 +31,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsCommonUtils.getDefaultObjectMapper;
-
/**
* Represents a set of {@link AuthorizationDetail} objects which specifies the authorization requirements for a
* specific resource type within the {@code authorization_details} request parameter used in OAuth 2.0 flows
@@ -77,8 +75,7 @@ public AuthorizationDetails(final Set authorizationDetails)
*/
public AuthorizationDetails(final String authorizationDetailsJson) {
- this(AuthorizationDetailsCommonUtils.fromJSONArray(
- authorizationDetailsJson, AuthorizationDetail.class, getDefaultObjectMapper()));
+ this(AuthorizationDetailsCommonUtils.fromJSONArray(authorizationDetailsJson, AuthorizationDetail.class));
}
/**
@@ -124,7 +121,7 @@ public Set getDetailsByType(final String type) {
*/
public String toJsonString() {
- return AuthorizationDetailsCommonUtils.toJSON(this.getDetails(), getDefaultObjectMapper());
+ return AuthorizationDetailsCommonUtils.toJSON(this.getDetails());
}
/**
@@ -136,8 +133,7 @@ public String toJsonString() {
public String toReadableText() {
return this.stream()
- .map(authorizationDetail ->
- authorizationDetail.getConsentDescriptionOrDefault(AuthorizationDetail::getType))
+ .map(authorizationDetail -> authorizationDetail.getDescriptionOrDefault(AuthorizationDetail::getType))
.collect(Collectors.joining(AuthorizationDetailsConstants.PARAM_SEPARATOR));
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
index e1e9c3040a..6e2d84090c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtils.java
@@ -45,6 +45,7 @@ public class AuthorizationDetailsCommonUtils {
private static final Log log = LogFactory.getLog(AuthorizationDetailsCommonUtils.class);
private static volatile ObjectMapper objectMapper;
+ private static final TypeReference> TYPE_MAP = new TypeReference>() { };
private AuthorizationDetailsCommonUtils() {
// Private constructor to prevent instantiation
@@ -55,20 +56,19 @@ private AuthorizationDetailsCommonUtils() {
*
* @param authorizationDetailsJson A JSON string containing authorization details which comes in the
* OAuth 2.0 authorization request or token request
- * @param objectMapper A Jackson {@link ObjectMapper} used for parsing
* @param clazz A Class that extends {@link AuthorizationDetail} to be parsed
* @param the type parameter extending {@code AuthorizationDetail}
* @return an immutable set of {@link AuthorizationDetail} objects parsed from the given JSON string,
* or an empty set if parsing fails
* @see AuthorizationDetails
*/
- public static Set fromJSONArray(
- final String authorizationDetailsJson, final Class clazz, final ObjectMapper objectMapper) {
+ public static Set fromJSONArray(final String authorizationDetailsJson,
+ final Class clazz) {
try {
if (StringUtils.isNotEmpty(authorizationDetailsJson)) {
- return objectMapper.readValue(authorizationDetailsJson,
- objectMapper.getTypeFactory().constructCollectionType(Set.class, clazz));
+ return getDefaultObjectMapper().readValue(authorizationDetailsJson,
+ getDefaultObjectMapper().getTypeFactory().constructCollectionType(Set.class, clazz));
}
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing String to AuthorizationDetails. Caused by, ", e);
@@ -80,19 +80,18 @@ public static Set fromJSONArray(
* Parses the given JSON object string into an {@link AuthorizationDetail} object.
*
* @param authorizationDetailJson A JSON string containing authorization detail object
- * @param objectMapper A Jackson {@link ObjectMapper} used for parsing
* @param clazz A Class that extends {@link AuthorizationDetail} to be parsed
* @param the type parameter extending {@code AuthorizationDetail}
* @return an {@link AuthorizationDetail} objects parsed from the given JSON string,
* or null if parsing fails
* @see AuthorizationDetail
*/
- public static T fromJSON(
- final String authorizationDetailJson, final Class clazz, final ObjectMapper objectMapper) {
+ public static T fromJSON(final String authorizationDetailJson,
+ final Class clazz) {
try {
if (StringUtils.isNotEmpty(authorizationDetailJson)) {
- return objectMapper.readValue(authorizationDetailJson, clazz);
+ return getDefaultObjectMapper().readValue(authorizationDetailJson, clazz);
}
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing String to AuthorizationDetails. Caused by, ", e);
@@ -108,19 +107,17 @@ public static T fromJSON(
*
*
* @param authorizationDetails the set of {@code AuthorizationDetail} objects to convert
- * @param objectMapper the {@code ObjectMapper} instance to use for serialization
* @param the type parameter extending {@code AuthorizationDetail}
* @return a JSON string representation of the authorization details set,
* or an empty JSON array if null or an error occurs
* @see AuthorizationDetail
* @see AuthorizationDetails
*/
- public static String toJSON(
- final Set authorizationDetails, final ObjectMapper objectMapper) {
+ public static String toJSON(final Set authorizationDetails) {
try {
if (authorizationDetails != null) {
- return objectMapper.writeValueAsString(authorizationDetails);
+ return getDefaultObjectMapper().writeValueAsString(authorizationDetails);
}
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing AuthorizationDetails to String. Caused by, ", e);
@@ -136,19 +133,17 @@ public static String toJSON(
*
*
* @param authorizationDetail the {@code AuthorizationDetail} object to convert
- * @param objectMapper the {@code ObjectMapper} instance to use for serialization
* @param the type parameter extending {@code AuthorizationDetail}
* @return a JSON string representation of the authorization detail,
* or an empty JSON object if null or an error occurs
* @see AuthorizationDetail
* @see AuthorizationDetails
*/
- public static String toJSON(
- final T authorizationDetail, final ObjectMapper objectMapper) {
+ public static String toJSON(final T authorizationDetail) {
try {
if (authorizationDetail != null) {
- return objectMapper.writeValueAsString(authorizationDetail);
+ return getDefaultObjectMapper().writeValueAsString(authorizationDetail);
}
} catch (JsonProcessingException e) {
log.debug("Error occurred while parsing AuthorizationDetail to String. Caused by, ", e);
@@ -164,21 +159,16 @@ public static String toJSON(
*
*
* @param authorizationDetail the {@code AuthorizationDetail} object to convert
- * @param objectMapper the {@code ObjectMapper} instance to use for serialization
* @param the type parameter extending {@code AuthorizationDetail}
* @return a {@code Map} representation of the authorization detail,
* or an empty {@code HashMap} if null or an error occurs
* @see AuthorizationDetail
* @see AuthorizationDetails
*/
- public static Map toMap(
- final T authorizationDetail, final ObjectMapper objectMapper) {
+ public static Map toMap(final T authorizationDetail) {
- if (authorizationDetail != null) {
- return objectMapper.convertValue(authorizationDetail, new TypeReference>() {
- });
- }
- return Collections.emptyMap();
+ return (authorizationDetail == null) ? Collections.emptyMap()
+ : getDefaultObjectMapper().convertValue(authorizationDetail, TYPE_MAP);
}
/**
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
index b078f7ea08..5a283dd1d9 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsSchemaValidatorTest.java
@@ -19,6 +19,7 @@
package org.wso2.carbon.identity.oauth2.rar;
import com.fasterxml.jackson.core.JsonProcessingException;
+import io.vertx.core.json.JsonObject;
import org.apache.commons.lang3.StringUtils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -27,6 +28,9 @@
import org.wso2.carbon.identity.oauth2.rar.util.TestDAOUtils;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -54,6 +58,7 @@ public void shouldReturnTrue_whenAuthorizationDetailIsSchemaCompliant()
testAuthorizationDetail.setType(TEST_TYPE);
assertTrue(this.uut.isSchemaCompliant(TEST_SCHEMA, testAuthorizationDetail));
+ assertTrue(this.uut.isSchemaCompliant(this.getTestSchema(), testAuthorizationDetail));
}
@Test
@@ -61,6 +66,10 @@ public void shouldReturnFalse_whenSchemaIsEmpty() throws AuthorizationDetailsPro
assertFalse(this.uut.isSchemaCompliant(StringUtils.EMPTY, new TestDAOUtils.TestAuthorizationDetail()));
assertFalse(this.uut.isSchemaCompliant(TEST_SCHEMA, null));
+ assertFalse(this.uut.isSchemaCompliant((JsonObject) null, new TestDAOUtils.TestAuthorizationDetail()));
+ assertFalse(this.uut.isSchemaCompliant(new JsonObject(), null));
+ assertFalse(this.uut.isSchemaCompliant((Map) null, new TestDAOUtils.TestAuthorizationDetail()));
+ assertFalse(this.uut.isSchemaCompliant(this.getTestSchema(), null));
}
@Test(expectedExceptions = {AuthorizationDetailsProcessingException.class})
@@ -102,4 +111,28 @@ public void shouldThrowAuthorizationDetailsProcessingException_whenSchemaIsInval
assertFalse(this.uut.isValidSchema(invalidSchema));
}
+
+ private Map getTestSchema() {
+ final Map items = new HashMap<>();
+ items.put("type", "string");
+ items.put("enum", Collections.singletonList("initiate"));
+
+ final Map actions = new HashMap<>();
+ actions.put("type", "array");
+ actions.put("items", items);
+
+ final Map type = new HashMap<>();
+ type.put("type", "string");
+ type.put("enum", Collections.singletonList("test_type_v1"));
+
+ final Map properties = new HashMap<>();
+ properties.put("type", type);
+ properties.put("actions", actions);
+
+ final Map schema = new HashMap<>();
+ schema.put("type", "object");
+ schema.put("required", Collections.singletonList("type"));
+ schema.put("properties", properties);
+ return schema;
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index fb27e90a4c..7dd3648d94 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -205,7 +205,7 @@ public void shouldThrowSQLException_whenAddingConsentedAuthorizationDetailsFails
try (Connection connectionMock = Mockito.spy(Connection.class)) {
- Mockito.when(connectionMock.getMetaData()).thenThrow(SQLException.class);
+ Mockito.when(connectionMock.prepareStatement(anyString())).thenThrow(SQLException.class);
identityDatabaseUtilMock
.when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
.thenReturn(connectionMock);
@@ -235,6 +235,6 @@ public void testGetConsentIdByUserIdAndAppId() throws SQLException {
@Test
public void shouldReturnNull_whenUserIdOrAppIdInvalid() throws SQLException {
- assertNull(this.uut.getConsentIdByUserIdAndAppId("invlid_user_id", "invalid_app_id", TEST_TENANT_ID));
+ assertNull(this.uut.getConsentIdByUserIdAndAppId("invalid_user_id", "invalid_app_id", TEST_TENANT_ID));
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
index 238be9a7b7..44ea42d325 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsCommonUtilsTest.java
@@ -18,10 +18,6 @@
package org.wso2.carbon.identity.oauth2.rar.util;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.mockito.Mockito;
-import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.collections.Sets;
@@ -36,8 +32,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_ARRAY;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.EMPTY_JSON_OBJECT;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_NAME;
@@ -48,20 +42,6 @@
*/
public class AuthorizationDetailsCommonUtilsTest {
- private ObjectMapper objectMapper;
- private ObjectMapper mockObjectMapper;
-
- @BeforeClass
- public void setUp() throws JsonProcessingException {
-
- this.objectMapper = AuthorizationDetailsCommonUtils.getDefaultObjectMapper();
- this.mockObjectMapper = Mockito.spy(this.objectMapper);
-
- doThrow(JsonProcessingException.class)
- .when(this.mockObjectMapper).writeValueAsString(any(TestDAOUtils.TestAuthorizationDetail.class));
- doThrow(JsonProcessingException.class).when(this.mockObjectMapper).writeValueAsString(any(Set.class));
- }
-
@DataProvider(name = "AuthorizationDetailsCommonUtilsTestDataProvider")
public Object[][] provideAuthorizationDetailsCommonUtilsTestData(Method testMethod) {
@@ -89,8 +69,8 @@ public Object[][] provideAuthorizationDetailsCommonUtilsTestData(Method testMeth
@Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
public void shouldReturnCorrectSize_whenJSONArrayIsValid(String inputJson, int expectedSize) {
- Set actualAuthorizationDetails = AuthorizationDetailsCommonUtils
- .fromJSONArray(inputJson, AuthorizationDetail.class, objectMapper);
+ Set actualAuthorizationDetails =
+ AuthorizationDetailsCommonUtils.fromJSONArray(inputJson, AuthorizationDetail.class);
assertEquals(expectedSize, actualAuthorizationDetails.size());
}
@@ -98,7 +78,7 @@ public void shouldReturnCorrectSize_whenJSONArrayIsValid(String inputJson, int e
@Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
public void shouldReturnNull_whenJSONIsInvalid(String inputJson, int expectedSize) {
- assertNull(AuthorizationDetailsCommonUtils.fromJSON(inputJson, AuthorizationDetail.class, objectMapper));
+ assertNull(AuthorizationDetailsCommonUtils.fromJSON(inputJson, AuthorizationDetail.class));
}
@Test(dataProvider = "AuthorizationDetailsCommonUtilsTestDataProvider")
@@ -106,7 +86,7 @@ public void shouldReturnCorrectType_whenJSONIsVa
final String inputJson = "{\"type\": \"" + TEST_TYPE + "\"}";
AuthorizationDetail actualAuthorizationDetail =
- AuthorizationDetailsCommonUtils.fromJSON(inputJson, expectedClazz, objectMapper);
+ AuthorizationDetailsCommonUtils.fromJSON(inputJson, expectedClazz);
assertNotNull(actualAuthorizationDetail);
assertEquals(TEST_TYPE, actualAuthorizationDetail.getType());
@@ -119,15 +99,12 @@ public void shouldReturnCorrectJson_whenAuthorizationDetailsAreValid() {
inputAuthorizationDetail.setType(TEST_TYPE);
inputAuthorizationDetail.setName(TEST_NAME);
- final String authorizationDetails = AuthorizationDetailsCommonUtils
- .toJSON(Sets.newHashSet(inputAuthorizationDetail), objectMapper);
+ final String authorizationDetails =
+ AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail));
assertTrue(authorizationDetails.contains(TEST_TYPE));
assertTrue(authorizationDetails.contains(TEST_NAME));
- assertEquals(EMPTY_JSON_ARRAY,
- AuthorizationDetailsCommonUtils.toJSON((Set) null, objectMapper));
- assertEquals(EMPTY_JSON_ARRAY,
- AuthorizationDetailsCommonUtils.toJSON(Sets.newHashSet(inputAuthorizationDetail), mockObjectMapper));
+ assertEquals(EMPTY_JSON_ARRAY, AuthorizationDetailsCommonUtils.toJSON((Set) null));
}
@Test
@@ -137,15 +114,14 @@ public void shouldReturnCorrectJson_whenAuthorizationDetailIsValid() {
inputAuthorizationDetail.setType(TEST_TYPE);
inputAuthorizationDetail.setName(TEST_NAME);
- final String authorizationDetail =
- AuthorizationDetailsCommonUtils.toJSON(inputAuthorizationDetail, objectMapper);
+ final String authorizationDetail = AuthorizationDetailsCommonUtils.toJSON(inputAuthorizationDetail);
assertTrue(authorizationDetail.contains(TEST_TYPE));
assertTrue(authorizationDetail.contains(TEST_NAME));
assertEquals(EMPTY_JSON_OBJECT,
- AuthorizationDetailsCommonUtils.toJSON((TestDAOUtils.TestAuthorizationDetail) null, objectMapper));
+ AuthorizationDetailsCommonUtils.toJSON((TestDAOUtils.TestAuthorizationDetail) null));
assertEquals(EMPTY_JSON_OBJECT,
- AuthorizationDetailsCommonUtils.toJSON(new TestDAOUtils.TestAuthorizationDetail(), mockObjectMapper));
+ AuthorizationDetailsCommonUtils.toJSON(new TestDAOUtils.TestAuthorizationDetail()));
}
@Test
@@ -154,7 +130,7 @@ public void shouldReturnMap_whenAuthorizationDetailIsValid() {
TestDAOUtils.TestAuthorizationDetail inputAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail();
inputAuthorizationDetail.setType(TEST_TYPE);
inputAuthorizationDetail.setName(TEST_NAME);
- Map map = AuthorizationDetailsCommonUtils.toMap(inputAuthorizationDetail, objectMapper);
+ Map map = AuthorizationDetailsCommonUtils.toMap(inputAuthorizationDetail);
assertTrue(map.containsKey("type"));
assertTrue(map.containsKey("name"));
@@ -162,6 +138,6 @@ public void shouldReturnMap_whenAuthorizationDetailIsValid() {
assertEquals(TEST_NAME, String.valueOf(map.get("name")));
assertEquals(2, map.keySet().size());
- assertFalse(AuthorizationDetailsCommonUtils.toMap(null, objectMapper).containsKey(TEST_TYPE));
+ assertFalse(AuthorizationDetailsCommonUtils.toMap(null).containsKey(TEST_TYPE));
}
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
index 7ab96e2b44..abcd4dacab 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS AUTHORIZATION_DETAILS_TYPES(
CURSOR_KEY INTEGER DEFAULT 1,
NAME VARCHAR(255),
DESCRIPTION VARCHAR (255),
- JSON_SCHEMA JSON NOT NULL,
+ JSON_SCHEMA CLOB NOT NULL,
TENANT_ID INTEGER DEFAULT -1
);
@@ -12,7 +12,7 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS (
ID INTEGER NOT NULL AUTO_INCREMENT,
CONSENT_ID VARCHAR(255) NOT NULL,
TYPE_ID INTEGER NOT NULL,
- AUTHORIZATION_DETAILS JSON NOT NULL,
+ AUTHORIZATION_DETAILS CLOB NOT NULL,
CONSENT BOOLEAN NOT NULL DEFAULT 1,
TENANT_ID INTEGER NOT NULL DEFAULT -1
);
@@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS (
CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS (
ID INTEGER NOT NULL AUTO_INCREMENT,
TYPE_ID INTEGER NOT NULL,
- AUTHORIZATION_DETAILS JSON NOT NULL,
+ AUTHORIZATION_DETAILS CLOB NOT NULL,
TOKEN_ID VARCHAR (255),
TENANT_ID INTEGER DEFAULT -1
);
@@ -28,7 +28,7 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS (
CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS (
ID INTEGER NOT NULL AUTO_INCREMENT,
TYPE_ID CHAR(36) NOT NULL,
- AUTHORIZATION_DETAILS JSON NOT NULL,
+ AUTHORIZATION_DETAILS CLOB NOT NULL,
CODE_ID VARCHAR (255),
TENANT_ID INTEGER
);
@@ -68,4 +68,4 @@ INSERT INTO IDN_OAUTH2_AUTHORIZATION_CODE (CODE_ID, AUTHORIZATION_CODE, IDP_ID)
VALUES ('81197bc6-63f3-4c0f-90dd-1588076ab50f', 'b1b833f0-f605-4f5c-add6-38ea8ce1b969', 1);
INSERT INTO IDN_OAUTH2_USER_CONSENT (USER_ID, APP_ID, TENANT_ID, CONSENT_ID)
-VALUES ('valid_user_id', 'valid_app_id', 1234, '52481ccd-0927-4d17-8cfc-5110fc4aa009');
\ No newline at end of file
+VALUES ('valid_user_id', 'valid_app_id', 1234, '52481ccd-0927-4d17-8cfc-5110fc4aa009');
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index ef32dcc622..a3a61ef6e9 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -266,7 +266,7 @@ public static boolean isRichAuthorizationRequest(final OAuth2Parameters oAuth2Pa
/**
* Transforms the given {@link AuthorizationDetails} by creating a new set of {@link AuthorizationDetail} objects
- * with only the displayable fields ({@code type}, {@code id}, {@code consentDescription}) copied over.
+ * with only the displayable fields ({@code type}, {@code id}, {@code description}) copied over.
*
* @param authorizationDetails The original AuthorizationDetails to be transformed.
* @return A new {@link AuthorizationDetails} object containing the displayable authorization details.
@@ -277,9 +277,9 @@ public static AuthorizationDetails getDisplayableAuthorizationDetails(
final Set displayableAuthorizationDetails = authorizationDetails.stream()
.map(protectedAuthorizationDetail -> {
final AuthorizationDetail authorizationDetail = new AuthorizationDetail();
- authorizationDetail.setType(protectedAuthorizationDetail.getType());
authorizationDetail.setId(protectedAuthorizationDetail.getId());
- authorizationDetail.setConsentDescription(protectedAuthorizationDetail.getConsentDescription());
+ authorizationDetail.setType(protectedAuthorizationDetail.getType());
+ authorizationDetail.setDescription(protectedAuthorizationDetail.getDescription());
return authorizationDetail;
}).collect(toSet());
@@ -297,23 +297,11 @@ public static AuthorizationDetails getTrimmedAuthorizationDetails(final Authoriz
authorizationDetails.stream().forEach(authorizationDetail -> {
authorizationDetail.setId(null);
- authorizationDetail.setConsentDescription(null);
+ authorizationDetail.setDescription(null);
});
return authorizationDetails;
}
- /**
- * Generates an {@link AuthorizationDetails} instance from given JSON string
- * and assigns unique IDs for each {@link AuthorizationDetail}.
- *
- * @param authorizationDetailsJson The JSON string representing the authorization details.
- * @return The AuthorizationDetails object with unique IDs assigned to each AuthorizationDetail.
- */
- public static AuthorizationDetails generateAndAssignUniqueIDs(final String authorizationDetailsJson) {
-
- return assignUniqueIDsToAuthorizationDetails(new AuthorizationDetails(authorizationDetailsJson));
- }
-
/**
* Generates unique IDs for each {@link AuthorizationDetail} within the given {@link AuthorizationDetails} object.
*
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
index 809bcfdd49..cc42caeb32 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
@@ -306,15 +306,15 @@ private Map getAuthorizedAuthorizationDetailsT
final List authorizationDetailsTypes = OAuth2ServiceComponentHolder.getInstance()
.getAuthorizedAPIManagementService().getAuthorizedAuthorizationDetailsTypes(appId, tenantDomain);
- if (CollectionUtils.isEmpty(authorizationDetailsTypes)) {
- return Collections.emptyMap();
+ if (CollectionUtils.isNotEmpty(authorizationDetailsTypes)) {
+ return authorizationDetailsTypes.stream()
+ .collect(Collectors.toMap(AuthorizationDetailsType::getType, Function.identity()));
}
- return authorizationDetailsTypes.stream()
- .collect(Collectors.toMap(AuthorizationDetailsType::getType, Function.identity()));
} catch (IdentityOAuth2Exception | IdentityApplicationManagementException e) {
log.error("Unable to retrieve authorized authorization details types. Caused by, ", e);
throw new IdentityOAuth2ServerException("Unable to retrieve authorized authorization details types", e);
}
+ return Collections.emptyMap();
}
private Set getSchemaCompliantAuthorizationDetails(
From ca2f0549d9310cbd71f18e16a08da7a34f7e6e44 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Mon, 28 Oct 2024 11:18:46 +0530
Subject: [PATCH 08/28] Resolve merge conflicts
---
.../org.wso2.carbon.identity.oauth/pom.xml | 2 --
.../rar/util/AuthorizationDetailsUtils.java | 10 ++++++----
.../grant/AbstractAuthorizationGrantHandler.java | 3 ++-
.../handlers/grant/RefreshGrantHandlerTest.java | 16 +++++++++++++++-
pom.xml | 5 +++--
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index b0218bad0d..0f334853fb 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -269,8 +269,6 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.oauth.rar
- compile
- 7.0.162-SNAPSHOT
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index a3a61ef6e9..012382d23a 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -295,10 +295,12 @@ public static AuthorizationDetails getDisplayableAuthorizationDetails(
*/
public static AuthorizationDetails getTrimmedAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
- authorizationDetails.stream().forEach(authorizationDetail -> {
- authorizationDetail.setId(null);
- authorizationDetail.setDescription(null);
- });
+ if (authorizationDetails != null) {
+ authorizationDetails.stream().forEach(authorizationDetail -> {
+ authorizationDetail.setId(null);
+ authorizationDetail.setDescription(null);
+ });
+ }
return authorizationDetails;
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
index 9321ba42a0..15dd3b7264 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
@@ -1275,6 +1275,7 @@ protected void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageCont
authorizationDetails = this.authorizationDetailsService.getAuthorizationCodeAuthorizationDetails(
oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode(), tenantId);
}
- oAuthTokenReqMessageContext.setAuthorizationDetails(authorizationDetails);
+ oAuthTokenReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
+ .getTrimmedAuthorizationDetails(authorizationDetails));
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTest.java
index 5dd37ce304..737414b8c7 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTest.java
@@ -36,7 +36,10 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.test.common.testng.utils.MockAuthenticatedUser;
import org.wso2.carbon.identity.user.profile.mgt.association.federation.FederatedAssociationManager;
import org.wso2.carbon.identity.user.profile.mgt.association.federation.exception.FederatedAssociationManagerClientException;
@@ -47,6 +50,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -54,6 +58,7 @@
import static org.mockito.Mockito.when;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_CHECKING_ACCOUNT_LOCK_STATUS;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_GETTING_USERNAME_ASSOCIATED_WITH_IDP;
+import static org.wso2.carbon.identity.oauth2.TestConstants.TENANT_ID;
/**
* Unit tests for the RefreshGrantHandler class.
@@ -66,6 +71,7 @@ public class RefreshGrantHandlerTest {
private OAuthServerConfiguration oAuthServerConfiguration;
private OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO;
private OAuth2ServiceComponentHolder oAuth2ServiceComponentHolder;
+ private AuthorizationDetailsService authorizationDetailsService;
@BeforeMethod
public void init() {
@@ -75,6 +81,7 @@ public void init() {
oAuthServerConfiguration = mock(OAuthServerConfiguration.class);
oAuth2AccessTokenReqDTO = mock(OAuth2AccessTokenReqDTO.class);
oAuth2ServiceComponentHolder = mock(OAuth2ServiceComponentHolder.class);
+ authorizationDetailsService = mock(AuthorizationDetailsService.class);
}
@DataProvider(name = "validateGrantWhenUserIsLockedInUserStoreEnd")
@@ -143,6 +150,10 @@ public void testValidateGrantWhenUserIsLockedInUserStoreEnd(AuthenticatedUser us
isValidateAuthenticatedUserForRefreshGrant);
when(oAuth2ServiceComponentHolder.getRefreshTokenGrantProcessor()).thenReturn(refreshTokenGrantProcessor);
when(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO()).thenReturn(oAuth2AccessTokenReqDTO);
+ when(authorizationDetailsService
+ .getUserConsentedAuthorizationDetails(any(AuthenticatedUser.class), anyString(), anyInt()))
+ .thenReturn(new AuthorizationDetails());
+ when(oAuth2ServiceComponentHolder.getAuthorizationDetailsService()).thenReturn(authorizationDetailsService);
FederatedAssociationManager federatedAssociationManager = mock(FederatedAssociationManager.class);
if (federatedAssociationManagerException instanceof FederatedAssociationManagerException) {
@@ -169,7 +180,9 @@ public void testValidateGrantWhenUserIsLockedInUserStoreEnd(AuthenticatedUser us
OAuthServerConfiguration.class);
MockedStatic oAuth2ServiceComponentHolderMockedStatic = mockStatic(
OAuth2ServiceComponentHolder.class);
- MockedStatic frameworkUtilsMockedStatic = mockStatic(FrameworkUtils.class)) {
+ MockedStatic frameworkUtilsMockedStatic = mockStatic(FrameworkUtils.class);
+ MockedStatic oAuth2Util = mockStatic(OAuth2Util.class)) {
+ oAuth2Util.when(() -> OAuth2Util.getTenantId(anyString())).thenReturn(TENANT_ID);
oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance)
.thenReturn(oAuthServerConfiguration);
oAuth2ServiceComponentHolderMockedStatic.when(OAuth2ServiceComponentHolder::getInstance)
@@ -185,6 +198,7 @@ public void testValidateGrantWhenUserIsLockedInUserStoreEnd(AuthenticatedUser us
}
RefreshGrantHandler refreshGrantHandler = new RefreshGrantHandler();
+ refreshGrantHandler.init();
boolean validateResult = refreshGrantHandler.validateGrant(oAuthTokenReqMessageContext);
assertTrue(validateResult);
}
diff --git a/pom.xml b/pom.xml
index 29d6b86721..558f5fb95c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,12 +62,12 @@
components/org.wso2.carbon.identity.oauth.client.authn.filter
components/org.wso2.carbon.identity.oauth.ciba
components/org.wso2.carbon.identity.client.attestation.filter
+ components/org.wso2.carbon.identity.oauth.rar
features/org.wso2.carbon.identity.oauth.common.feature
features/org.wso2.carbon.identity.oauth.feature
features/org.wso2.carbon.identity.oauth.server.feature
features/org.wso2.carbon.identity.oauth.ui.feature
features/org.wso2.carbon.identity.oauth.dcr.server.feature
- components/org.wso2.carbon.identity.oauth.rar
@@ -957,7 +957,8 @@
[1.0.1, 2.0.0)
- 7.5.86
+
+ 7.5.94-SNAPSHOT
[5.25.234, 8.0.0)
From ffba19a022e4bce2069d2408f009eeae0d39f760 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Mon, 28 Oct 2024 14:13:40 +0530
Subject: [PATCH 09/28] Add license headers
---
.../pom.xml | 3 +-
.../pom.xml | 2 +-
.../src/test/resources/dbScripts/h2.sql | 34 +++++++++----------
.../rar/AuthorizationDetailsService.java | 18 ++++++++++
.../AuthorizationDetailsProcessorFactory.java | 4 +--
.../rar/util/AuthorizationDetailsUtils.java | 18 ++++++++++
.../AuthorizationDetailsValidator.java | 18 ++++++++++
.../rar/AuthorizationDetailsServiceTest.java | 18 ++++++++++
.../AccessTokenResponseRARHandlerTest.java | 18 ++++++++++
.../IntrospectionRARDataProviderTest.java | 18 ++++++++++
.../JWTAccessTokenRARClaimProviderTest.java | 18 ++++++++++
.../utils/AuthorizationDetailsBaseTest.java | 18 ++++++++++
...aultAuthorizationDetailsValidatorTest.java | 18 ++++++++++
pom.xml | 6 ----
14 files changed, 183 insertions(+), 28 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
index b60ef106f2..2de3921206 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/pom.xml
@@ -327,8 +327,7 @@
COMPLEXITY
COVEREDRATIO
-
- 0.47
+ 0.48
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 99929f0ce5..7b74c4df18 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.174-SNAPSHOT
+ 7.0.177-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
index abcd4dacab..83f076e4bc 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/resources/dbScripts/h2.sql
@@ -34,23 +34,23 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHZ_CODE_AUTHORIZATION_DETAILS (
);
CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_CODE (
- CODE_ID VARCHAR (255),
- AUTHORIZATION_CODE VARCHAR (2048),
- CONSUMER_KEY_ID INTEGER,
- CALLBACK_URL VARCHAR (2048),
- SCOPE VARCHAR(2048),
- AUTHZ_USER VARCHAR (100),
- TENANT_ID INTEGER,
- USER_DOMAIN VARCHAR(50),
- TIME_CREATED TIMESTAMP,
- VALIDITY_PERIOD BIGINT,
- STATE VARCHAR (25) DEFAULT 'ACTIVE',
- TOKEN_ID VARCHAR(255),
- SUBJECT_IDENTIFIER VARCHAR(255),
- PKCE_CODE_CHALLENGE VARCHAR (255),
- PKCE_CODE_CHALLENGE_METHOD VARCHAR(128),
- AUTHORIZATION_CODE_HASH VARCHAR (512),
- IDP_ID INTEGER DEFAULT -1 NOT NULL
+ CODE_ID VARCHAR (255),
+ AUTHORIZATION_CODE VARCHAR (2048),
+ CONSUMER_KEY_ID INTEGER,
+ CALLBACK_URL VARCHAR (2048),
+ SCOPE VARCHAR(2048),
+ AUTHZ_USER VARCHAR (100),
+ TENANT_ID INTEGER,
+ USER_DOMAIN VARCHAR(50),
+ TIME_CREATED TIMESTAMP,
+ VALIDITY_PERIOD BIGINT,
+ STATE VARCHAR (25) DEFAULT 'ACTIVE',
+ TOKEN_ID VARCHAR(255),
+ SUBJECT_IDENTIFIER VARCHAR(255),
+ PKCE_CODE_CHALLENGE VARCHAR (255),
+ PKCE_CODE_CHALLENGE_METHOD VARCHAR(128),
+ AUTHORIZATION_CODE_HASH VARCHAR (512),
+ IDP_ID INTEGER DEFAULT -1 NOT NULL
);
CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENT (
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
index f870ae85d1..11e412a9d2 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar;
import org.apache.commons.logging.Log;
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
index a8798b42e2..3743515386 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
@@ -41,8 +41,8 @@
* Example usage:
*
{@code
* // Get a specific provider by type
- * AuthorizationDetailsProviderFactory.getInstance()
- * .getProviderByType("customer_information")
+ * AuthorizationDetailsProcessorFactory.getInstance()
+ * .getAuthorizationDetailsProcessorByType("customer_information")
* .ifPresentOrElse(
* p -> log.debug("Provider for type " + type + ": " + p.getClass().getName()),
* () -> log.debug("No provider found for type " + type)
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index 012382d23a..5f9cc82d41 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.util;
import org.apache.commons.lang.StringUtils;
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
index 2cdf2afd7f..71e5549e55 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/AuthorizationDetailsValidator.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.validator;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
index 143ee3fb9a..987da89649 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
index 26dae1ca6c..53103e1eb4 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandlerTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
import org.testng.annotations.BeforeClass;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
index ec9f84b1d0..bb8a935e39 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
import org.mockito.MockedStatic;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
index 7e8c99e6fc..a4a903d37d 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProviderTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
import org.testng.annotations.BeforeClass;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
index 7159bda1be..b8bec6482f 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.utils;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
index 2849f2976b..67c8e4f942 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.validator;
import org.apache.oltu.oauth2.common.message.types.GrantType;
diff --git a/pom.xml b/pom.xml
index 2362c9c2a0..c2446c22de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -415,11 +415,6 @@
gson
${com.google.code.gson.version}
-
- com.google.auto.service
- auto-service
- ${com.google.auto.service.version}
-
io.vertx
@@ -1052,7 +1047,6 @@
2.4.7
5.2
9.2
- 1.1.1
4.5.10
From 4c56858466f6f43b6bd9c9ec071f363285fac535 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Wed, 13 Nov 2024 17:59:35 +0530
Subject: [PATCH 10/28] Add a config method to check if RAR is enabled
---
.../builders/ProviderConfigBuilder.java | 8 +-
.../endpoint/authz/OAuth2AuthzEndpoint.java | 12 +-
.../pom.xml | 6 +
.../rar/dao/AuthorizationDetailsDAO.java | 14 +-
.../rar/dao/AuthorizationDetailsDAOImpl.java | 81 ++++++++--
.../identity/oauth2/rar/dao/SQLQueries.java | 5 +
.../dao/AuthorizationDetailsDAOImplTest.java | 113 ++++++++++---
.../oauth2/rar/util/TestDAOUtils.java | 8 +
.../authz/AuthorizationHandlerManager.java | 2 -
.../authz/OAuthAuthzReqMessageContext.java | 44 +++--
.../handlers/AbstractResponseTypeHandler.java | 2 +-
.../rar/AuthorizationDetailsService.java | 151 ++++++++++++------
.../AuthorizationDetailsProcessorFactory.java | 16 +-
.../token/AccessTokenResponseRARHandler.java | 4 +-
.../token/JWTAccessTokenRARClaimProvider.java | 4 +-
.../rar/util/AuthorizationDetailsUtils.java | 31 +---
.../DefaultAuthorizationDetailsValidator.java | 4 +-
.../AbstractAuthorizationGrantHandler.java | 42 +----
.../grant/AuthorizationCodeGrantHandler.java | 35 +++-
.../handlers/grant/RefreshGrantHandler.java | 33 +++-
.../rar/AuthorizationDetailsServiceTest.java | 15 +-
.../utils/AuthorizationDetailsBaseTest.java | 3 +-
22 files changed, 436 insertions(+), 197 deletions(-)
diff --git a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
index 68b79545e3..d3ac9f6ad1 100644
--- a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
+++ b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
@@ -154,11 +154,11 @@ public OIDProviderConfigResponse buildOIDProviderConfig(OIDProviderRequest reque
providerConfig.setMtlsTokenEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSTokenEPUrl());
providerConfig.setMtlsPushedAuthorizationRequestEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSParEPUrl());
- final Set supportedTypes = AuthorizationDetailsProcessorFactory.getInstance()
+ final Set authorizationDetailTypes = AuthorizationDetailsProcessorFactory.getInstance()
.getSupportedAuthorizationDetailTypes();
- if (supportedTypes != null && !supportedTypes.isEmpty()) {
- final int size = supportedTypes.size();
- providerConfig.setAuthorizationDetailsTypesSupported(supportedTypes.toArray(new String[size]));
+ if (authorizationDetailTypes != null && !authorizationDetailTypes.isEmpty()) {
+ //final int size = supportedTypes.size();
+ providerConfig.setAuthorizationDetailsTypesSupported(authorizationDetailTypes.toArray(String[]::new));
}
return providerConfig;
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
index 296c78eaf0..37b2f67266 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java
@@ -1637,6 +1637,7 @@ private String handleUserConsent(OAuthMessage oAuthMessage, String consent, OIDC
oAuthMessage.getSessionDataCacheEntry().getAuthzReqMsgCtx();
oAuthAuthzReqMessageContext.setAuthorizationReqDTO(authzReqDTO);
oAuthAuthzReqMessageContext.addProperty(OAuthConstants.IS_MTLS_REQUEST, oauth2Params.isMtlsRequest());
+ oAuthAuthzReqMessageContext.setApprovedAuthorizationDetails(oauth2Params.getAuthorizationDetails());
// authorizing the request
OAuth2AuthorizeRespDTO authzRespDTO = authorize(oAuthAuthzReqMessageContext);
if (authzRespDTO != null && authzRespDTO.getCallbackURI() != null) {
@@ -1742,7 +1743,7 @@ private void storeUserConsent(OAuthMessage oAuthMessage, String consent) throws
clientId, oauth2Params, userConsentedAuthorizationDetails);
} else {
EndpointUtil.storeOAuthScopeConsent(loggedInUser, oauth2Params, false);
- authorizationDetailsService.storeUserConsentedAuthorizationDetails(loggedInUser,
+ authorizationDetailsService.storeOrUpdateUserConsentedAuthorizationDetails(loggedInUser,
clientId, oauth2Params, userConsentedAuthorizationDetails);
}
}
@@ -4894,15 +4895,14 @@ private void validateAuthorizationDetailsBeforeConsent(final OAuthMessage oAuthM
.getAuthorizationDetailsValidator()
.getValidatedAuthorizationDetails(oAuthAuthzReqMessageContext);
- // update oAuth2Parameters with validated authorization details
- oAuth2Parameters.setAuthorizationDetails(AuthorizationDetailsUtils
- .assignUniqueIDsToAuthorizationDetails(validatedAuthorizationDetails));
-
// Update the authorization message context with validated authorization details
- oAuthAuthzReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
+ oAuthAuthzReqMessageContext.setRequestedAuthorizationDetails(AuthorizationDetailsUtils
.assignUniqueIDsToAuthorizationDetails(validatedAuthorizationDetails));
oAuthMessage.getSessionDataCacheEntry().setAuthzReqMsgCtx(oAuthAuthzReqMessageContext);
+ // update oAuth2Parameters with validated authorization details
+ oAuth2Parameters.setAuthorizationDetails(oAuthAuthzReqMessageContext.getRequestedAuthorizationDetails());
+
if (LoggerUtils.isDiagnosticLogsEnabled()) {
DiagnosticLog.DiagnosticLogBuilder diagnosticLogBuilder = new DiagnosticLog.DiagnosticLogBuilder(
OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE,
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 7b74c4df18..5af7f05e05 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -44,6 +44,12 @@
provided
+
+ org.wso2.carbon.identity.framework
+ org.wso2.carbon.identity.api.resource.mgt
+ provided
+
+
com.fasterxml.jackson.core
jackson-databind
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
index be49e2c822..eddef973d4 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAO.java
@@ -45,6 +45,18 @@ public interface AuthorizationDetailsDAO {
int[] addUserConsentedAuthorizationDetails(Set authorizationDetailsConsentDTOs)
throws SQLException;
+ /**
+ * Updates user consented authorization details in the database.
+ *
+ * @param authorizationDetailsConsentDTOs A set of user consented authorization details DTOs.
+ * {@link AuthorizationDetailsConsentDTO }
+ * @return An array of positive integers indicating the number of rows affected for each batch operation,
+ * or negative integers if any of the batch operations fail.
+ * @throws SQLException If a database access error occurs.
+ */
+ int[] updateUserConsentedAuthorizationDetails(Set authorizationDetailsConsentDTOs)
+ throws SQLException;
+
/**
* Retrieves user consented authorization details from the database.
*
@@ -114,7 +126,7 @@ int[] addOAuth2CodeAuthorizationDetails(Set authori
* Retrieves authorization code authorization details from the database.
*
* @param authorizationCode The value of the authorization code.
- * @param tenantId The tenant ID.
+ * @param tenantId The tenant ID.
* @return A set of authorization code authorization details DTOs.
* @throws SQLException If a database access error occurs.
*/
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index fc9682292e..4af816fbba 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -30,6 +30,8 @@
import java.util.HashSet;
import java.util.Set;
+import static org.wso2.carbon.identity.api.resource.mgt.util.AuthorizationDetailsTypesUtil.isRichAuthorizationRequestsDisabled;
+
/**
* Implements the {@link AuthorizationDetailsDAO} interface to manage rich authorization requests.
*
@@ -42,14 +44,18 @@ public class AuthorizationDetailsDAOImpl implements AuthorizationDetailsDAO {
* {@inheritDoc}
*/
@Override
- public int[] addUserConsentedAuthorizationDetails(
- final Set authorizationDetailsConsentDTOs) throws SQLException {
+ public int[] addUserConsentedAuthorizationDetails(final Set consentDTOs)
+ throws SQLException {
+
+ if (isRichAuthorizationRequestsDisabled()) {
+ return new int[0];
+ }
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
- for (AuthorizationDetailsConsentDTO consentDTO : authorizationDetailsConsentDTOs) {
+ for (AuthorizationDetailsConsentDTO consentDTO : consentDTOs) {
ps.setString(1, consentDTO.getConsentId());
ps.setString(2, consentDTO.getAuthorizationDetail().toJsonString());
ps.setBoolean(3, consentDTO.isConsentActive());
@@ -62,6 +68,34 @@ public int[] addUserConsentedAuthorizationDetails(
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int[] updateUserConsentedAuthorizationDetails(final Set consentDTOs)
+ throws SQLException {
+
+ if (isRichAuthorizationRequestsDisabled()) {
+ return new int[0];
+ }
+
+ try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
+ PreparedStatement ps =
+ connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
+
+ for (AuthorizationDetailsConsentDTO consentDTO : consentDTOs) {
+ ps.setString(1, consentDTO.getAuthorizationDetail().toJsonString());
+ ps.setBoolean(2, consentDTO.isConsentActive());
+ ps.setString(3, consentDTO.getConsentId());
+ ps.setString(4, consentDTO.getAuthorizationDetail().getType());
+ ps.setInt(5, consentDTO.getTenantId());
+ ps.setInt(6, consentDTO.getTenantId());
+ ps.addBatch();
+ }
+ return ps.executeBatch();
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -70,6 +104,11 @@ public Set getUserConsentedAuthorizationDetails(
final int tenantId)
throws SQLException {
+ final Set authorizationDetailsConsentDTOs = new HashSet<>();
+ if (isRichAuthorizationRequestsDisabled()) {
+ return authorizationDetailsConsentDTOs;
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -78,7 +117,6 @@ public Set getUserConsentedAuthorizationDetails(
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
- final Set authorizationDetailsConsentDTOs = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
final String typeId = rs.getString(2);
@@ -100,6 +138,10 @@ public Set getUserConsentedAuthorizationDetails(
public int deleteUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
throws SQLException {
+ if (isRichAuthorizationRequestsDisabled()) {
+ return -1;
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.DELETE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -114,13 +156,18 @@ public int deleteUserConsentedAuthorizationDetails(final String consentId, final
* {@inheritDoc}
*/
@Override
- public int[] addAccessTokenAuthorizationDetails(final Set
- authorizationDetailsTokenDTOs) throws SQLException {
+ public int[] addAccessTokenAuthorizationDetails(final Set tokenDTOs)
+ throws SQLException {
+
+ if (isRichAuthorizationRequestsDisabled()) {
+ return new int[0];
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
- for (AuthorizationDetailsTokenDTO tokenDTO : authorizationDetailsTokenDTOs) {
+ for (AuthorizationDetailsTokenDTO tokenDTO : tokenDTOs) {
ps.setString(1, tokenDTO.getAccessTokenId());
ps.setString(2, tokenDTO.getAuthorizationDetail().toJsonString());
ps.setString(3, tokenDTO.getAuthorizationDetail().getType());
@@ -140,6 +187,11 @@ public Set getAccessTokenAuthorizationDetails(fina
final int tenantId)
throws SQLException {
+ final Set authorizationDetailsTokenDTO = new HashSet<>();
+ if (isRichAuthorizationRequestsDisabled()) {
+ return authorizationDetailsTokenDTO;
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
@@ -148,7 +200,6 @@ public Set getAccessTokenAuthorizationDetails(fina
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
- final Set authorizationDetailsTokenDTO = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
final String typeId = rs.getString(2);
@@ -169,6 +220,10 @@ public Set getAccessTokenAuthorizationDetails(fina
public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, final int tenantId)
throws SQLException {
+ if (isRichAuthorizationRequestsDisabled()) {
+ return -1;
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
@@ -186,6 +241,10 @@ public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, fin
public int[] addOAuth2CodeAuthorizationDetails(final Set authorizationDetailsCodeDTOs)
throws SQLException {
+ if (isRichAuthorizationRequestsDisabled()) {
+ return new int[0];
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS)) {
@@ -209,6 +268,11 @@ public int[] addOAuth2CodeAuthorizationDetails(final Set getOAuth2CodeAuthorizationDetails(final String authorizationCode,
final int tenantId) throws SQLException {
+ final Set authorizationDetailsCodeDTOs = new HashSet<>();
+ if (isRichAuthorizationRequestsDisabled()) {
+ return authorizationDetailsCodeDTOs;
+ }
+
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_CODE_AUTHORIZATION_DETAILS_BY_CODE)) {
@@ -217,7 +281,6 @@ public Set getOAuth2CodeAuthorizationDetails(final
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
- final Set authorizationDetailsCodeDTOs = new HashSet<>();
while (rs.next()) {
final String codeId = rs.getString(1);
final String typeId = rs.getString(2);
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
index 3582c3babf..ef901d0bd9 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/SQLQueries.java
@@ -36,6 +36,11 @@ private SQLQueries() {
"(CONSENT_ID, AUTHORIZATION_DETAILS, CONSENT, TYPE_ID, TENANT_ID) " +
"VALUES (?, ?, ?, (" + SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE + "), ?)";
+ public static final String UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
+ "UPDATE IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
+ "SET AUTHORIZATION_DETAILS=?, CONSENT=? " +
+ "WHERE CONSENT_ID=? AND TYPE_ID=(" + SELECT_AUTHORIZATION_DETAILS_ID_BY_TYPE + ") AND TENANT_ID=?";
+
public static final String GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS =
"SELECT ID, TYPE_ID, AUTHORIZATION_DETAILS, CONSENT FROM IDN_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS " +
"WHERE CONSENT_ID=? AND TENANT_ID=?";
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index 7dd3648d94..f51555d8e6 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -18,12 +18,15 @@
package org.wso2.carbon.identity.oauth2.rar.dao;
+import org.apache.commons.lang3.StringUtils;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
+import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import org.wso2.carbon.identity.api.resource.mgt.util.AuthorizationDetailsTypesUtil;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsCodeDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
@@ -35,6 +38,7 @@
import java.sql.SQLException;
import java.util.Collections;
import java.util.Set;
+import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -48,6 +52,7 @@
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TENANT_ID;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TOKEN_ID;
import static org.wso2.carbon.identity.oauth2.rar.util.TestConstants.TEST_TYPE;
+import static org.wso2.carbon.identity.oauth2.rar.util.TestDAOUtils.closeMockedStatic;
/**
* Test class for {@link AuthorizationDetailsDAO}.
@@ -55,6 +60,7 @@
public class AuthorizationDetailsDAOImplTest {
private MockedStatic identityDatabaseUtilMock;
+ private MockedStatic authorizationDetailsTypesUtilMock;
private AuthorizationDetailsDAO uut;
@BeforeClass
@@ -62,22 +68,21 @@ public void setUp() throws SQLException {
this.uut = new AuthorizationDetailsDAOImpl();
TestDAOUtils.initializeDataSource(TEST_DB_NAME, TestDAOUtils.getFilePath("h2.sql"));
this.identityDatabaseUtilMock = Mockito.mockStatic(IdentityDatabaseUtil.class);
+ this.authorizationDetailsTypesUtilMock = Mockito.mockStatic(AuthorizationDetailsTypesUtil.class);
}
@AfterClass
public void tearDown() throws SQLException {
- if (this.identityDatabaseUtilMock != null && !this.identityDatabaseUtilMock.isClosed()) {
- this.identityDatabaseUtilMock.close();
- }
+ closeMockedStatic(this.identityDatabaseUtilMock);
+ closeMockedStatic(this.authorizationDetailsTypesUtilMock);
}
@BeforeMethod
public void setUpBeforeMethod() throws SQLException {
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
+ this.mockAuthorizationDetailsTypesUtil(true);
}
@Test
@@ -85,9 +90,7 @@ public void testAddUserConsentedAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
testAuthorizationDetail.setType(TEST_TYPE);
@@ -114,13 +117,43 @@ public void testGetUserConsentedAuthorizationDetails() throws SQLException {
}
@Test(priority = 2)
+ public void testUpdateUserConsentedAuthorizationDetails() throws SQLException {
+
+ final String identifier = UUID.randomUUID().toString();
+ Set existingConsentDTOs =
+ this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID);
+
+ this.mockIdentityDatabaseUtil();
+
+ AuthorizationDetailsConsentDTO existingDTO = existingConsentDTOs.iterator().next();
+ Assert.assertTrue(StringUtils.isEmpty(existingDTO.getAuthorizationDetail().getIdentifier()));
+
+ AuthorizationDetail authorizationDetailToUpdate = existingDTO.getAuthorizationDetail();
+ authorizationDetailToUpdate.setIdentifier(identifier);
+
+ AuthorizationDetailsConsentDTO consentDTO = new AuthorizationDetailsConsentDTO(existingDTO.getConsentId(),
+ authorizationDetailToUpdate, existingDTO.isConsentActive(), existingDTO.getTenantId());
+
+ int[] result = uut.updateUserConsentedAuthorizationDetails(Collections.singleton(consentDTO));
+ assertEquals(1, result.length);
+
+ this.mockIdentityDatabaseUtil();
+
+ Set updatedConsentDTOs =
+ this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID);
+ AuthorizationDetailsConsentDTO updatedDto = updatedConsentDTOs.iterator().next();
+
+ assertEquals(existingConsentDTOs.size(), updatedConsentDTOs.size());
+ assertEquals(existingDTO.getAuthorizationDetail().getType(), updatedDto.getAuthorizationDetail().getType());
+ assertEquals(identifier, updatedDto.getAuthorizationDetail().getIdentifier());
+ }
+
+ @Test(dependsOnMethods = "testUpdateUserConsentedAuthorizationDetails")
public void testDeleteUserConsentedAuthorizationDetails() throws SQLException {
assertEquals(1, uut.deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID));
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
}
@@ -129,9 +162,7 @@ public void testDeleteUserConsentedAuthorizationDetails() throws SQLException {
public void testAddAccessTokenAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
testAuthorizationDetail.setType(TEST_TYPE);
@@ -161,9 +192,7 @@ public void testGetAccessTokenAuthorizationDetails() throws SQLException {
public void testDeleteAccessTokenAuthorizationDetails() throws SQLException {
assertEquals(1, uut.deleteAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID));
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
}
@@ -172,9 +201,7 @@ public void testDeleteAccessTokenAuthorizationDetails() throws SQLException {
public void testAddOAuth2CodeAuthorizationDetails() throws SQLException {
assertEquals(0, this.uut.getOAuth2CodeAuthorizationDetails(TEST_CODE_ID, TEST_TENANT_ID).size());
- this.identityDatabaseUtilMock
- .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
- .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ this.mockIdentityDatabaseUtil();
AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
testAuthorizationDetail.setType(TEST_TYPE);
@@ -237,4 +264,48 @@ public void shouldReturnNull_whenUserIdOrAppIdInvalid() throws SQLException {
assertNull(this.uut.getConsentIdByUserIdAndAppId("invalid_user_id", "invalid_app_id", TEST_TENANT_ID));
}
+
+ @Test
+ public void testUserConsentedAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
+
+ this.mockAuthorizationDetailsTypesUtil(false);
+
+ assertEquals(0, this.uut.addUserConsentedAuthorizationDetails(Collections.emptySet()).length);
+ assertEquals(0, this.uut.updateUserConsentedAuthorizationDetails(Collections.emptySet()).length);
+ assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
+ assertEquals(-1, this.uut.deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID));
+ }
+
+ @Test
+ public void testAccessTokenAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
+
+ this.mockAuthorizationDetailsTypesUtil(false);
+
+ assertEquals(0, uut.addAccessTokenAuthorizationDetails(Collections.emptySet()).length);
+ assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
+ assertEquals(-1, this.uut.deleteAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID));
+ }
+
+ @Test
+ public void testOAuth2CodeAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
+
+ this.mockAuthorizationDetailsTypesUtil(false);
+
+ assertEquals(0, uut.addOAuth2CodeAuthorizationDetails(Collections.emptySet()).length);
+ assertEquals(0, this.uut.getOAuth2CodeAuthorizationDetails(TEST_AUTHORIZATION_CODE, TEST_TENANT_ID).size());
+ }
+
+ private void mockAuthorizationDetailsTypesUtil(boolean isRichAuthorizationRequestsEnabled) {
+
+ this.authorizationDetailsTypesUtilMock
+ .when(AuthorizationDetailsTypesUtil::isRichAuthorizationRequestsDisabled)
+ .thenReturn(!isRichAuthorizationRequestsEnabled);
+ }
+
+ private void mockIdentityDatabaseUtil() throws SQLException {
+
+ this.identityDatabaseUtilMock
+ .when(() -> IdentityDatabaseUtil.getDBConnection(any(Boolean.class)))
+ .thenReturn(TestDAOUtils.getConnection(TEST_DB_NAME));
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
index fe2e3b0dd8..d9fd51e2f1 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/util/TestDAOUtils.java
@@ -20,6 +20,7 @@
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.StringUtils;
+import org.mockito.MockedStatic;
import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
import java.nio.file.Paths;
@@ -66,6 +67,13 @@ public static String getFilePath(String fileName) {
return null;
}
+ public static void closeMockedStatic(final MockedStatic> mockedStatic) {
+
+ if (mockedStatic != null && !mockedStatic.isClosed()) {
+ mockedStatic.close();
+ }
+ }
+
/**
* Test authorization detail class which extends AuthorizationDetail
*/
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
index a9f1307804..c2c0d44ecf 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/AuthorizationHandlerManager.java
@@ -41,7 +41,6 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
-import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.util.AuthzUtil;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.validators.DefaultOAuth2ScopeValidator;
@@ -256,7 +255,6 @@ public OAuth2AuthorizeRespDTO handleAuthorization(OAuthAuthzReqMessageContext au
// set the authorization request context to be used by downstream handlers. This is introduced as a fix for
// IDENTITY-4111
OAuth2Util.setAuthzRequestContext(authzReqMsgCtx);
- AuthorizationDetailsUtils.setRARPropertiesToAuthzRequestContext(authzReqMsgCtx);
authorizeRespDTO = authzHandler.issue(authzReqMsgCtx);
} finally {
// clears authorization request context
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
index 8b7cc822f4..8b4e677500 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/OAuthAuthzReqMessageContext.java
@@ -57,7 +57,9 @@ public class OAuthAuthzReqMessageContext implements Serializable {
private Properties properties = new Properties();
- private AuthorizationDetails authorizationDetails;
+ private AuthorizationDetails approvedAuthorizationDetails;
+
+ private AuthorizationDetails requestedAuthorizationDetails;
public OAuthAuthzReqMessageContext(OAuth2AuthorizeReqDTO authorizationReqDTO) {
@@ -217,24 +219,46 @@ public void setSubjectTokenFlow(boolean subjectTokenFlow) {
}
/**
- * Retrieves the current authorization details.
+ * Retrieves the user approved authorization details.
+ *
+ * @return the {@link AuthorizationDetails} instance representing the approved authorization information.
+ * If no authorization details are available, it will return {@code null}.
+ */
+ public AuthorizationDetails getApprovedAuthorizationDetails() {
+
+ return this.approvedAuthorizationDetails;
+ }
+
+ /**
+ * Sets the approved authorization details.
+ * This method updates the approved authorization details with the provided {@link AuthorizationDetails} instance.
+ *
+ * @param approvedAuthorizationDetails the approved {@link AuthorizationDetails} to set.
+ */
+ public void setApprovedAuthorizationDetails(final AuthorizationDetails approvedAuthorizationDetails) {
+
+ this.approvedAuthorizationDetails = approvedAuthorizationDetails;
+ }
+
+ /**
+ * Retrieves the requested authorization details.
*
- * @return the {@link AuthorizationDetails} instance representing the current authorization information.
+ * @return the {@link AuthorizationDetails} instance representing the authorization information came in the request.
* If no authorization details are available, it will return {@code null}.
*/
- public AuthorizationDetails getAuthorizationDetails() {
+ public AuthorizationDetails getRequestedAuthorizationDetails() {
- return this.authorizationDetails;
+ return this.requestedAuthorizationDetails;
}
/**
- * Sets the authorization details.
- * This method updates the authorization details with the provided {@link AuthorizationDetails} instance.
+ * Sets the requested authorization details.
+ * This method updates the requested authorization details with the provided {@link AuthorizationDetails} instance.
*
- * @param authorizationDetails the {@link AuthorizationDetails} to set.
+ * @param requestedAuthorizationDetails the requested {@link AuthorizationDetails} to set.
*/
- public void setAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
+ public void setRequestedAuthorizationDetails(final AuthorizationDetails requestedAuthorizationDetails) {
- this.authorizationDetails = authorizationDetails;
+ this.requestedAuthorizationDetails = requestedAuthorizationDetails;
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
index 4be8704f12..89c099d9a2 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/AbstractResponseTypeHandler.java
@@ -225,7 +225,7 @@ public OAuth2AuthorizeRespDTO initResponse(OAuthAuthzReqMessageContext oauthAuth
OAuth2AuthorizeReqDTO authorizationReqDTO = oauthAuthzMsgCtx.getAuthorizationReqDTO();
respDTO.setCallbackURI(authorizationReqDTO.getCallbackUrl());
respDTO.setScope(oauthAuthzMsgCtx.getApprovedScope());
- respDTO.setAuthorizationDetails(oauthAuthzMsgCtx.getAuthorizationDetails());
+ respDTO.setAuthorizationDetails(oauthAuthzMsgCtx.getApprovedAuthorizationDetails());
return respDTO;
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
index 11e412a9d2..cf1ad3ea89 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
@@ -18,6 +18,7 @@
package org.wso2.carbon.identity.oauth2.rar;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
@@ -47,8 +48,8 @@
import java.util.Optional;
import java.util.Set;
-import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.getAuthorizationDetailsConsentDTOs;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.getAuthorizationDetailsTypesMap;
+import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.isEmpty;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils.isRichAuthorizationRequest;
/**
@@ -94,14 +95,15 @@ public AuthorizationDetailsService() {
public AuthorizationDetailsService(final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory,
final AuthorizationDetailsDAO authorizationDetailsDAO) {
- this.authorizationDetailsDAO = Objects
- .requireNonNull(authorizationDetailsDAO, "AuthorizationDetailsDAO must not be null");
+ this.authorizationDetailsDAO =
+ Objects.requireNonNull(authorizationDetailsDAO, "AuthorizationDetailsDAO must not be null");
this.authorizationDetailsProcessorFactory = Objects.requireNonNull(authorizationDetailsProcessorFactory,
"AuthorizationDetailsProviderFactory must not be null");
}
/**
- * Stores user-consented authorization details.
+ * Persists or updates user-consented authorization details. If previously stored authorization details are found,
+ * they are updated with the new information.
*
* @param authenticatedUser The authenticated user.
* @param clientId The client ID.
@@ -109,9 +111,9 @@ public AuthorizationDetailsService(final AuthorizationDetailsProcessorFactory au
* @param userConsentedAuthorizationDetails User consented authorization details.
* @throws OAuthSystemException if an error occurs while storing user consented authorization details.
*/
- public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authenticatedUser, final String clientId,
- final OAuth2Parameters oAuth2Parameters,
- final AuthorizationDetails userConsentedAuthorizationDetails)
+ public void storeOrUpdateUserConsentedAuthorizationDetails(
+ final AuthenticatedUser authenticatedUser, final String clientId, final OAuth2Parameters oAuth2Parameters,
+ final AuthorizationDetails userConsentedAuthorizationDetails)
throws OAuthSystemException {
if (!isRichAuthorizationRequest(oAuth2Parameters)) {
@@ -121,19 +123,48 @@ public void storeUserConsentedAuthorizationDetails(final AuthenticatedUser authe
try {
final int tenantId = OAuth2Util.getTenantId(oAuth2Parameters.getTenantDomain());
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
+ final Optional optConsentId = this.getConsentId(authenticatedUser, clientId, tenantId);
- if (consentId.isPresent()) {
- final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
- .getTrimmedAuthorizationDetails(userConsentedAuthorizationDetails);
+ if (!optConsentId.isPresent()) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Unable to find a consent for userId %s and appId %s",
+ authenticatedUser.getLoggableMaskedUserId(), clientId));
+ }
+ return;
+ }
- final Set authorizationDetailsConsentDTOs =
- getAuthorizationDetailsConsentDTOs(consentId.get(), trimmedAuthorizationDetails, tenantId);
+ final String consentId = optConsentId.get();
+ final Set authorizationDetailsToBeUpdated = new HashSet<>();
+ final Set authorizationDetailsToBeAdded = new HashSet<>();
- this.authorizationDetailsDAO.addUserConsentedAuthorizationDetails(authorizationDetailsConsentDTOs);
+ final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
+ .getTrimmedAuthorizationDetails(userConsentedAuthorizationDetails);
+ final Map> consentedAuthorizationDetailsByType =
+ getAuthorizationDetailsTypesMap(this.getUserConsentedAuthorizationDetails(consentId, tenantId));
+
+ // Determine new authorization details to add or update based on the existing user consent
+ trimmedAuthorizationDetails.stream().forEach(authorizationDetail -> {
+ final AuthorizationDetailsConsentDTO authorizationDetailsConsentDTO =
+ new AuthorizationDetailsConsentDTO(consentId, authorizationDetail, true, tenantId);
+
+ if (isUserConsentedAuthorizationDetailsType(authorizationDetail, consentedAuthorizationDetailsByType)) {
+ authorizationDetailsToBeUpdated.add(authorizationDetailsConsentDTO);
+ } else {
+ authorizationDetailsToBeAdded.add(authorizationDetailsConsentDTO);
+ }
+ });
+
+ if (CollectionUtils.isNotEmpty(authorizationDetailsToBeUpdated)) {
+ this.authorizationDetailsDAO.updateUserConsentedAuthorizationDetails(authorizationDetailsToBeUpdated);
if (log.isDebugEnabled()) {
- log.debug("User consented authorization details stored successfully. consentId: " +
- consentId.get());
+ log.debug("User consented authorization details updated. consentId: " + consentId);
+ }
+ }
+
+ if (CollectionUtils.isNotEmpty(authorizationDetailsToBeAdded)) {
+ this.authorizationDetailsDAO.addUserConsentedAuthorizationDetails(authorizationDetailsToBeAdded);
+ if (log.isDebugEnabled()) {
+ log.debug("User consented authorization details stored. consentId: " + consentId);
}
}
} catch (SQLException | IdentityOAuth2Exception e) {
@@ -192,7 +223,7 @@ public void replaceUserConsentedAuthorizationDetails(
final AuthorizationDetails userConsentedAuthorizationDetails) throws OAuthSystemException {
this.deleteUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters);
- this.storeUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters,
+ this.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, clientId, oAuth2Parameters,
userConsentedAuthorizationDetails);
}
@@ -212,7 +243,7 @@ public boolean isUserAlreadyConsentedForAuthorizationDetails(final Authenticated
return true;
}
- return this.getConsentRequiredAuthorizationDetails(authenticatedUser, oAuth2Parameters).getDetails().isEmpty();
+ return isEmpty(this.getConsentRequiredAuthorizationDetails(authenticatedUser, oAuth2Parameters));
}
public AuthorizationDetails getConsentRequiredAuthorizationDetails(final AuthenticatedUser authenticatedUser,
@@ -224,8 +255,8 @@ public AuthorizationDetails getConsentRequiredAuthorizationDetails(final Authent
return new AuthorizationDetails();
}
- final Map> consentedAuthorizationDetailsByType =
- this.getUserConsentedAuthorizationDetailsByType(authenticatedUser, oAuth2Parameters);
+ Map> consentedAuthorizationDetailsByType = getAuthorizationDetailsTypesMap(
+ this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters));
final Set consentRequiredAuthorizationDetails = new HashSet<>();
oAuth2Parameters.getAuthorizationDetails().stream()
@@ -236,14 +267,6 @@ public AuthorizationDetails getConsentRequiredAuthorizationDetails(final Authent
return new AuthorizationDetails(consentRequiredAuthorizationDetails);
}
- private Map> getUserConsentedAuthorizationDetailsByType(
- final AuthenticatedUser authenticatedUser, final OAuth2Parameters oAuth2Parameters)
- throws IdentityOAuth2Exception {
-
- return getAuthorizationDetailsTypesMap(
- this.getUserConsentedAuthorizationDetails(authenticatedUser, oAuth2Parameters));
- }
-
/**
* Checks if the user has already consented to the requested authorization detail.
*
@@ -258,15 +281,12 @@ private boolean isUserConsentedAuthorizationDetail(
final AuthorizationDetail requestedAuthorizationDetail,
final Map> consentedAuthorizationDetailsByType) {
- final String requestedType = requestedAuthorizationDetail.getType();
- if (!consentedAuthorizationDetailsByType.containsKey(requestedType)) {
- if (log.isDebugEnabled()) {
- log.debug(String.format("User hasn't consented for the requested authorization details type '%s'.",
- requestedType));
- }
+ if (!this.isUserConsentedAuthorizationDetailsType(requestedAuthorizationDetail,
+ consentedAuthorizationDetailsByType)) {
return false;
}
+ final String requestedType = requestedAuthorizationDetail.getType();
final Optional optProcessor =
this.authorizationDetailsProcessorFactory.getAuthorizationDetailsProcessorByType(requestedType);
@@ -295,6 +315,20 @@ private boolean isUserConsentedAuthorizationDetail(
return false;
}
+ private boolean isUserConsentedAuthorizationDetailsType(
+ final AuthorizationDetail requestedAuthorizationDetail,
+ final Map> consentedAuthorizationDetailsByType) {
+
+ if (consentedAuthorizationDetailsByType.containsKey(requestedAuthorizationDetail.getType())) {
+ return true;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("User hasn't consented for the requested authorization details type '%s'",
+ requestedAuthorizationDetail.getType()));
+ }
+ return false;
+ }
+
/**
* Retrieves the user consented authorization details for a given user and OAuth2 parameters.
*
@@ -324,22 +358,28 @@ public AuthorizationDetails getUserConsentedAuthorizationDetails(
final AuthenticatedUser authenticatedUser, final String clientId, final int tenantId)
throws IdentityOAuth2Exception {
+ final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
+ if (consentId.isPresent()) {
+ return this.getUserConsentedAuthorizationDetails(consentId.get(), tenantId);
+ }
+ return null;
+ }
+
+ public AuthorizationDetails getUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
+ throws IdentityOAuth2Exception {
+
try {
- final Optional consentId = this.getConsentId(authenticatedUser, clientId, tenantId);
- if (consentId.isPresent()) {
- final Set consentedAuthorizationDetails = new HashSet<>();
- this.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId.get(), tenantId)
- .stream()
- .filter(AuthorizationDetailsConsentDTO::isConsentActive)
- .map(AuthorizationDetailsConsentDTO::getAuthorizationDetail)
- .forEach(consentedAuthorizationDetails::add);
- return new AuthorizationDetails(consentedAuthorizationDetails);
- }
+ final Set consentedAuthorizationDetails = new HashSet<>();
+ this.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId, tenantId)
+ .stream()
+ .filter(AuthorizationDetailsConsentDTO::isConsentActive)
+ .map(AuthorizationDetailsConsentDTO::getAuthorizationDetail)
+ .forEach(consentedAuthorizationDetails::add);
+ return new AuthorizationDetails(consentedAuthorizationDetails);
} catch (SQLException e) {
log.error("Error occurred while retrieving user consented authorization details. Caused by, ", e);
throw new IdentityOAuth2Exception("Unable to retrieve user consented authorization details", e);
}
- return null;
}
/**
@@ -422,12 +462,13 @@ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessToken
final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
throws IdentityOAuth2Exception {
- if (!isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
+ if (!isRichAuthorizationRequest(oAuthAuthzReqMessageContext.getApprovedAuthorizationDetails())) {
log.debug("Request is not a rich authorization request. Skipping storage of token authorization details.");
return;
}
- this.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthAuthzReqMessageContext.getAuthorizationDetails());
+ this.storeAccessTokenAuthorizationDetails(accessTokenDO,
+ oAuthAuthzReqMessageContext.getApprovedAuthorizationDetails());
}
/**
@@ -441,6 +482,10 @@ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessToken
final AuthorizationDetails authorizationDetails)
throws IdentityOAuth2Exception {
+ if (AuthorizationDetailsUtils.isEmpty(authorizationDetails)) {
+ return;
+ }
+
try {
final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
.getTrimmedAuthorizationDetails(authorizationDetails);
@@ -498,8 +543,8 @@ public void deleteAccessTokenAuthorizationDetails(final String accessTokenId, fi
throws IdentityOAuth2Exception {
try {
- this.authorizationDetailsDAO.deleteAccessTokenAuthorizationDetails(accessTokenId, tenantId);
- if (log.isDebugEnabled()) {
+ int result = this.authorizationDetailsDAO.deleteAccessTokenAuthorizationDetails(accessTokenId, tenantId);
+ if (result > 0 && log.isDebugEnabled()) {
log.debug("Access token authorization details deleted successfully. accessTokenId: " + accessTokenId);
}
} catch (SQLException e) {
@@ -570,7 +615,7 @@ public void storeAuthorizationCodeAuthorizationDetails(
final Set authorizationDetailsCodeDTOs =
AuthorizationDetailsUtils.getCodeAuthorizationDetailsDTOs(authzCodeDO,
- oAuthAuthzReqMessageContext.getAuthorizationDetails(), tenantId);
+ oAuthAuthzReqMessageContext.getApprovedAuthorizationDetails(), tenantId);
// Storing the authorization details.
this.authorizationDetailsDAO.addOAuth2CodeAuthorizationDetails(authorizationDetailsCodeDTOs);
@@ -588,17 +633,17 @@ public void storeAuthorizationCodeAuthorizationDetails(
/**
* Retrieves the authorization details associated with a given authorization code Id.
*
- * @param codeId The authorization code ID.
+ * @param code The authorization code.
* @param tenantId The tenant ID.
* @return The authorization code authorization details.
* @throws IdentityOAuth2Exception If an error occurs while retrieving the details.
*/
- public AuthorizationDetails getAuthorizationCodeAuthorizationDetails(final String codeId, final int tenantId)
+ public AuthorizationDetails getAuthorizationCodeAuthorizationDetails(final String code, final int tenantId)
throws IdentityOAuth2Exception {
try {
final Set authorizationDetailsCodeDTOs =
- this.authorizationDetailsDAO.getOAuth2CodeAuthorizationDetails(codeId, tenantId);
+ this.authorizationDetailsDAO.getOAuth2CodeAuthorizationDetails(code, tenantId);
final Set codeAuthorizationDetails = new HashSet<>();
authorizationDetailsCodeDTOs
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
index 3743515386..1c55095726 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/core/AuthorizationDetailsProcessorFactory.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
@@ -122,11 +123,16 @@ public Set getSupportedAuthorizationDetailTypes() {
final String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
try {
- return OAuth2ServiceComponentHolder.getInstance().getAuthorizationDetailsTypeManager()
- .getAuthorizationDetailsTypes(StringUtils.EMPTY, tenantDomain)
- .stream()
- .map(AuthorizationDetailsType::getType)
- .collect(Collectors.toUnmodifiableSet());
+
+ final List authorizationDetailsTypes = OAuth2ServiceComponentHolder.getInstance()
+ .getAuthorizationDetailsTypeManager().getAuthorizationDetailsTypes(StringUtils.EMPTY, tenantDomain);
+
+ if (authorizationDetailsTypes != null) {
+ return authorizationDetailsTypes
+ .stream()
+ .map(AuthorizationDetailsType::getType)
+ .collect(Collectors.toUnmodifiableSet());
+ }
} catch (APIResourceMgtException e) {
if (log.isDebugEnabled()) {
log.debug(String.format("Error occurred while retrieving supported authorization details types " +
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
index a6d4baa1cd..f2d618e85a 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
@@ -38,8 +38,8 @@ public Map getAdditionalTokenResponseAttributes(
if (isRichAuthorizationRequest(oAuthTokenReqMessageContext.getAuthorizationDetails())) {
if (log.isDebugEnabled()) {
- log.debug("Processing Rich Authorization Request in token flow. authorization_details: " +
- oAuthTokenReqMessageContext.getAuthorizationDetails().toJsonString());
+ log.debug("Adding authorization details into the token response: " + oAuthTokenReqMessageContext
+ .getAuthorizationDetails().toReadableText());
}
additionalAttributes.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
oAuthTokenReqMessageContext.getAuthorizationDetails().toSet());
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
index d429390131..cdbe9c2425 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
@@ -36,10 +36,10 @@ public Map getAdditionalClaims(final OAuthAuthzReqMessageContext
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
if (log.isDebugEnabled()) {
log.debug("Processing Rich Authorization Request in authorization flow. authorization_details: " +
- oAuthAuthzReqMessageContext.getAuthorizationDetails().toJsonString());
+ oAuthAuthzReqMessageContext.getRequestedAuthorizationDetails().toJsonString());
}
additionalClaims.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
- oAuthAuthzReqMessageContext.getAuthorizationDetails().toSet());
+ oAuthAuthzReqMessageContext.getApprovedAuthorizationDetails().toSet());
}
return additionalClaims;
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
index 5f9cc82d41..ebd9ebdad5 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/util/AuthorizationDetailsUtils.java
@@ -25,11 +25,9 @@
import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
-import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
-import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.AuthzCodeDO;
import org.wso2.carbon.identity.oauth2.model.CarbonOAuthTokenRequest;
@@ -75,7 +73,7 @@ public class AuthorizationDetailsUtils {
*/
public static boolean isRichAuthorizationRequest(final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) {
- return isRichAuthorizationRequest(oAuthAuthzReqMessageContext.getAuthorizationDetails());
+ return isRichAuthorizationRequest(oAuthAuthzReqMessageContext.getRequestedAuthorizationDetails());
}
/**
@@ -313,7 +311,7 @@ public static AuthorizationDetails getDisplayableAuthorizationDetails(
*/
public static AuthorizationDetails getTrimmedAuthorizationDetails(final AuthorizationDetails authorizationDetails) {
- if (authorizationDetails != null) {
+ if (!isEmpty(authorizationDetails)) {
authorizationDetails.stream().forEach(authorizationDetail -> {
authorizationDetail.setId(null);
authorizationDetail.setDescription(null);
@@ -370,31 +368,6 @@ public static String getUrlDecodedAuthorizationDetails(final String encodedAutho
return StringUtils.EMPTY;
}
- public static void setRARPropertiesToAuthzRequestContext(
- final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext) throws IdentityOAuth2Exception {
-
- OAuth2AuthorizeReqDTO oAuth2AuthorizeReqDTO = oAuthAuthzReqMessageContext.getAuthorizationReqDTO();
- if (!AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuth2AuthorizeReqDTO)) {
- if (log.isDebugEnabled()) {
- log.debug("Request is not a rich authorization request. " +
- "Skips adding authorization details to OAuthAuthzReqMessageContext");
- }
- return;
- }
-
- final AuthorizationDetails authorizationDetails = OAuth2ServiceComponentHolder.getInstance()
- .getAuthorizationDetailsService()
- .getUserConsentedAuthorizationDetails(
- oAuth2AuthorizeReqDTO.getUser(),
- oAuth2AuthorizeReqDTO.getConsumerKey(),
- IdentityTenantUtil.getTenantId(oAuth2AuthorizeReqDTO.getTenantDomain())
- );
-
- if (authorizationDetails != null) {
- oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
- }
- }
-
/**
* Determines if the given {@link OAuth2AuthorizeReqDTO} object contains {@link AuthorizationDetails}.
*
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
index cc42caeb32..6dce155dc5 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidator.java
@@ -399,9 +399,9 @@ private boolean isSchemaCompliant(final String type, final AuthorizationDetail a
if (!authorizedDetailsTypes.containsKey(type)) {
if (log.isDebugEnabled()) {
- log.debug("Ignoring unauthorized authorization details type: " + type);
+ log.debug("Request received for unauthorized authorization details type: " + type);
}
- return false;
+ throw new AuthorizationDetailsProcessingException(VALIDATION_FAILED_ERR_MSG);
}
if (this.authorizationDetailsSchemaValidator
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
index 15dd3b7264..c69bcaf991 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AbstractAuthorizationGrantHandler.java
@@ -58,7 +58,6 @@
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
-import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.OauthTokenIssuer;
@@ -433,7 +432,7 @@ private OAuth2AccessTokenRespDTO issueExistingAccessToken(OAuthTokenReqMessageCo
existingTokenBean.getTokenId(), true);
}
- if (AuthorizationDetailsUtils.isRichAuthorizationRequest(tokReqMsgCtx)) {
+ if (AuthorizationDetailsUtils.isRichAuthorizationRequest(tokReqMsgCtx.getAuthorizationDetails())) {
this.authorizationDetailsService.replaceAccessTokenAuthorizationDetails(existingTokenBean.getTokenId(),
existingTokenBean, tokReqMsgCtx);
}
@@ -1239,43 +1238,4 @@ private boolean isFederatedUser(OAuthTokenReqMessageContext tokReqMsgCtx) {
}
return tokReqMsgCtx.getAuthorizedUser().isFederatedUser();
}
-
- /**
- * Sets the Rich Authorization Requests (RAR) properties for token generation.
- * It retrieves the user-consented authorization details or fallback to code authorization details
- * based on the provided OAuth token request context.
- *
- * @param oAuthTokenReqMessageContext Context of the OAuth token request message.
- * @throws IdentityOAuth2Exception If an error occurs while retrieving authorization details.
- */
- protected void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
- throws IdentityOAuth2Exception {
-
- final int tenantId =
- OAuth2Util.getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
-
- if (log.isDebugEnabled()) {
- log.debug("Retrieving user consented authorization details for user: "
- + oAuthTokenReqMessageContext.getAuthorizedUser().getLoggableMaskedUserId());
- }
-
- AuthorizationDetails authorizationDetails = this.authorizationDetailsService
- .getUserConsentedAuthorizationDetails(
- oAuthTokenReqMessageContext.getAuthorizedUser(),
- oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getClientId(),
- tenantId);
-
- // Fallback to code authorization details if user consent is unavailable
- if (authorizationDetails == null) {
- if (log.isDebugEnabled()) {
- log.debug("No user consent is available. Fetching authorization details for code: " +
- oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode());
- }
-
- authorizationDetails = this.authorizationDetailsService.getAuthorizationCodeAuthorizationDetails(
- oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode(), tenantId);
- }
- oAuthTokenReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
- .getTrimmedAuthorizationDetails(authorizationDetails));
- }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
index e111552248..6c627cb759 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/AuthorizationCodeGrantHandler.java
@@ -49,6 +49,8 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.AuthzCodeDO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.utils.DiagnosticLog;
@@ -134,7 +136,7 @@ private void setPropertiesForTokenGeneration(OAuthTokenReqMessageContext tokReqM
// keep the pre processed authz code as a OAuthTokenReqMessageContext property to avoid
// calculating it again when issuing the access token.
tokReqMsgCtx.addProperty(AUTHZ_CODE, tokenReq.getAuthorizationCode());
- super.setRARPropertiesForTokenGeneration(tokReqMsgCtx);
+ this.setRARPropertiesForTokenGeneration(tokReqMsgCtx);
}
private boolean validateCallbackUrlFromRequest(String callbackUrlFromRequest,
@@ -672,4 +674,35 @@ private String resolveUserResidentOrganization(Map userAtt
}
return null;
}
+
+ /**
+ * Configures RAR properties for token generation in the OAuth 2.0 flow.
+ *
+ * It checks if authorization details were included in the authorization code request and whether the
+ * user has consented to these specific authorization details. Depending on user consent, it selects
+ * the appropriate authorization details to be included in the token response.
+ *
+ *
+ * @param oAuthTokenReqMessageContext Context of the OAuth token request message.
+ * @throws IdentityOAuth2Exception If an error occurs while retrieving authorization details.
+ */
+ private void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ final int tenantId =
+ OAuth2Util.getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
+
+ if (log.isDebugEnabled()) {
+ log.debug("Retrieving user consented authorization details for user: "
+ + oAuthTokenReqMessageContext.getAuthorizedUser().getLoggableMaskedUserId());
+ }
+
+ final AuthorizationDetails authorizationCodeAuthorizationDetails = super.authorizationDetailsService
+ .getAuthorizationCodeAuthorizationDetails(
+ oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getAuthorizationCode(),
+ tenantId);
+
+ oAuthTokenReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
+ .getTrimmedAuthorizationDetails(authorizationCodeAuthorizationDetails));
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
index 858134956f..b69dacdcf9 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandler.java
@@ -59,6 +59,8 @@
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
import org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.OauthTokenIssuer;
@@ -221,7 +223,7 @@ public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx)
/**
* Build and return a string to be used as a lock for synchronous token issuance for refresh token grant type.
*
- * @param tokReqMsgCtx OAuthTokenReqMessageContext
+ * @param tokReqMsgCtx OAuthTokenReqMessageContext
* @return A string to be used as a lock for synchronous token issuance for refresh token grant type.
*/
public String buildSyncLockString(OAuthTokenReqMessageContext tokReqMsgCtx) {
@@ -253,7 +255,7 @@ private void setPropertiesForTokenGeneration(OAuthTokenReqMessageContext tokReqM
// Store the old access token as a OAuthTokenReqMessageContext property, this is already
// a preprocessed token.
tokReqMsgCtx.addProperty(PREV_ACCESS_TOKEN, validationBean);
- super.setRARPropertiesForTokenGeneration(tokReqMsgCtx);
+ this.setRARPropertiesForTokenGeneration(tokReqMsgCtx, validationBean);
}
private boolean validateRefreshTokenInRequest(OAuth2AccessTokenReqDTO tokenReq,
@@ -894,4 +896,31 @@ private RefreshTokenGrantProcessor getRefreshTokenGrantProcessor() {
return OAuth2ServiceComponentHolder.getInstance().getRefreshTokenGrantProcessor();
}
+
+ /**
+ * Sets the RAR properties for token generation.
+ * It retrieves the token authorization details based on the provided OAuth token request context.
+ *
+ * @param oAuthTokenReqMessageContext Context of the OAuth token request message.
+ * @param validationBean Refresh token validation data.
+ * @throws IdentityOAuth2Exception If an error occurs while retrieving authorization details.
+ */
+ private void setRARPropertiesForTokenGeneration(final OAuthTokenReqMessageContext oAuthTokenReqMessageContext,
+ final RefreshTokenValidationDataDO validationBean)
+ throws IdentityOAuth2Exception {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Retrieving token authorization details for user: "
+ + oAuthTokenReqMessageContext.getAuthorizedUser().getLoggableMaskedUserId());
+ }
+
+ final int tenantId =
+ OAuth2Util.getTenantId(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO().getTenantDomain());
+
+ AuthorizationDetails tokenAuthorizationDetails = super.authorizationDetailsService
+ .getAccessTokenAuthorizationDetails(validationBean.getTokenId(), tenantId);
+
+ oAuthTokenReqMessageContext.setAuthorizationDetails(AuthorizationDetailsUtils
+ .getTrimmedAuthorizationDetails(tokenAuthorizationDetails));
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
index 987da89649..4df6f96e9d 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -155,7 +155,7 @@ public void setUpErrorMethod() throws SQLException {
public void shouldNotAddUserConsentedAuthorizationDetails_ifNotRichAuthorizationRequest()
throws OAuthSystemException, SQLException {
- uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ uut.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
new OAuth2Parameters(), authorizationDetails);
verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anySet());
@@ -168,7 +168,7 @@ public void shouldNotAddUserConsentedAuthorizationDetails_whenConsentIsNotFound(
final OAuth2Parameters oAuth2Parameters = new OAuth2Parameters();
oAuth2Parameters.setAuthorizationDetails(authorizationDetails);
- uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ uut.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anySet());
@@ -178,7 +178,10 @@ public void shouldNotAddUserConsentedAuthorizationDetails_whenConsentIsNotFound(
public void shouldAddUserConsentedAuthorizationDetails_ifRichAuthorizationRequest()
throws OAuthSystemException, SQLException {
- uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ when(this.authorizationDetailsDAOMock.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID))
+ .thenReturn(Collections.emptySet());
+
+ uut.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
verify(authorizationDetailsDAOMock, times(1)).addUserConsentedAuthorizationDetails(anySet());
@@ -218,6 +221,8 @@ public void shouldDeleteUserConsentedAuthorizationDetails_ifRichAuthorizationReq
public void shouldReplaceUserConsentedAuthorizationDetails_ifRichAuthorizationRequest()
throws OAuthSystemException, SQLException {
+ when(this.authorizationDetailsDAOMock.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID))
+ .thenReturn(Collections.emptySet());
uut.replaceUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
@@ -293,7 +298,7 @@ public void shouldAddAccessTokenAuthorizationDetails_ifRichAuthorizationRequest(
throws SQLException, IdentityOAuth2Exception {
OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext = new OAuthAuthzReqMessageContext(null);
- oAuthAuthzReqMessageContext.setAuthorizationDetails(authorizationDetails);
+ oAuthAuthzReqMessageContext.setApprovedAuthorizationDetails(authorizationDetails);
uut.storeAccessTokenAuthorizationDetails(accessTokenDO, oAuthAuthzReqMessageContext);
@@ -398,7 +403,7 @@ public void shouldReturnConsentRequiredAuthorizationDetails() throws IdentityOAu
public void shouldThrowOAuthSystemException_onUserConsentAuthorizationDetailsInsertionFailure()
throws OAuthSystemException {
- uut.storeUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
+ uut.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID,
oAuth2Parameters, authorizationDetails);
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
index b8bec6482f..8254b42634 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
@@ -86,7 +86,8 @@ public AuthorizationDetailsBaseTest() {
authorizeReqDTO.setAuthorizationDetails(this.authorizationDetails);
this.authzReqMessageContext = new OAuthAuthzReqMessageContext(authorizeReqDTO);
- this.authzReqMessageContext.setAuthorizationDetails(this.authorizationDetails);
+ this.authzReqMessageContext.setRequestedAuthorizationDetails(this.authorizationDetails);
+ this.authzReqMessageContext.setApprovedAuthorizationDetails(this.authorizationDetails);
this.accessTokenReqDTO = new OAuth2AccessTokenReqDTO();
this.accessTokenReqDTO.setAuthorizationDetails(authorizationDetails);
From faa5e3136d6609b39117838443bdcf3ea2066ad6 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Wed, 13 Nov 2024 20:08:37 +0530
Subject: [PATCH 11/28] Fix refresh token introspection issue
---
.../token/AccessTokenResponseRARHandler.java | 18 +++++++++
.../token/IntrospectionRARDataProvider.java | 39 +++++++++++++++++--
.../token/JWTAccessTokenRARClaimProvider.java | 26 +++++++++++--
pom.xml | 2 +-
4 files changed, 76 insertions(+), 9 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
index f2d618e85a..516eba5cd3 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/AccessTokenResponseRARHandler.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
import org.apache.commons.logging.Log;
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
index 150cf8de51..f185e9d2ed 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProvider.java
@@ -1,5 +1,24 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
@@ -22,6 +41,7 @@
import java.util.Objects;
import static org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsConstants.AUTHORIZATION_DETAILS;
+import static org.wso2.carbon.identity.oauth2.validators.RefreshTokenValidator.TOKEN_TYPE_NAME;
/**
* Class responsible for modifying the introspection response to include user-consented authorization details.
@@ -107,10 +127,8 @@ private OAuth2TokenValidationMessageContext generateOAuth2TokenValidationMessage
new OAuth2TokenValidationMessageContext(tokenValidationRequestDTO,
generateOAuth2TokenValidationResponseDTO(introspectionResponseDTO));
- final AccessTokenDO accessTokenDO = OAuth2ServiceComponentHolder.getInstance().getTokenProvider()
- .getVerifiedAccessToken(tokenValidationRequestDTO.getAccessToken().getIdentifier(), false);
-
- oAuth2TokenValidationMessageContext.addProperty(OAuthConstants.ACCESS_TOKEN_DO, accessTokenDO);
+ oAuth2TokenValidationMessageContext.addProperty(OAuthConstants.ACCESS_TOKEN_DO,
+ this.getVerifiedToken(tokenValidationRequestDTO, introspectionResponseDTO));
return oAuth2TokenValidationMessageContext;
}
@@ -130,4 +148,17 @@ private OAuth2TokenValidationResponseDTO generateOAuth2TokenValidationResponseDT
return tokenValidationResponseDTO;
}
+
+ private AccessTokenDO getVerifiedToken(final OAuth2TokenValidationRequestDTO tokenValidationRequestDTO,
+ final OAuth2IntrospectionResponseDTO introspectionResponseDTO)
+ throws IdentityOAuth2Exception {
+
+ if (StringUtils.equals(TOKEN_TYPE_NAME, introspectionResponseDTO.getTokenType())) {
+ return OAuth2ServiceComponentHolder.getInstance().getTokenProvider()
+ .getVerifiedRefreshToken(tokenValidationRequestDTO.getAccessToken().getIdentifier());
+ } else {
+ return OAuth2ServiceComponentHolder.getInstance().getTokenProvider()
+ .getVerifiedAccessToken(tokenValidationRequestDTO.getAccessToken().getIdentifier(), false);
+ }
+ }
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
index cdbe9c2425..dc4e10ac45 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/token/JWTAccessTokenRARClaimProvider.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.oauth2.rar.token;
import org.apache.commons.logging.Log;
@@ -35,8 +53,8 @@ public Map getAdditionalClaims(final OAuthAuthzReqMessageContext
final Map additionalClaims = new HashMap<>();
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
if (log.isDebugEnabled()) {
- log.debug("Processing Rich Authorization Request in authorization flow. authorization_details: " +
- oAuthAuthzReqMessageContext.getRequestedAuthorizationDetails().toJsonString());
+ log.debug("Adding authorization details into JWT token response in authorization flow: " +
+ oAuthAuthzReqMessageContext.getRequestedAuthorizationDetails().toReadableText());
}
additionalClaims.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
oAuthAuthzReqMessageContext.getApprovedAuthorizationDetails().toSet());
@@ -59,8 +77,8 @@ public Map getAdditionalClaims(final OAuthTokenReqMessageContext
final Map additionalClaims = new HashMap<>();
if (AuthorizationDetailsUtils.isRichAuthorizationRequest(oAuthTokenReqMessageContext)) {
if (log.isDebugEnabled()) {
- log.debug("Processing Rich Authorization Request in token flow.authorization_details: " +
- oAuthTokenReqMessageContext.getAuthorizationDetails().toJsonString());
+ log.debug("Adding authorization details into JWT token response in token flow: " +
+ oAuthTokenReqMessageContext.getAuthorizationDetails().toReadableText());
}
additionalClaims.put(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS,
oAuthTokenReqMessageContext.getAuthorizationDetails().toSet());
diff --git a/pom.xml b/pom.xml
index 535ef6a796..dba911544e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -952,7 +952,7 @@
[1.0.1, 2.0.0)
- 7.6.0
+ 7.6.8-SNAPSHOT
[5.25.234, 8.0.0)
From 4b205a490fc6cf0834c7656c1c4aad5dd0fd1db2 Mon Sep 17 00:00:00 2001
From: Shan Chathusanda Jayathilaka
Date: Tue, 17 Dec 2024 12:57:58 +0530
Subject: [PATCH 12/28] Improve user authorization check when accessing org is
different from resident org
---
.../org/wso2/carbon/identity/oauth2/util/AuthzUtil.java | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java
index 5811e251c0..29620bd069 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/AuthzUtil.java
@@ -255,7 +255,13 @@ public static boolean isUserAuthorized(AuthenticatedUser authenticatedUser, List
// Application id is not required for basic authentication flow.
List roleIds = getUserRoles(authenticatedUser, null);
- List permissions = getAssociatedScopesForRoles(roleIds, authenticatedUser.getTenantDomain());
+ String tenantDomain = authenticatedUser.getTenantDomain();
+ if (StringUtils.isNotBlank(authenticatedUser.getAccessingOrganization()) &&
+ !authenticatedUser.getAccessingOrganization().
+ equals(authenticatedUser.getUserResidentOrganization())) {
+ tenantDomain = getAccessingTenantDomain(authenticatedUser);
+ }
+ List permissions = getAssociatedScopesForRoles(roleIds, tenantDomain);
if (OAuthServerConfiguration.getInstance().isUseLegacyPermissionAccessForUserBasedAuth()) {
// Handling backward compatibility for previous access level.
List internalScopes = getInternalScopes(authenticatedUser.getTenantDomain());
From a8e87fe14365c6877ab774d88363620ed11104f2 Mon Sep 17 00:00:00 2001
From: sandushi
Date: Fri, 3 Jan 2025 17:00:22 +0530
Subject: [PATCH 13/28] Fix the issue of password expiry event trigger of
PasswordGrantHandler
---
.../handlers/grant/PasswordGrantHandler.java | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java
index bba4046100..5822cd1f35 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java
@@ -169,6 +169,11 @@ private Optional authenticateUserAtUserStore(OAuth2AccessTok
if (log.isDebugEnabled()) {
log.debug("user " + tokenReq.getResourceOwnerUsername() + " authenticated: " + authenticated);
}
+ triggerPasswordExpiryValidationEvent(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT, tenantAwareUserName,
+ userTenantDomain, userStoreManager, true);
+ if (log.isDebugEnabled()) {
+ log.debug(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT + " event is triggered");
+ }
if (authenticated) {
AuthenticatedUser authenticatedUser =
new AuthenticatedUser(authenticationResult.getAuthenticatedUser().get());
@@ -178,11 +183,6 @@ private Optional authenticateUserAtUserStore(OAuth2AccessTok
return Optional.of(authenticatedUser);
}
- triggerPasswordExpiryValidationEvent(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT, tenantAwareUserName,
- userTenantDomain, userStoreManager, true);
- if (log.isDebugEnabled()) {
- log.debug(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT + " event is triggered");
- }
return Optional.empty();
}
@@ -387,14 +387,14 @@ private AuthenticatedUser validateUserCredentials(OAuth2AccessTokenReqDTO tokenR
authenticatedUser = authenticateUserAtUserStore(tokenReq, userId, userStoreManager,
tenantAwareUserName, isPublishPasswordGrantLoginEnabled, userTenantDomain, serviceProvider);
}
- if (authenticatedUser.isPresent()) {
- return authenticatedUser.get();
- }
triggerPasswordExpiryValidationEvent(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT, tenantAwareUserName,
userTenantDomain, userStoreManager, false);
if (log.isDebugEnabled()) {
log.debug(PASSWORD_GRANT_POST_AUTHENTICATION_EVENT + " event is triggered");
}
+ if (authenticatedUser.isPresent()) {
+ return authenticatedUser.get();
+ }
if (isPublishPasswordGrantLoginEnabled) {
publishAuthenticationData(tokenReq, false, serviceProvider);
}
From 95792de333865a975e864ecf71d3b95dde045553 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 17 Jan 2025 09:39:31 +0530
Subject: [PATCH 14/28] Resolve test failures
---
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../identity/oauth2/rar/AuthorizationDetailsServiceTest.java | 2 ++
.../oauth2/rar/token/IntrospectionRARDataProviderTest.java | 4 +---
.../oauth2/rar/utils/AuthorizationDetailsBaseTest.java | 4 ++--
.../validator/DefaultAuthorizationDetailsValidatorTest.java | 5 ++++-
5 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 2e79ffbf4b..20fc5054ee 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.191-SNAPSHOT
+ 7.0.211-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
index 4df6f96e9d..e62c8b9702 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -34,6 +34,7 @@
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessor;
+import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory;
import org.wso2.carbon.identity.oauth2.rar.dao.AuthorizationDetailsDAO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsConsentDTO;
import org.wso2.carbon.identity.oauth2.rar.dto.AuthorizationDetailsTokenDTO;
@@ -126,6 +127,7 @@ public void setUpMethod()
when(processor.getType()).thenReturn(TEST_TYPE);
when(processor.validate(any(AuthorizationDetailsContext.class))).thenReturn(ValidationResult.valid());
+ this.processorFactoryMock = Mockito.mock(AuthorizationDetailsProcessorFactory.class);
when(this.processorFactoryMock.getAuthorizationDetailsProcessorByType(TEST_TYPE))
.thenReturn(Optional.of(processor));
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
index bb8a935e39..1a2d0d198e 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/token/IntrospectionRARDataProviderTest.java
@@ -79,11 +79,9 @@ public void shouldNotReturnAuthorizationDetails_ifNotRichAuthorizationRequest()
when(validatorMock.getValidatedAuthorizationDetails(any(OAuth2TokenValidationMessageContext.class)))
.thenReturn(new AuthorizationDetails());
- try (MockedStatic oAuth2UtilMock = Mockito.mockStatic(OAuth2Util.class);
- MockedStatic componentHolderMock =
+ try (MockedStatic componentHolderMock =
Mockito.mockStatic(OAuth2ServiceComponentHolder.class)) {
- oAuth2UtilMock.when(() -> OAuth2Util.buildScopeArray(any())).thenReturn(new String[0]);
componentHolderMock.when(OAuth2ServiceComponentHolder::getInstance)
.thenReturn(this.componentHolderMock);
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
index 8254b42634..720a6f267c 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/utils/AuthorizationDetailsBaseTest.java
@@ -115,7 +115,7 @@ public AuthorizationDetailsBaseTest() {
this.accessTokenDO.setTokenId(ACESS_TOKEN_ID);
this.accessTokenDO.setTenantID(TENANT_ID);
- mockAuthorizationDetailsProviderFactory();
+ mockAuthorizationDetailsProcessorFactory();
this.serviceMock = mock(AuthorizationDetailsService.class);
this.schemaValidatorMock = spy(AuthorizationDetailsSchemaValidator.class);
@@ -133,7 +133,7 @@ public static void assertAuthorizationDetailsMissing(final Map a
assertFalse(attributes.containsKey(AuthorizationDetailsConstants.AUTHORIZATION_DETAILS));
}
- private void mockAuthorizationDetailsProviderFactory() {
+ private void mockAuthorizationDetailsProcessorFactory() {
this.processorFactoryMock = spy(AuthorizationDetailsProcessorFactory.class);
try {
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
index 67c8e4f942..3c63abce05 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/validator/DefaultAuthorizationDetailsValidatorTest.java
@@ -24,10 +24,12 @@
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
import org.wso2.carbon.identity.oauth2.rar.exception.AuthorizationDetailsProcessingException;
import org.wso2.carbon.identity.oauth2.rar.utils.AuthorizationDetailsBaseTest;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.wso2.carbon.identity.oauth2.TestConstants.ACESS_TOKEN_ID;
@@ -39,7 +41,8 @@ public class DefaultAuthorizationDetailsValidatorTest extends AuthorizationDetai
@BeforeClass
public void setUp() throws IdentityOAuth2Exception {
- when(serviceMock.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID))
+ this.serviceMock = mock(AuthorizationDetailsService.class);
+ when(this.serviceMock.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID))
.thenReturn(authorizationDetails);
this.uut = new DefaultAuthorizationDetailsValidator(processorFactoryMock, serviceMock, schemaValidatorMock);
From 61bf493292788fc06110644798deeadb95f302d4 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 17 Jan 2025 14:04:58 +0530
Subject: [PATCH 15/28] Improve unit tests coverage
---
.../authz/OAuth2AuthzEndpointTest.java | 87 +++++++++++++------
.../oauth/endpoint/util/EndpointUtilTest.java | 31 ++++++-
.../pom.xml | 2 +-
.../OAuth2ServiceComponentHolder.java | 2 +
4 files changed, 93 insertions(+), 29 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
index 91535b6212..aba2d95884 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpointTest.java
@@ -51,6 +51,7 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import org.testng.collections.Sets;
import org.wso2.carbon.base.CarbonBaseConstants;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticatorFlowStatus;
@@ -113,6 +114,9 @@
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
+import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
import org.wso2.carbon.identity.oauth2.responsemode.provider.ResponseModeProvider;
import org.wso2.carbon.identity.oauth2.responsemode.provider.impl.DefaultResponseModeProvider;
import org.wso2.carbon.identity.oauth2.responsemode.provider.impl.FormPostResponseModeProvider;
@@ -287,7 +291,13 @@ public class OAuth2AuthzEndpointTest extends TestOAuthEndpointBase {
private CentralLogMgtServiceComponentHolder centralLogMgtServiceComponentHolderMock;
@Mock
- private AuthorizationDetailsService authorizationDetailsService;
+ private AuthorizationDetailsService authorizationDetailsServiceMock;
+
+ @Mock
+ private AuthorizationDetailsValidator authorizationDetailsValidatorMock;
+
+ @Mock
+ private OAuth2ServiceComponentHolder oAuth2ServiceComponentHolderMock;
private static final String ERROR_PAGE_URL = "https://localhost:9443/authenticationendpoint/oauth2_error.do";
private static final String LOGIN_PAGE_URL = "https://localhost:9443/authenticationendpoint/login.do";
@@ -577,8 +587,8 @@ public void testAuthorize(Object flowStatusObject, String[] clientId, String ses
SessionDataCacheKey consentDataCacheKey = new SessionDataCacheKey(SESSION_DATA_KEY_CONSENT_VALUE);
when(mockSessionDataCache.getValueFromCache(loginDataCacheKey)).thenReturn(loginCacheEntry);
when(mockSessionDataCache.getValueFromCache(consentDataCacheKey)).thenReturn(consentCacheEntry);
- when(loginCacheEntry.getoAuth2Parameters()).thenReturn(setOAuth2Parameters(
- new HashSet<>(Collections.singletonList(OAuthConstants.Scope.OPENID)), APP_NAME, null, null));
+ when(loginCacheEntry.getoAuth2Parameters()).thenReturn(setOAuth2Parameters(new HashSet<>(Collections
+ .singletonList(OAuthConstants.Scope.OPENID)), APP_NAME, null, null, null));
mockEndpointUtil(false, endpointUtil);
when(oAuth2Service.getOauthApplicationState(CLIENT_ID_VALUE)).thenReturn("ACTIVE");
@@ -676,32 +686,39 @@ public void testAuthorize(Object flowStatusObject, String[] clientId, String ses
@DataProvider(name = "provideAuthenticatedData")
public Object[][] provideAuthenticatedData() {
+ final AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
+ testAuthorizationDetail.setType("test_type");
+
return addDiagnosticLogStatusToExistingDataProvider(new Object[][]{
{true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)),
- RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
+ null, RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
{false, true, null, null, null, null, new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)),
- RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
+ null, RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
- {true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList("scope1")), "not_form_post",
- APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
+ {true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList("scope1")), null,
+ "not_form_post", APP_REDIRECT_URL, HttpServletResponse.SC_FOUND},
{true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)),
- RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL_JSON, HttpServletResponse.SC_OK},
+ null, RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL_JSON, HttpServletResponse.SC_OK},
- {true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList("scope1")),
+ {true, true, new HashMap(), null, null, null, new HashSet<>(Arrays.asList("scope1")), null,
RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL_JSON, HttpServletResponse.SC_OK},
{true, false, null, OAuth2ErrorCodes.INVALID_REQUEST, null, null,
- new HashSet<>(Arrays.asList("scope1")),
+ new HashSet<>(Arrays.asList("scope1")), null,
RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_OK},
{true, false, null, null, "Error!", null, new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)),
- RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_OK},
+ null, RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL, HttpServletResponse.SC_OK},
{true, false, null, null, null, "http://localhost:8080/error",
- new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)), RESPONSE_MODE_FORM_POST,
- APP_REDIRECT_URL, HttpServletResponse.SC_OK}
+ new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)), null, RESPONSE_MODE_FORM_POST,
+ APP_REDIRECT_URL, HttpServletResponse.SC_OK},
+
+ {true, true, new HashMap<>(), null, null, null, Sets.newHashSet("scope1"),
+ Sets.newHashSet(testAuthorizationDetail), RESPONSE_MODE_FORM_POST, APP_REDIRECT_URL_JSON,
+ HttpServletResponse.SC_OK}
});
}
@@ -709,6 +726,7 @@ public Object[][] provideAuthenticatedData() {
public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, boolean isAuthenticated,
Map attributes, String errorCode,
String errorMsg, String errorUri, Set scopes,
+ Set testAuthorizationDetails,
String responseMode, String redirectUri, int expected,
boolean diagnosticLogsEnabled)
throws Exception {
@@ -729,7 +747,9 @@ public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, bo
MockedStatic identityUtil = mockStatic(IdentityUtil.class,
Mockito.CALLS_REAL_METHODS);
MockedStatic serviceURLBuilder = mockStatic(ServiceURLBuilder.class);
- MockedStatic endpointUtil = mockStatic(EndpointUtil.class, Mockito.CALLS_REAL_METHODS)) {
+ MockedStatic endpointUtil = mockStatic(EndpointUtil.class, Mockito.CALLS_REAL_METHODS);
+ MockedStatic serviceComponentHolder =
+ mockStatic(OAuth2ServiceComponentHolder.class, Mockito.CALLS_REAL_METHODS)) {
sessionDataCache.when(SessionDataCache::getInstance).thenReturn(mockSessionDataCache);
SessionDataCacheKey loginDataCacheKey = new SessionDataCacheKey(SESSION_DATA_KEY_VALUE);
@@ -770,7 +790,8 @@ public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, bo
identityUtil.when(() -> IdentityUtil.getServerURL(anyString(), anyBoolean(), anyBoolean()))
.thenReturn("https://localhost:9443/carbon");
- OAuth2Parameters oAuth2Params = setOAuth2Parameters(scopes, APP_NAME, responseMode, redirectUri);
+ OAuth2Parameters oAuth2Params =
+ setOAuth2Parameters(scopes, APP_NAME, responseMode, redirectUri, testAuthorizationDetails);
oAuth2Params.setClientId(CLIENT_ID_VALUE);
oAuth2Params.setState(STATE);
when(loginCacheEntry.getoAuth2Parameters()).thenReturn(oAuth2Params);
@@ -796,6 +817,7 @@ public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, bo
authzReqDTO.setResponseType("code");
OAuthAuthzReqMessageContext authzReqMsgCtx = new OAuthAuthzReqMessageContext(authzReqDTO);
authzReqMsgCtx.setApprovedScope(new String[]{OAuthConstants.Scope.OPENID});
+ authzReqMsgCtx.setApprovedAuthorizationDetails(new AuthorizationDetails(testAuthorizationDetails));
when(oAuth2Service.validateScopesBeforeConsent(any(OAuth2AuthorizeReqDTO.class))).thenReturn(
authzReqMsgCtx);
when(mockAuthorizationHandlerManager.validateScopesBeforeConsent(any(OAuth2AuthorizeReqDTO.class)))
@@ -819,9 +841,18 @@ public void testAuthorizeForAuthenticationResponse(boolean isResultInRequest, bo
when(oAuth2ScopeService.hasUserProvidedConsentForAllRequestedScopes(
anyString(), isNull(), anyInt(), anyList())).thenReturn(true);
- when(authorizationDetailsService.isUserAlreadyConsentedForAuthorizationDetails(
+ when(authorizationDetailsServiceMock.isUserAlreadyConsentedForAuthorizationDetails(
any(AuthenticatedUser.class), any(OAuth2Parameters.class))).thenReturn(true);
- OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsService);
+ OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsServiceMock);
+
+ when(authorizationDetailsValidatorMock
+ .getValidatedAuthorizationDetails(any(OAuthAuthzReqMessageContext.class)))
+ .thenReturn(new AuthorizationDetails(testAuthorizationDetails));
+
+ when(oAuth2ServiceComponentHolderMock.getAuthorizationDetailsValidator())
+ .thenReturn(authorizationDetailsValidatorMock);
+ serviceComponentHolder.when(OAuth2ServiceComponentHolder::getInstance)
+ .thenReturn(oAuth2ServiceComponentHolderMock);
mockServiceURLBuilder(serviceURLBuilder);
setSupportedResponseModes();
@@ -976,7 +1007,7 @@ public void testUserConsentResponse(String consent, String redirectUrl, Set(), APP_NAME, responseMode, APP_REDIRECT_URL);
+ setOAuth2Parameters(new HashSet<>(), APP_NAME, responseMode, APP_REDIRECT_URL, null);
oAuth2Params.setResponseType(responseType);
oAuth2Params.setState(state);
oAuth2Params.setClientId(CLIENT_ID_VALUE);
@@ -1664,7 +1695,7 @@ public void testHandleUserConsent(boolean isRespDTONull, String consent, boolean
OAuthAuthzReqMessageContext authzReqMsgCtx = new OAuthAuthzReqMessageContext(authorizeReqDTO);
when(consentCacheEntry.getAuthzReqMsgCtx()).thenReturn(authzReqMsgCtx);
- OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsService);
+ OAuth2AuthzEndpoint.setAuthorizationDetailsService(authorizationDetailsServiceMock);
Response response;
try {
@@ -1760,7 +1791,8 @@ public void testDoUserAuthz(String prompt, String idTokenHint, boolean hasUserAp
mockHttpRequest(requestParams, requestAttributes, HttpMethod.POST);
- OAuth2Parameters oAuth2Params = setOAuth2Parameters(new HashSet<>(), APP_NAME, null, APP_REDIRECT_URL);
+ OAuth2Parameters oAuth2Params =
+ setOAuth2Parameters(new HashSet<>(), APP_NAME, null, APP_REDIRECT_URL, null);
oAuth2Params.setClientId(CLIENT_ID_VALUE);
oAuth2Params.setPrompt(prompt);
oAuth2Params.setIDTokenHint(idTokenHint);
@@ -1920,7 +1952,7 @@ public void testManageOIDCSessionState(Object cookieObject, Object sessionStateO
OAuth2Parameters oAuth2Params =
setOAuth2Parameters(new HashSet<>(Arrays.asList(OAuthConstants.Scope.OPENID)),
- APP_NAME, responseMode, APP_REDIRECT_URL);
+ APP_NAME, responseMode, APP_REDIRECT_URL, null);
oAuth2Params.setClientId(CLIENT_ID_VALUE);
oAuth2Params.setPrompt(OAuthConstants.Prompt.LOGIN);
@@ -1953,8 +1985,8 @@ public void testManageOIDCSessionState(Object cookieObject, Object sessionStateO
, anyString()))
.thenReturn("sessionStateValue");
oidcSessionManagementUtil.when(
- () -> OIDCSessionManagementUtil.addSessionStateToURL(anyString(), anyString(),
- isNull())).thenCallRealMethod();
+ () -> OIDCSessionManagementUtil.addSessionStateToURL(anyString(), anyString(),
+ isNull())).thenCallRealMethod();
sessionDataCache.when(SessionDataCache::getInstance).thenReturn(mockSessionDataCache);
SessionDataCacheKey loginDataCacheKey = new SessionDataCacheKey(SESSION_DATA_KEY_VALUE);
@@ -2685,11 +2717,11 @@ private void mockEndpointUtil(boolean isConsentMgtEnabled, MockedStatic EndpointUtil.getUserConsentURL(any(OAuth2Parameters.class),
- anyString(), anyString(), any(OAuthMessage.class), anyString())).thenReturn(USER_CONSENT_URL);
+ anyString(), anyString(), any(OAuthMessage.class), anyString())).thenReturn(USER_CONSENT_URL);
endpointUtil.when(EndpointUtil::getRequestObjectService).thenReturn(requestObjectService);
endpointUtil.when(() -> EndpointUtil.getLoginPageURL(anyString(), anyString(), anyBoolean(),
- anyBoolean(), anySet(), anyMap(), any())).thenReturn(LOGIN_PAGE_URL);
+ anyBoolean(), anySet(), anyMap(), any())).thenReturn(LOGIN_PAGE_URL);
EndpointUtil.setOAuthAdminService(oAuthAdminService);
EndpointUtil.setOAuth2ScopeService(oAuth2ScopeService);
@@ -2734,13 +2766,14 @@ private AuthenticationResult setAuthenticationResult(boolean isAuthenticated, Ma
}
private OAuth2Parameters setOAuth2Parameters(Set scopes, String appName, String responseMode,
- String redirectUri) {
+ String redirectUri, Set authorizationDetails) {
OAuth2Parameters oAuth2Parameters = new OAuth2Parameters();
oAuth2Parameters.setScopes(scopes);
oAuth2Parameters.setResponseMode(responseMode);
oAuth2Parameters.setRedirectURI(redirectUri);
oAuth2Parameters.setApplicationName(appName);
+ oAuth2Parameters.setAuthorizationDetails(new AuthorizationDetails(authorizationDetails));
return oAuth2Parameters;
}
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtilTest.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtilTest.java
index 188c294385..58af26b813 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtilTest.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/test/java/org/wso2/carbon/identity/oauth/endpoint/util/EndpointUtilTest.java
@@ -38,6 +38,7 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
+import org.testng.collections.Sets;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.PrivilegedCarbonContext;
@@ -71,8 +72,12 @@
import org.wso2.carbon.identity.oauth2.OAuth2Service;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
import org.wso2.carbon.identity.oauth2.bean.Scope;
+import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters;
import org.wso2.carbon.identity.oauth2.model.OAuth2ScopeConsentResponse;
+import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetail;
+import org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.openidconnect.RequestObjectService;
import org.wso2.carbon.identity.webfinger.DefaultWebFingerProcessor;
@@ -159,9 +164,15 @@ public class EndpointUtilTest {
@Mock
OAuth2ScopeService oAuth2ScopeService;
+ @Mock
+ private AuthorizationDetailsService authorizationDetailsServiceMock;
+
@Mock
FileBasedConfigurationBuilder mockFileBasedConfigurationBuilder;
+ @Mock
+ private OAuth2ServiceComponentHolder oAuth2ServiceComponentHolderMock;
+
private static final String COMMONAUTH_URL = "https://localhost:9443/commonauth";
private static final String OIDC_CONSENT_PAGE_URL =
"https://localhost:9443/authenticationendpoint/oauth2_consent.do";
@@ -196,6 +207,14 @@ public class EndpointUtilTest {
private String clientId;
private AuthenticatedUser user;
private OAuth2ScopeConsentResponse oAuth2ScopeConsentResponse;
+ private final AuthorizationDetails testAuthorizationDetails;
+
+ public EndpointUtilTest() {
+
+ final AuthorizationDetail testAuthorizationDetail = new AuthorizationDetail();
+ testAuthorizationDetail.setType("test_type");
+ this.testAuthorizationDetails = new AuthorizationDetails(Sets.newHashSet(testAuthorizationDetail));
+ }
@BeforeMethod
public void setUp() {
@@ -245,6 +264,7 @@ public Object[][] provideDataForUserConsentURL() {
params.setClientId("testClientId");
params.setTenantDomain("testTenantDomain");
params.setScopes(new HashSet(Arrays.asList("scope1", "scope2", "internal_login")));
+ params.setAuthorizationDetails(testAuthorizationDetails);
OAuth2Parameters paramsOIDC = new OAuth2Parameters();
paramsOIDC.setApplicationName("TestApplication");
@@ -291,7 +311,9 @@ public void testGetUserConsentURL(Object oAuth2ParamObject, boolean isOIDC, bool
MockedStatic oAuthURL = mockStatic(OAuth2Util.OAuthURL.class);
MockedStatic identityTenantUtil = mockStatic(IdentityTenantUtil.class);
MockedStatic frameworkUtils = mockStatic(FrameworkUtils.class);
- MockedStatic sessionDataCache = mockStatic(SessionDataCache.class);) {
+ MockedStatic sessionDataCache = mockStatic(SessionDataCache.class);
+ MockedStatic serviceComponentHolder =
+ mockStatic(OAuth2ServiceComponentHolder.class, Mockito.CALLS_REAL_METHODS)) {
EndpointUtil.setOauthServerConfiguration(mockedOAuthServerConfiguration);
lenient().when(mockedOAuthServerConfiguration.isDropUnregisteredScopes()).thenReturn(false);
@@ -344,6 +366,13 @@ public void testGetUserConsentURL(Object oAuth2ParamObject, boolean isOIDC, bool
lenient().when(mockedOAuthAdminService.getRegisteredOIDCScope(anyString()))
.thenReturn(Arrays.asList("openid", "email", "profile", "groups"));
+ lenient().when(authorizationDetailsServiceMock.getConsentRequiredAuthorizationDetails(user, parameters))
+ .thenReturn(testAuthorizationDetails);
+ lenient().when(oAuth2ServiceComponentHolderMock.getAuthorizationDetailsService())
+ .thenReturn(authorizationDetailsServiceMock);
+ serviceComponentHolder.when(OAuth2ServiceComponentHolder::getInstance)
+ .thenReturn(oAuth2ServiceComponentHolderMock);
+
String consentUrl;
try {
consentUrl = EndpointUtil.getUserConsentURL(parameters, username, sessionDataKey, isOIDC);
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 20fc5054ee..ac4fa5d2d0 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.211-SNAPSHOT
+ 7.0.215-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
index 5c3a68c1b2..ada9ba8480 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.java
@@ -979,6 +979,8 @@ public AuthorizationDetailsTypeManager getAuthorizationDetailsTypeManager() {
/**
* set an {@link AuthorizationDetailsTypeManager} instance.
+ *
+ * @param authorizationDetailsTypeManager An {@link AuthorizationDetailsTypeManager} instance.
*/
public void setAuthorizationDetailsTypeManager(AuthorizationDetailsTypeManager authorizationDetailsTypeManager) {
From f52306142aaba78cc433a914dc201263312263f7 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 17 Jan 2025 14:12:35 +0530
Subject: [PATCH 16/28] bump carbon.identity.framework.version to support
authorization details
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0f05a18987..a7cc63d959 100644
--- a/pom.xml
+++ b/pom.xml
@@ -957,7 +957,7 @@
[1.0.1, 2.0.0)
- 7.7.49
+ 7.7.90
[5.25.234, 8.0.0)
[2.0.0, 3.0.0)
From be2070a72128e1f37952c2c2e60606e0a68c906b Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 17 Jan 2025 15:52:49 +0530
Subject: [PATCH 17/28] Add logic to check RAR is enabled
---
.../builders/ProviderConfigBuilder.java | 4 +-
.../rar/dao/AuthorizationDetailsDAOImpl.java | 44 ++--------------
.../dao/AuthorizationDetailsDAOImplTest.java | 30 -----------
.../dao/OAuthTokenPersistenceFactory.java | 2 +-
.../rar/AuthorizationDetailsService.java | 44 ++++++++++++----
.../rar/AuthorizationDetailsServiceTest.java | 51 ++++++++++++++++++-
6 files changed, 90 insertions(+), 85 deletions(-)
diff --git a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
index d3ac9f6ad1..c44c689683 100644
--- a/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
+++ b/components/org.wso2.carbon.identity.discovery/src/main/java/org/wso2/carbon/identity/discovery/builders/ProviderConfigBuilder.java
@@ -157,8 +157,8 @@ public OIDProviderConfigResponse buildOIDProviderConfig(OIDProviderRequest reque
final Set authorizationDetailTypes = AuthorizationDetailsProcessorFactory.getInstance()
.getSupportedAuthorizationDetailTypes();
if (authorizationDetailTypes != null && !authorizationDetailTypes.isEmpty()) {
- //final int size = supportedTypes.size();
- providerConfig.setAuthorizationDetailsTypesSupported(authorizationDetailTypes.toArray(String[]::new));
+ providerConfig
+ .setAuthorizationDetailsTypesSupported(authorizationDetailTypes.stream().toArray(String[]::new));
}
return providerConfig;
}
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
index 4af816fbba..a4508e880c 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImpl.java
@@ -30,8 +30,6 @@
import java.util.HashSet;
import java.util.Set;
-import static org.wso2.carbon.identity.api.resource.mgt.util.AuthorizationDetailsTypesUtil.isRichAuthorizationRequestsDisabled;
-
/**
* Implements the {@link AuthorizationDetailsDAO} interface to manage rich authorization requests.
*
@@ -47,10 +45,6 @@ public class AuthorizationDetailsDAOImpl implements AuthorizationDetailsDAO {
public int[] addUserConsentedAuthorizationDetails(final Set consentDTOs)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return new int[0];
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -75,10 +69,6 @@ public int[] addUserConsentedAuthorizationDetails(final Set consentDTOs)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return new int[0];
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
PreparedStatement ps =
connection.prepareStatement(SQLQueries.UPDATE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -104,11 +94,6 @@ public Set getUserConsentedAuthorizationDetails(
final int tenantId)
throws SQLException {
- final Set authorizationDetailsConsentDTOs = new HashSet<>();
- if (isRichAuthorizationRequestsDisabled()) {
- return authorizationDetailsConsentDTOs;
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -117,6 +102,7 @@ public Set getUserConsentedAuthorizationDetails(
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
+ final Set authorizationDetailsConsentDTOs = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
final String typeId = rs.getString(2);
@@ -138,10 +124,6 @@ public Set getUserConsentedAuthorizationDetails(
public int deleteUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return -1;
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.DELETE_OAUTH2_USER_CONSENTED_AUTHORIZATION_DETAILS)) {
@@ -159,10 +141,6 @@ public int deleteUserConsentedAuthorizationDetails(final String consentId, final
public int[] addAccessTokenAuthorizationDetails(final Set tokenDTOs)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return new int[0];
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
@@ -187,11 +165,6 @@ public Set getAccessTokenAuthorizationDetails(fina
final int tenantId)
throws SQLException {
- final Set authorizationDetailsTokenDTO = new HashSet<>();
- if (isRichAuthorizationRequestsDisabled()) {
- return authorizationDetailsTokenDTO;
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
@@ -200,6 +173,7 @@ public Set getAccessTokenAuthorizationDetails(fina
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
+ final Set authorizationDetailsTokenDTO = new HashSet<>();
while (rs.next()) {
final String id = rs.getString(1);
final String typeId = rs.getString(2);
@@ -220,10 +194,6 @@ public Set getAccessTokenAuthorizationDetails(fina
public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, final int tenantId)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return -1;
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.DELETE_OAUTH2_ACCESS_TOKEN_AUTHORIZATION_DETAILS)) {
@@ -241,10 +211,6 @@ public int deleteAccessTokenAuthorizationDetails(final String accessTokenId, fin
public int[] addOAuth2CodeAuthorizationDetails(final Set authorizationDetailsCodeDTOs)
throws SQLException {
- if (isRichAuthorizationRequestsDisabled()) {
- return new int[0];
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.ADD_OAUTH2_CODE_AUTHORIZATION_DETAILS)) {
@@ -268,11 +234,6 @@ public int[] addOAuth2CodeAuthorizationDetails(final Set getOAuth2CodeAuthorizationDetails(final String authorizationCode,
final int tenantId) throws SQLException {
- final Set authorizationDetailsCodeDTOs = new HashSet<>();
- if (isRichAuthorizationRequestsDisabled()) {
- return authorizationDetailsCodeDTOs;
- }
-
try (final Connection connection = IdentityDatabaseUtil.getDBConnection(false);
final PreparedStatement ps =
connection.prepareStatement(SQLQueries.GET_OAUTH2_CODE_AUTHORIZATION_DETAILS_BY_CODE)) {
@@ -281,6 +242,7 @@ public Set getOAuth2CodeAuthorizationDetails(final
ps.setInt(2, tenantId);
try (ResultSet rs = ps.executeQuery()) {
+ final Set authorizationDetailsCodeDTOs = new HashSet<>();
while (rs.next()) {
final String codeId = rs.getString(1);
final String typeId = rs.getString(2);
diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
index f51555d8e6..a5fe74cf90 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
+++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth2/rar/dao/AuthorizationDetailsDAOImplTest.java
@@ -265,36 +265,6 @@ public void shouldReturnNull_whenUserIdOrAppIdInvalid() throws SQLException {
assertNull(this.uut.getConsentIdByUserIdAndAppId("invalid_user_id", "invalid_app_id", TEST_TENANT_ID));
}
- @Test
- public void testUserConsentedAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
-
- this.mockAuthorizationDetailsTypesUtil(false);
-
- assertEquals(0, this.uut.addUserConsentedAuthorizationDetails(Collections.emptySet()).length);
- assertEquals(0, this.uut.updateUserConsentedAuthorizationDetails(Collections.emptySet()).length);
- assertEquals(0, this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID).size());
- assertEquals(-1, this.uut.deleteUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TEST_TENANT_ID));
- }
-
- @Test
- public void testAccessTokenAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
-
- this.mockAuthorizationDetailsTypesUtil(false);
-
- assertEquals(0, uut.addAccessTokenAuthorizationDetails(Collections.emptySet()).length);
- assertEquals(0, this.uut.getAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID).size());
- assertEquals(-1, this.uut.deleteAccessTokenAuthorizationDetails(TEST_TOKEN_ID, TEST_TENANT_ID));
- }
-
- @Test
- public void testOAuth2CodeAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException {
-
- this.mockAuthorizationDetailsTypesUtil(false);
-
- assertEquals(0, uut.addOAuth2CodeAuthorizationDetails(Collections.emptySet()).length);
- assertEquals(0, this.uut.getOAuth2CodeAuthorizationDetails(TEST_AUTHORIZATION_CODE, TEST_TENANT_ID).size());
- }
-
private void mockAuthorizationDetailsTypesUtil(boolean isRichAuthorizationRequestsEnabled) {
this.authorizationDetailsTypesUtilMock
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
index 3737e52311..e38b6ad272 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/dao/OAuthTokenPersistenceFactory.java
@@ -116,7 +116,7 @@ public OAuthUserConsentedScopesDAO getOAuthUserConsentedScopesDAO() {
* Retrieves the DAO for authorization details.
*
* This method returns an {@link AuthorizationDetailsDAO} singleton instance that provides access to the
- * {@link org.wso2.carbon.identity.oauth2.rar.common.model.AuthorizationDetails} data. This DAO is used to interact
+ * {@link org.wso2.carbon.identity.oauth2.rar.model.AuthorizationDetails} data. This DAO is used to interact
* with the underlying data store to fetch and manipulate authorization information.
*
* @return the {@link AuthorizationDetailsDAO} instance that provides access to authorization details data.
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
index cf1ad3ea89..2bb41ca418 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsService.java
@@ -22,6 +22,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.wso2.carbon.identity.api.resource.mgt.util.AuthorizationDetailsTypesUtil;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
@@ -68,6 +69,7 @@ public class AuthorizationDetailsService {
private static final Log log = LogFactory.getLog(AuthorizationDetailsService.class);
private final AuthorizationDetailsDAO authorizationDetailsDAO;
private final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory;
+ private final boolean isRichAuthorizationRequestsDisabled;
/**
* Default constructor that initializes the service with the default {@link AuthorizationDetailsDAO} and
@@ -81,7 +83,8 @@ public AuthorizationDetailsService() {
this(
AuthorizationDetailsProcessorFactory.getInstance(),
- OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO()
+ OAuthTokenPersistenceFactory.getInstance().getAuthorizationDetailsDAO(),
+ AuthorizationDetailsTypesUtil.isRichAuthorizationRequestsEnabled()
);
}
@@ -93,12 +96,14 @@ public AuthorizationDetailsService() {
* handling authorization details persistence. Must not be {@code null}.
*/
public AuthorizationDetailsService(final AuthorizationDetailsProcessorFactory authorizationDetailsProcessorFactory,
- final AuthorizationDetailsDAO authorizationDetailsDAO) {
+ final AuthorizationDetailsDAO authorizationDetailsDAO,
+ final boolean isRichAuthorizationRequestsEnabled) {
this.authorizationDetailsDAO =
Objects.requireNonNull(authorizationDetailsDAO, "AuthorizationDetailsDAO must not be null");
this.authorizationDetailsProcessorFactory = Objects.requireNonNull(authorizationDetailsProcessorFactory,
"AuthorizationDetailsProviderFactory must not be null");
+ this.isRichAuthorizationRequestsDisabled = !isRichAuthorizationRequestsEnabled;
}
/**
@@ -116,7 +121,7 @@ public void storeOrUpdateUserConsentedAuthorizationDetails(
final AuthorizationDetails userConsentedAuthorizationDetails)
throws OAuthSystemException {
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ if (this.isRichAuthorizationRequestsDisabled || !isRichAuthorizationRequest(oAuth2Parameters)) {
log.debug("Request is not a rich authorization request. Skipping storage of authorization details.");
return;
}
@@ -185,7 +190,7 @@ public void deleteUserConsentedAuthorizationDetails(final AuthenticatedUser auth
final String clientId, final OAuth2Parameters oAuth2Parameters)
throws OAuthSystemException {
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ if (this.isRichAuthorizationRequestsDisabled || !isRichAuthorizationRequest(oAuth2Parameters)) {
log.debug("Request is not a rich authorization request. Skipping deletion of authorization details.");
return;
}
@@ -239,7 +244,7 @@ public boolean isUserAlreadyConsentedForAuthorizationDetails(final Authenticated
final OAuth2Parameters oAuth2Parameters)
throws IdentityOAuth2Exception {
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ if (this.isRichAuthorizationRequestsDisabled || !isRichAuthorizationRequest(oAuth2Parameters)) {
return true;
}
@@ -250,7 +255,7 @@ public AuthorizationDetails getConsentRequiredAuthorizationDetails(final Authent
final OAuth2Parameters oAuth2Parameters)
throws IdentityOAuth2Exception {
- if (!isRichAuthorizationRequest(oAuth2Parameters)) {
+ if (this.isRichAuthorizationRequestsDisabled || !isRichAuthorizationRequest(oAuth2Parameters)) {
log.debug("Request is not a rich authorization request. Skipping the authorization details retrieval.");
return new AuthorizationDetails();
}
@@ -368,6 +373,11 @@ public AuthorizationDetails getUserConsentedAuthorizationDetails(
public AuthorizationDetails getUserConsentedAuthorizationDetails(final String consentId, final int tenantId)
throws IdentityOAuth2Exception {
+ if (this.isRichAuthorizationRequestsDisabled) {
+ log.debug("Rich authorization requests is disabled. Skip retrieving consented authorization details.");
+ return new AuthorizationDetails();
+ }
+
try {
final Set consentedAuthorizationDetails = new HashSet<>();
this.authorizationDetailsDAO.getUserConsentedAuthorizationDetails(consentId, tenantId)
@@ -413,6 +423,10 @@ private Optional getConsentId(final AuthenticatedUser authenticatedUser,
public Optional getConsentIdByUserIdAndAppId(final String userId, final String appId, final int tenantId)
throws IdentityOAuth2Exception {
+ if (this.isRichAuthorizationRequestsDisabled) {
+ log.debug("Rich authorization requests is disabled. Skip retrieving consents.");
+ return Optional.empty();
+ }
try {
return Optional
.ofNullable(this.authorizationDetailsDAO.getConsentIdByUserIdAndAppId(userId, appId, tenantId));
@@ -434,6 +448,10 @@ public Optional getConsentIdByUserIdAndAppId(final String userId, final
public AuthorizationDetails getAccessTokenAuthorizationDetails(final String accessTokenId, final int tenantId)
throws IdentityOAuth2Exception {
+ if (this.isRichAuthorizationRequestsDisabled) {
+ log.debug("Rich authorization requests is disabled. Skip retrieving token authorization details.");
+ return new AuthorizationDetails();
+ }
try {
final Set authorizationDetailsTokenDTOs =
this.authorizationDetailsDAO.getAccessTokenAuthorizationDetails(accessTokenId, tenantId);
@@ -482,10 +500,10 @@ public void storeAccessTokenAuthorizationDetails(final AccessTokenDO accessToken
final AuthorizationDetails authorizationDetails)
throws IdentityOAuth2Exception {
- if (AuthorizationDetailsUtils.isEmpty(authorizationDetails)) {
+ if (this.isRichAuthorizationRequestsDisabled || AuthorizationDetailsUtils.isEmpty(authorizationDetails)) {
+ log.debug("Request is not a rich authorization request. Skipping storage of token authorization details.");
return;
}
-
try {
final AuthorizationDetails trimmedAuthorizationDetails = AuthorizationDetailsUtils
.getTrimmedAuthorizationDetails(authorizationDetails);
@@ -542,6 +560,10 @@ public void storeOrReplaceAccessTokenAuthorizationDetails(
public void deleteAccessTokenAuthorizationDetails(final String accessTokenId, final int tenantId)
throws IdentityOAuth2Exception {
+ if (this.isRichAuthorizationRequestsDisabled) {
+ log.debug("Rich authorization requests is disabled. Skip persisting token authorization details.");
+ return;
+ }
try {
int result = this.authorizationDetailsDAO.deleteAccessTokenAuthorizationDetails(accessTokenId, tenantId);
if (result > 0 && log.isDebugEnabled()) {
@@ -604,7 +626,7 @@ public void storeAuthorizationCodeAuthorizationDetails(
final AuthzCodeDO authzCodeDO, final OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext)
throws IdentityOAuth2Exception {
- if (!isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
+ if (this.isRichAuthorizationRequestsDisabled || !isRichAuthorizationRequest(oAuthAuthzReqMessageContext)) {
log.debug("Request is not a rich authorization request. Skipping storage of code authorization details.");
return;
}
@@ -641,6 +663,10 @@ public void storeAuthorizationCodeAuthorizationDetails(
public AuthorizationDetails getAuthorizationCodeAuthorizationDetails(final String code, final int tenantId)
throws IdentityOAuth2Exception {
+ if (this.isRichAuthorizationRequestsDisabled) {
+ log.debug("Rich authorization requests is disabled. Skip retrieving code authorization details.");
+ return new AuthorizationDetails();
+ }
try {
final Set authorizationDetailsCodeDTOs =
this.authorizationDetailsDAO.getOAuth2CodeAuthorizationDetails(code, tenantId);
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
index e62c8b9702..355752747b 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/rar/AuthorizationDetailsServiceTest.java
@@ -131,7 +131,7 @@ public void setUpMethod()
when(this.processorFactoryMock.getAuthorizationDetailsProcessorByType(TEST_TYPE))
.thenReturn(Optional.of(processor));
- uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock);
+ uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock, true);
}
@BeforeMethod(onlyForGroups = {"error-flow-tests"}, dependsOnMethods = {"setUpMethod"})
@@ -150,7 +150,13 @@ public void setUpErrorMethod() throws SQLException {
when(this.authorizationDetailsDAOMock.deleteAccessTokenAuthorizationDetails(anyString(), anyInt()))
.thenThrow(SQLException.class);
- uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock);
+ uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock, true);
+ }
+
+ @BeforeMethod(onlyForGroups = {"feature-disabled-flow-tests"}, dependsOnMethods = {"setUpErrorMethod"})
+ public void setUpFeatureDisabledMethod() {
+
+ uut = new AuthorizationDetailsService(this.processorFactoryMock, this.authorizationDetailsDAOMock, false);
}
@Test
@@ -443,4 +449,45 @@ public void shouldThrowIdentityOAuth2Exception_onAccessTokenAuthorizationDetails
uut.deleteAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
}
+
+ @Test(groups = {"feature-disabled-flow-tests"})
+ public void testUserConsentedAuthorizationDetailsWhenFeatureIsDisabled()
+ throws OAuthSystemException, SQLException, IdentityOAuth2Exception {
+
+ this.uut.storeOrUpdateUserConsentedAuthorizationDetails(authenticatedUser, CLIENT_ID, oAuth2Parameters,
+ new AuthorizationDetails());
+ verify(authorizationDetailsDAOMock, times(0)).addUserConsentedAuthorizationDetails(anySet());
+ verify(authorizationDetailsDAOMock, times(0)).updateUserConsentedAuthorizationDetails(anySet());
+
+ this.uut.getUserConsentedAuthorizationDetails(TEST_CONSENT_ID, TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(0)).getUserConsentedAuthorizationDetails(anyString(), anyInt());
+
+ this.uut.deleteUserConsentedAuthorizationDetails(authenticatedUser, TEST_CONSENT_ID, oAuth2Parameters);
+ verify(authorizationDetailsDAOMock, times(0)).deleteUserConsentedAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test(groups = {"feature-disabled-flow-tests"})
+ public void testAccessTokenAuthorizationDetailsWhenFeatureIsDisabled()
+ throws SQLException, IdentityOAuth2Exception {
+
+ this.uut.storeAccessTokenAuthorizationDetails(accessTokenDO, authorizationDetails);
+ verify(authorizationDetailsDAOMock, times(0)).addAccessTokenAuthorizationDetails(anySet());
+
+ this.uut.getAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(0)).getAccessTokenAuthorizationDetails(anyString(), anyInt());
+
+ this.uut.deleteAccessTokenAuthorizationDetails(ACESS_TOKEN_ID, TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(0)).getAccessTokenAuthorizationDetails(anyString(), anyInt());
+ }
+
+ @Test(groups = {"feature-disabled-flow-tests"})
+ public void testOAuth2CodeAuthorizationDetailsWhenFeatureIsDisabled() throws SQLException, IdentityOAuth2Exception {
+
+ uut.storeAuthorizationCodeAuthorizationDetails(null, new OAuthAuthzReqMessageContext(null));
+ verify(authorizationDetailsDAOMock, times(0)).addOAuth2CodeAuthorizationDetails(anySet());
+
+ this.uut.getAuthorizationCodeAuthorizationDetails("", TENANT_ID);
+ verify(authorizationDetailsDAOMock, times(0)).getOAuth2CodeAuthorizationDetails(anyString(), anyInt());
+ }
+
}
From 0c03aa3f9fbbdae33850e11178697d0db1061d91 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Fri, 17 Jan 2025 17:27:07 +0530
Subject: [PATCH 18/28] Update license to 2025
---
.../AuthorizationDetailsServiceFactory.java | 2 +-
.../org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../AuthorizationDetailsSchemaValidator.java | 2 +-
.../rar/dao/AuthorizationDetailsDAO.java | 2 +-
.../rar/dao/AuthorizationDetailsDAOImpl.java | 2 +-
.../identity/oauth2/rar/dao/SQLQueries.java | 2 +-
.../rar/dto/AuthorizationDetailsCodeDTO.java | 18 ++++++++++++++++++
.../dto/AuthorizationDetailsConsentDTO.java | 18 ++++++++++++++++++
.../rar/dto/AuthorizationDetailsDTO.java | 2 +-
.../rar/dto/AuthorizationDetailsTokenDTO.java | 18 ++++++++++++++++++
...uthorizationDetailsProcessingException.java | 18 ++++++++++++++++++
.../oauth2/rar/model/AuthorizationDetail.java | 2 +-
.../oauth2/rar/model/AuthorizationDetails.java | 2 +-
.../oauth2/rar/model/ValidationResult.java | 2 +-
.../util/AuthorizationDetailsCommonUtils.java | 2 +-
.../util/AuthorizationDetailsConstants.java | 2 +-
...uthorizationDetailsSchemaValidatorTest.java | 2 +-
.../dao/AuthorizationDetailsDAOImplTest.java | 2 +-
.../AuthorizationDetailsCommonUtilsTest.java | 2 +-
.../oauth2/rar/util/TestConstants.java | 2 +-
.../identity/oauth2/rar/util/TestDAOUtils.java | 2 +-
.../src/test/resources/testng.xml | 2 +-
.../rar/AuthorizationDetailsService.java | 2 +-
.../core/AuthorizationDetailsProcessor.java | 2 +-
.../AuthorizationDetailsProcessorFactory.java | 2 +-
.../rar/model/AuthorizationDetailsContext.java | 2 +-
.../token/AccessTokenResponseRARHandler.java | 2 +-
.../token/IntrospectionRARDataProvider.java | 2 +-
.../token/JWTAccessTokenRARClaimProvider.java | 2 +-
.../rar/util/AuthorizationDetailsUtils.java | 2 +-
.../AuthorizationDetailsValidator.java | 2 +-
.../DefaultAuthorizationDetailsValidator.java | 2 +-
.../rar/AuthorizationDetailsServiceTest.java | 2 +-
.../AccessTokenResponseRARHandlerTest.java | 2 +-
.../IntrospectionRARDataProviderTest.java | 2 +-
.../JWTAccessTokenRARClaimProviderTest.java | 2 +-
.../utils/AuthorizationDetailsBaseTest.java | 2 +-
...faultAuthorizationDetailsValidatorTest.java | 2 +-
38 files changed, 106 insertions(+), 34 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
index f33588a722..af195571c7 100644
--- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
+++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/factory/AuthorizationDetailsServiceFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * Copyright (c) 2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index ac4fa5d2d0..5d491ddac4 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -1,6 +1,6 @@
- io.vertx
+ org.wso2.orbit.io.vertx
vertx-json-schema
- ${vertx.json.schema.version}
+ ${vertx.json.schema.wso2.osgi.version}
+
+
+ org.wso2.orbit.io.netty
+ netty-all
+ ${netty-all.wso2.osgi.version}
@@ -1055,7 +1060,9 @@
2.4.7
5.2
9.2
- 4.5.11
+ 4.5.11.wso2v1
+ [4.5.11, 5.0.0)
+ 4.1.115.wso2v1
5.1.2
From 4959016ab05d3bf410ac77dbe2b06266dc4dd951 Mon Sep 17 00:00:00 2001
From: vimukthiRajapaksha
Date: Thu, 23 Jan 2025 08:59:40 +0530
Subject: [PATCH 22/28] Bump RAR version to 7.0.219-SNAPSHOT
---
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 4 ----
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index be72db8d59..f83136d649 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -24,7 +24,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.215-SNAPSHOT
+ 7.0.219-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 11f6468f88..71b475b8f0 100644
--- a/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml
+++ b/features/org.wso2.carbon.identity.oauth.server.feature/pom.xml
@@ -120,10 +120,6 @@
org.wso2.carbon.identity.inbound.auth.oauth2
org.wso2.carbon.identity.client.attestation.filter
-
- org.wso2.orbit.io.vertx
- vertx-json-schema
-
From 16cd35043be929230f3452a79c1e76318968e5ad Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 07:10:10 +0000
Subject: [PATCH 23/28] [WSO2 Release] [Jenkins #5172] [Release 7.0.219]
prepare release v7.0.219
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 6 ++----
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
.../org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 32 insertions(+), 34 deletions(-)
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 e2e44506b7..b0ce46621b 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.219-SNAPSHOT
+ 7.0.219
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.219-SNAPSHOT
+ 7.0.219
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 73a1943011..7b3910c784 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.219-SNAPSHOT
+ 7.0.219
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.219-SNAPSHOT
+ 7.0.219
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 bf2d312be5..88f5073bf6 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.219-SNAPSHOT
+ 7.0.219
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index 6c3bc0d82e..b6921ca62f 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.219-SNAPSHOT
+ 7.0.219
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 b1ce812487..7c3e4ddb9e 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.219-SNAPSHOT
+ 7.0.219
../../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 2539660e24..8a272954d0 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.219-SNAPSHOT
+ 7.0.219
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 7dd72856aa..f28fdbb5da 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.219-SNAPSHOT
+ 7.0.219
4.0.0
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 72daea93b2..239c0419a6 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.219-SNAPSHOT
+ 7.0.219
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 82df845436..9d1eb0dc57 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.219-SNAPSHOT
+ 7.0.219
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 b7965ec57a..b1bf0865b7 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.219-SNAPSHOT
+ 7.0.219
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 5092392fe5..57c269c09e 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.219-SNAPSHOT
+ 7.0.219
../../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 4676d51a1d..ef0a7b103e 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index f83136d649..6dc1a03f60 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -16,15 +16,13 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.219-SNAPSHOT
+ 7.0.219
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 aacebc802f..1fd2a54ae7 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.219-SNAPSHOT
+ 7.0.219
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 af88724432..66b4cac263 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index 61b3254601..b33405f3b1 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 1c4267e9c5..26300b8106 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index 7f3f2bf5ed..b37f6559f8 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.219-SNAPSHOT
+ 7.0.219
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 b054c08ef8..de893379a9 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/components/org.wso2.carbon.identity.webfinger/pom.xml b/components/org.wso2.carbon.identity.webfinger/pom.xml
index bf0ea5fbf6..3b19e4b51f 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.219-SNAPSHOT
+ 7.0.219
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 ebb8e3e44d..c26d6a6e6f 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.219-SNAPSHOT
+ 7.0.219
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 2f70c712db..3022f5a495 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.219-SNAPSHOT
+ 7.0.219
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 f5ea737204..3c0919b9ca 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.219-SNAPSHOT
+ 7.0.219
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 71b475b8f0..338c35d2ee 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.219-SNAPSHOT
+ 7.0.219
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 72047250dd..e1395f4fab 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.219-SNAPSHOT
+ 7.0.219
4.0.0
diff --git a/pom.xml b/pom.xml
index add9f3bf7f..94632131c1 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.219-SNAPSHOT
+ 7.0.219
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- HEAD
+ v7.0.219
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 4c7c603a6c..1f58c459e8 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.219-SNAPSHOT
+ 7.0.219
../../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 c118e9217e..ef9950b2e2 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.219-SNAPSHOT
+ 7.0.219
4.0.0
From 209b7eaaf5a494d864d0cffaf0e322ec2f4df426 Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 07:10:13 +0000
Subject: [PATCH 24/28] [WSO2 Release] [Jenkins #5172] [Release 7.0.219]
prepare for next development iteration
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 31 insertions(+), 31 deletions(-)
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 b0ce46621b..a64882ab66 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.219
+ 7.0.220-SNAPSHOT
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.219
+ 7.0.220-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 7b3910c784..0a2a4ff341 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.219
+ 7.0.220-SNAPSHOT
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.219
+ 7.0.220-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 88f5073bf6..7f82d0e55c 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.219
+ 7.0.220-SNAPSHOT
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index b6921ca62f..fc304c5a25 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.219
+ 7.0.220-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 7c3e4ddb9e..ff30d5326a 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.219
+ 7.0.220-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 8a272954d0..ec1c3548cb 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.219
+ 7.0.220-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 f28fdbb5da..674aadb49a 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.219
+ 7.0.220-SNAPSHOT
4.0.0
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 239c0419a6..8d554f6c05 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.219
+ 7.0.220-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 9d1eb0dc57..fcbfbf1a15 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.219
+ 7.0.220-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 b1bf0865b7..08e0170718 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.219
+ 7.0.220-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 57c269c09e..5dd749dd2c 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.219
+ 7.0.220-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 ef0a7b103e..e76683d3f8 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.219
+ 7.0.220-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 6dc1a03f60..6be36573f2 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -22,7 +22,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.219
+ 7.0.220-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 1fd2a54ae7..0f1261ab65 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.219
+ 7.0.220-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 66b4cac263..2262fd45d8 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.219
+ 7.0.220-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index b33405f3b1..56f4d1fc85 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.219
+ 7.0.220-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 26300b8106..2cd71c4ce4 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.219
+ 7.0.220-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index b37f6559f8..38ccf1578c 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.219
+ 7.0.220-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 de893379a9..6f2b41bf3d 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.219
+ 7.0.220-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 3b19e4b51f..ae83e6987d 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.219
+ 7.0.220-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 c26d6a6e6f..180478d064 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.219
+ 7.0.220-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 3022f5a495..a3bb61d6bd 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.219
+ 7.0.220-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 3c0919b9ca..533190ce72 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.219
+ 7.0.220-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 338c35d2ee..d7c24d24d1 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.219
+ 7.0.220-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 e1395f4fab..f4cde2b86d 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.219
+ 7.0.220-SNAPSHOT
4.0.0
diff --git a/pom.xml b/pom.xml
index 94632131c1..769dd5f252 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.219
+ 7.0.220-SNAPSHOT
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- v7.0.219
+ HEAD
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 1f58c459e8..a01a62636b 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.219
+ 7.0.220-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 ef9950b2e2..d6ca2f995e 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.219
+ 7.0.220-SNAPSHOT
4.0.0
From 9319df356f68e46fdc2af9204ca5bc6457661af8 Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 07:39:31 +0000
Subject: [PATCH 25/28] [WSO2 Release] [Jenkins #5174] [Release 7.0.220]
prepare release v7.0.220
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 31 insertions(+), 31 deletions(-)
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 a64882ab66..8636abd2bf 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.220-SNAPSHOT
+ 7.0.220
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.220-SNAPSHOT
+ 7.0.220
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 0a2a4ff341..12741e0b6f 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.220-SNAPSHOT
+ 7.0.220
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.220-SNAPSHOT
+ 7.0.220
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 7f82d0e55c..36336bb869 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.220-SNAPSHOT
+ 7.0.220
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index fc304c5a25..710438ad93 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.220-SNAPSHOT
+ 7.0.220
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 ff30d5326a..6769926bc3 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.220-SNAPSHOT
+ 7.0.220
../../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 ec1c3548cb..65d8088e85 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.220-SNAPSHOT
+ 7.0.220
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 674aadb49a..9092af0662 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.220-SNAPSHOT
+ 7.0.220
4.0.0
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 8d554f6c05..03c7fe6110 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.220-SNAPSHOT
+ 7.0.220
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 fcbfbf1a15..62032826b3 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.220-SNAPSHOT
+ 7.0.220
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 08e0170718..d2cdca196f 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.220-SNAPSHOT
+ 7.0.220
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 5dd749dd2c..74b0370d27 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.220-SNAPSHOT
+ 7.0.220
../../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 e76683d3f8..e799a7c1af 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 6be36573f2..68ffd97bd7 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -22,7 +22,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.220-SNAPSHOT
+ 7.0.220
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 0f1261ab65..32a6b275a0 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.220-SNAPSHOT
+ 7.0.220
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 2262fd45d8..d8e89bf9b9 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index 56f4d1fc85..67f9813be8 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 2cd71c4ce4..f2b12495e4 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index 38ccf1578c..c53df5fd5f 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.220-SNAPSHOT
+ 7.0.220
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 6f2b41bf3d..9b6f8e36ca 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/components/org.wso2.carbon.identity.webfinger/pom.xml b/components/org.wso2.carbon.identity.webfinger/pom.xml
index ae83e6987d..8167aa854d 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.220-SNAPSHOT
+ 7.0.220
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 180478d064..f6d5a34f92 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.220-SNAPSHOT
+ 7.0.220
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 a3bb61d6bd..f29cf508dd 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.220-SNAPSHOT
+ 7.0.220
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 533190ce72..45f722e5de 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.220-SNAPSHOT
+ 7.0.220
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 d7c24d24d1..699aba5473 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.220-SNAPSHOT
+ 7.0.220
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 f4cde2b86d..98e0f78946 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.220-SNAPSHOT
+ 7.0.220
4.0.0
diff --git a/pom.xml b/pom.xml
index 769dd5f252..bac9a996b6 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.220-SNAPSHOT
+ 7.0.220
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- HEAD
+ v7.0.220
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 a01a62636b..04357fe87a 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.220-SNAPSHOT
+ 7.0.220
../../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 d6ca2f995e..c56e4425c9 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.220-SNAPSHOT
+ 7.0.220
4.0.0
From e64fd7dcf89f32be3c94c981cb27b98f63899f8d Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 07:39:33 +0000
Subject: [PATCH 26/28] [WSO2 Release] [Jenkins #5174] [Release 7.0.220]
prepare for next development iteration
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 31 insertions(+), 31 deletions(-)
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 8636abd2bf..4e0d52d30d 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.220
+ 7.0.221-SNAPSHOT
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.220
+ 7.0.221-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 12741e0b6f..7379022b9d 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.220
+ 7.0.221-SNAPSHOT
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.220
+ 7.0.221-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 36336bb869..88b16104a2 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.220
+ 7.0.221-SNAPSHOT
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index 710438ad93..7426828081 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.220
+ 7.0.221-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 6769926bc3..b3d1164f03 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.220
+ 7.0.221-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 65d8088e85..c219e81be7 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.220
+ 7.0.221-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 9092af0662..0085ee7a3c 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.220
+ 7.0.221-SNAPSHOT
4.0.0
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 03c7fe6110..48b4eccc19 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.220
+ 7.0.221-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 62032826b3..d87535581d 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.220
+ 7.0.221-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 d2cdca196f..d1b500dca3 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.220
+ 7.0.221-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 74b0370d27..bbcc9c297e 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.220
+ 7.0.221-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 e799a7c1af..c12b26d353 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.220
+ 7.0.221-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 68ffd97bd7..56d4f19c10 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -22,7 +22,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.220
+ 7.0.221-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 32a6b275a0..535d77a8a3 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.220
+ 7.0.221-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 d8e89bf9b9..e03a1a5a27 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.220
+ 7.0.221-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index 67f9813be8..5f80835e08 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.220
+ 7.0.221-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 f2b12495e4..ada1b8ee86 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.220
+ 7.0.221-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index c53df5fd5f..56180f1500 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.220
+ 7.0.221-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 9b6f8e36ca..bbd4c84a05 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.220
+ 7.0.221-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 8167aa854d..afcfd84e61 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.220
+ 7.0.221-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 f6d5a34f92..63b6dc026f 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.220
+ 7.0.221-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 f29cf508dd..0c8570e2b2 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.220
+ 7.0.221-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 45f722e5de..497b2a9631 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.220
+ 7.0.221-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 699aba5473..a838be3132 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.220
+ 7.0.221-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 98e0f78946..69dea60e28 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.220
+ 7.0.221-SNAPSHOT
4.0.0
diff --git a/pom.xml b/pom.xml
index bac9a996b6..c649707371 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.220
+ 7.0.221-SNAPSHOT
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- v7.0.220
+ HEAD
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 04357fe87a..3b6120cfa2 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.220
+ 7.0.221-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 c56e4425c9..c2f217653f 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.220
+ 7.0.221-SNAPSHOT
4.0.0
From 11826d55347f5ada81aad9e16afb4f7ece049409 Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 09:13:56 +0000
Subject: [PATCH 27/28] [WSO2 Release] [Jenkins #5176] [Release 7.0.221]
prepare release v7.0.221
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 31 insertions(+), 31 deletions(-)
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 4e0d52d30d..20d651a27f 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.221-SNAPSHOT
+ 7.0.221
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.221-SNAPSHOT
+ 7.0.221
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 7379022b9d..4ce1d5726f 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.221-SNAPSHOT
+ 7.0.221
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.221-SNAPSHOT
+ 7.0.221
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 88b16104a2..7eb433b2f2 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.221-SNAPSHOT
+ 7.0.221
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index 7426828081..0497b8b97c 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.221-SNAPSHOT
+ 7.0.221
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 b3d1164f03..7540be594e 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.221-SNAPSHOT
+ 7.0.221
../../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 c219e81be7..4354b2844a 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.221-SNAPSHOT
+ 7.0.221
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 0085ee7a3c..bd22927189 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.221-SNAPSHOT
+ 7.0.221
4.0.0
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 48b4eccc19..0f36137766 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.221-SNAPSHOT
+ 7.0.221
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 d87535581d..0122bab97e 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.221-SNAPSHOT
+ 7.0.221
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 d1b500dca3..f9283ba2e9 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.221-SNAPSHOT
+ 7.0.221
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 bbcc9c297e..fb1bd19517 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.221-SNAPSHOT
+ 7.0.221
../../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 c12b26d353..54c1af08b6 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index 56d4f19c10..d8eee0d701 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -22,7 +22,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.221-SNAPSHOT
+ 7.0.221
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 535d77a8a3..7acf157a2a 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.221-SNAPSHOT
+ 7.0.221
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 e03a1a5a27..587bb90e35 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index 5f80835e08..e4f436023e 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index ada1b8ee86..129bb33c0d 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index 56180f1500..304769b1cc 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.221-SNAPSHOT
+ 7.0.221
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 bbd4c84a05..8a4239a37f 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/components/org.wso2.carbon.identity.webfinger/pom.xml b/components/org.wso2.carbon.identity.webfinger/pom.xml
index afcfd84e61..15266777d0 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.221-SNAPSHOT
+ 7.0.221
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 63b6dc026f..47b7daef1b 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.221-SNAPSHOT
+ 7.0.221
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 0c8570e2b2..6128c1fa29 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.221-SNAPSHOT
+ 7.0.221
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 497b2a9631..9a8304740d 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.221-SNAPSHOT
+ 7.0.221
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 a838be3132..3369bcd727 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.221-SNAPSHOT
+ 7.0.221
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 69dea60e28..ca6b142222 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.221-SNAPSHOT
+ 7.0.221
4.0.0
diff --git a/pom.xml b/pom.xml
index c649707371..f3fc4a5a22 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.221-SNAPSHOT
+ 7.0.221
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- HEAD
+ v7.0.221
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 3b6120cfa2..0883399bb6 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.221-SNAPSHOT
+ 7.0.221
../../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 c2f217653f..f432126bc5 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.221-SNAPSHOT
+ 7.0.221
4.0.0
From a22fe6d70688b2628195478b32f5c83b926dea61 Mon Sep 17 00:00:00 2001
From: WSO2 Builder
Date: Thu, 23 Jan 2025 09:13:58 +0000
Subject: [PATCH 28/28] [WSO2 Release] [Jenkins #5176] [Release 7.0.221]
prepare for next development iteration
---
components/org.wso2.carbon.identity.api.server.dcr/pom.xml | 4 ++--
.../org.wso2.carbon.identity.api.server.oauth.scope/pom.xml | 4 ++--
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.discovery/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ciba/pom.xml | 2 +-
.../pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.common/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.extension/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.par/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.rar/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.scope.endpoint/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.stub/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth.ui/pom.xml | 2 +-
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.dcr/pom.xml | 2 +-
components/org.wso2.carbon.identity.oidc.session/pom.xml | 2 +-
components/org.wso2.carbon.identity.webfinger/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.dcr.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.feature/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.server.feature/pom.xml | 2 +-
features/org.wso2.carbon.identity.oauth.ui.feature/pom.xml | 2 +-
pom.xml | 4 ++--
service-stubs/org.wso2.carbon.claim.metadata.mgt.stub/pom.xml | 2 +-
.../org.wso2.carbon.identity.oauth.common.testng/pom.xml | 2 +-
28 files changed, 31 insertions(+), 31 deletions(-)
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 20d651a27f..b1baab8e02 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.221
+ 7.0.222-SNAPSHOT
../../pom.xml
org.wso2.carbon.identity.api.server.dcr
- 7.0.221
+ 7.0.222-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 4ce1d5726f..79b06403cb 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.221
+ 7.0.222-SNAPSHOT
../..
org.wso2.carbon.identity.api.server.oauth.scope
- 7.0.221
+ 7.0.222-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 7eb433b2f2..588d3bcd58 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.221
+ 7.0.222-SNAPSHOT
../../pom.xml
diff --git a/components/org.wso2.carbon.identity.discovery/pom.xml b/components/org.wso2.carbon.identity.discovery/pom.xml
index 0497b8b97c..6157f7646b 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.221
+ 7.0.222-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 7540be594e..06993486fc 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.221
+ 7.0.222-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 4354b2844a..d23605575c 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.221
+ 7.0.222-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 bd22927189..378948f89c 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.221
+ 7.0.222-SNAPSHOT
4.0.0
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 0f36137766..486120eb3a 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.221
+ 7.0.222-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 0122bab97e..b2a688c39e 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.221
+ 7.0.222-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 f9283ba2e9..8ed421354c 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.221
+ 7.0.222-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 fb1bd19517..77081413ec 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.221
+ 7.0.222-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 54c1af08b6..0d7c04fdd7 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.221
+ 7.0.222-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.rar/pom.xml b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
index d8eee0d701..0abc113005 100644
--- a/components/org.wso2.carbon.identity.oauth.rar/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth.rar/pom.xml
@@ -22,7 +22,7 @@
org.wso2.carbon.identity.inbound.auth.oauth2
identity-inbound-auth-oauth
../../pom.xml
- 7.0.221
+ 7.0.222-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 7acf157a2a..4f8f56dd8b 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.221
+ 7.0.222-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 587bb90e35..6e7b1b9029 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.221
+ 7.0.222-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oauth.ui/pom.xml b/components/org.wso2.carbon.identity.oauth.ui/pom.xml
index e4f436023e..2f1e638143 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.221
+ 7.0.222-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 129bb33c0d..26158431a6 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.221
+ 7.0.222-SNAPSHOT
4.0.0
diff --git a/components/org.wso2.carbon.identity.oidc.dcr/pom.xml b/components/org.wso2.carbon.identity.oidc.dcr/pom.xml
index 304769b1cc..f62669a8eb 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.221
+ 7.0.222-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 8a4239a37f..120eab8fa3 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.221
+ 7.0.222-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 15266777d0..1187078c7b 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.221
+ 7.0.222-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 47b7daef1b..7e84cb5cb1 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.221
+ 7.0.222-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 6128c1fa29..7746f0d1fe 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.221
+ 7.0.222-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 9a8304740d..fc94e58d5d 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.221
+ 7.0.222-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 3369bcd727..405785f51b 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.221
+ 7.0.222-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 ca6b142222..d95c879597 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.221
+ 7.0.222-SNAPSHOT
4.0.0
diff --git a/pom.xml b/pom.xml
index f3fc4a5a22..6951d0e3d5 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.221
+ 7.0.222-SNAPSHOT
pom
WSO2 Carbon OAuth module
http://wso2.org
@@ -37,7 +37,7 @@
https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
scm:git:https://github.com/wso2-extensions/identity-inbound-auth-oauth.git
- v7.0.221
+ HEAD
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 0883399bb6..fc7fb5af05 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.221
+ 7.0.222-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 f432126bc5..62a7bb22ea 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.221
+ 7.0.222-SNAPSHOT
4.0.0