From d7717f01231869bc228140200cb88c0a6607adf0 Mon Sep 17 00:00:00 2001
From: DilshanSenarath <74205483+DilshanSenarath@users.noreply.github.com>
Date: Tue, 1 Oct 2024 18:07:48 +0530
Subject: [PATCH 1/6] add authenticated user validation logic for the refresh
grant flow
---
.../org.wso2.carbon.identity.oauth/pom.xml | 5 ++
.../config/OAuthServerConfiguration.java | 31 ++++++++
.../internal/OAuth2ServiceComponent.java | 24 +++++++
.../OAuth2ServiceComponentHolder.java | 22 ++++++
.../handlers/grant/RefreshGrantHandler.java | 72 +++++++++++++++++++
pom.xml | 11 +++
6 files changed, 165 insertions(+)
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 8910c5ee4c7..c8d3e27b784 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -115,6 +115,10 @@
org.wso2.carbon.identity.framework
org.wso2.carbon.identity.event
+
+ org.wso2.carbon.identity.event.handler.accountlock
+ org.wso2.carbon.identity.handler.event.account.lock
+
org.wso2.carbon.identity.framework
org.wso2.carbon.identity.core
@@ -435,6 +439,7 @@
org.wso2.carbon.identity.organization.management.role.management.service.models; version="${carbon.identity.organization.management.version.range}",
org.wso2.carbon.identity.organization.management.organization.user.sharing.util;version="${carbon.identity.organization.management.version.range}",
org.wso2.carbon.identity.organization.management.organization.user.sharing.models;version="${carbon.identity.organization.management.version.range}",
+ org.wso2.carbon.identity.handler.event.account.lock.service.*;version="${account.lock.service.imp.pkg.version.range}",
org.wso2.carbon.base; version="${carbon.base.imp.pkg.version.range}",
org.wso2.carbon.registry.api;version="${carbon.kernel.registry.imp.pkg.version.range}",
diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfiguration.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfiguration.java
index 07350987a2c..5072ec576ef 100644
--- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfiguration.java
+++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfiguration.java
@@ -161,6 +161,7 @@ public class OAuthServerConfiguration {
private boolean isTokenRenewalPerRequestEnabled = false;
private boolean isRefreshTokenRenewalEnabled = true;
private boolean isExtendRenewedTokenExpiryTimeEnabled = true;
+ private boolean isValidateAuthenticatedUserForRefreshGrantEnabled = false;
private boolean assertionsUserNameEnabled = false;
private boolean accessTokenPartitioningEnabled = false;
private boolean redirectToRequestedRedirectUriEnabled = true;
@@ -417,6 +418,9 @@ private void buildOAuthServerConfiguration() {
// read refresh token renewal config
parseRefreshTokenRenewalConfiguration(oauthElem);
+ // Read the authenticated user validation config for refresh grant.
+ parseRefreshTokenGrantValidationConfiguration(oauthElem);
+
// read token persistence processor config
parseTokenPersistenceProcessorConfig(oauthElem);
@@ -944,6 +948,16 @@ public boolean isExtendRenewedTokenExpiryTimeEnabled() {
return isExtendRenewedTokenExpiryTimeEnabled;
}
+ /**
+ * Check if the authenticated user validation is enabled for refresh token grant flow.
+ *
+ * @return Returns true if the config is enabled.
+ */
+ public boolean isValidateAuthenticatedUserForRefreshGrantEnabled() {
+
+ return isValidateAuthenticatedUserForRefreshGrantEnabled;
+ }
+
public Map getOauthTokenIssuerMap() {
return oauthTokenIssuerMap;
}
@@ -2231,6 +2245,20 @@ private void parseRefreshTokenRenewalConfiguration(OMElement oauthConfigElem) {
}
}
+ private void parseRefreshTokenGrantValidationConfiguration(OMElement oauthConfigElem) {
+
+ OMElement validateAuthenticatedUserForRefreshGrantElem = oauthConfigElem.getFirstChildWithName(
+ getQNameWithIdentityNS(ConfigElements.VALIDATE_AUTHENTICATED_USER_FOR_REFRESH_GRANT));
+ if (validateAuthenticatedUserForRefreshGrantElem != null) {
+ isValidateAuthenticatedUserForRefreshGrantEnabled =
+ Boolean.parseBoolean(validateAuthenticatedUserForRefreshGrantElem.getText());
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("ValidateAuthenticatedUserForRefreshGrant was set to : " +
+ isValidateAuthenticatedUserForRefreshGrantEnabled);
+ }
+ }
+
private void parseAccessTokenPartitioningConfig(OMElement oauthConfigElem) {
OMElement enableAccessTokenPartitioningElem =
@@ -3933,6 +3961,9 @@ private class ConfigElements {
private static final String ENABLE_CACHE = "EnableOAuthCache";
// Enable/Disable refresh token renewal on each refresh_token grant request
private static final String RENEW_REFRESH_TOKEN_FOR_REFRESH_GRANT = "RenewRefreshTokenForRefreshGrant";
+ // Enable/Disable Authenticated user validation on refresh_token grant request.
+ private static final String VALIDATE_AUTHENTICATED_USER_FOR_REFRESH_GRANT =
+ "ValidateAuthenticatedUserForRefreshGrant";
// Enable/Disable extend the lifetime of the new refresh token
private static final String EXTEND_RENEWED_REFRESH_TOKEN_EXPIRY_TIME = "ExtendRenewedRefreshTokenExpiryTime";
// TokenPersistenceProcessor
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 7e4db0f45ff..c1ba6b58ec2 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
@@ -48,6 +48,7 @@
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.event.handler.AbstractEventHandler;
import org.wso2.carbon.identity.event.services.IdentityEventService;
+import org.wso2.carbon.identity.handler.event.account.lock.service.AccountLockService;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth.common.token.bindings.TokenBinderInfo;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
@@ -1612,4 +1613,27 @@ protected void unregisterConfigurationManager(ConfigurationManager configuration
}
OAuth2ServiceComponentHolder.getInstance().setConfigurationManager(null);
}
+
+ @Reference(
+ name = "org.wso2.carbon.identity.handler.event.account.lock.service.AccountLockService",
+ service = AccountLockService.class,
+ cardinality = ReferenceCardinality.MANDATORY,
+ policy = ReferencePolicy.DYNAMIC,
+ unbind = "unsetAccountLockService"
+ )
+ protected void setAccountLockService(AccountLockService accountLockService) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("AccountLockService set in OAuth2ServiceComponent bundle.");
+ }
+ OAuth2ServiceComponentHolder.setAccountLockService(accountLockService);
+ }
+
+ protected void unsetAccountLockService(AccountLockService accountLockService) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("AccountLockService unset in OAuth2ServiceComponent bundle.");
+ }
+ OAuth2ServiceComponentHolder.setAccountLockService(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 c22e3f9ffdc..1f5f5b0b95a 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
@@ -29,6 +29,7 @@
import org.wso2.carbon.identity.core.SAMLSSOServiceProviderManager;
import org.wso2.carbon.identity.core.handler.HandlerComparator;
import org.wso2.carbon.identity.event.services.IdentityEventService;
+import org.wso2.carbon.identity.handler.event.account.lock.service.AccountLockService;
import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl;
import org.wso2.carbon.identity.oauth.dto.ScopeDTO;
import org.wso2.carbon.identity.oauth.tokenprocessor.DefaultOAuth2RevocationProcessor;
@@ -122,6 +123,7 @@ public class OAuth2ServiceComponentHolder {
private List impersonationValidators = new ArrayList<>();
private ConfigurationManager configurationManager;
+ private static AccountLockService accountLockService;
private OAuth2ServiceComponentHolder() {
@@ -889,4 +891,24 @@ public void setConfigurationManager(ConfigurationManager configurationManager) {
this.configurationManager = configurationManager;
}
+
+ /**
+ * Set the account lock service to the OAuth2ServiceComponentHolder.
+ *
+ * @param accountLockService Account lock service instance.
+ */
+ public static void setAccountLockService(AccountLockService accountLockService) {
+
+ OAuth2ServiceComponentHolder.accountLockService = accountLockService;
+ }
+
+ /**
+ * Retrieve the account lock service.
+ *
+ * @return Account lock service instance.
+ */
+ public static AccountLockService getAccountLockService() {
+
+ return OAuth2ServiceComponentHolder.accountLockService;
+ }
}
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 f4d5e3dfa5a..c47bd808f7e 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
@@ -27,10 +27,15 @@
import org.wso2.carbon.identity.action.execution.exception.ActionExecutionException;
import org.wso2.carbon.identity.action.execution.model.ActionExecutionStatus;
import org.wso2.carbon.identity.action.execution.model.ActionType;
+import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException;
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.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.base.IdentityConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
+import org.wso2.carbon.identity.handler.event.account.lock.exception.AccountLockServiceException;
+import org.wso2.carbon.identity.handler.event.account.lock.service.AccountLockService;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey;
@@ -52,11 +57,16 @@
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.token.AccessTokenIssuer;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.OauthTokenIssuer;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
+import org.wso2.carbon.identity.user.profile.mgt.association.federation.FederatedAssociationManager;
+import org.wso2.carbon.identity.user.profile.mgt.association.federation.exception.FederatedAssociationManagerException;
+import org.wso2.carbon.user.core.UserCoreConstants;
+import org.wso2.carbon.user.core.util.UserCoreUtil;
import java.sql.Timestamp;
import java.util.Arrays;
@@ -69,6 +79,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
+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.oauth.common.OAuthConstants.GrantTypes.REFRESH_TOKEN;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenBindings.NONE;
import static org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration.JWT_TOKEN_TYPE;
@@ -86,6 +98,8 @@ public class RefreshGrantHandler extends AbstractAuthorizationGrantHandler {
public static final String DEACTIVATED_ACCESS_TOKEN = "DeactivatedAccessToken";
private static final Log log = LogFactory.getLog(RefreshGrantHandler.class);
private boolean isHashDisabled = OAuth2Util.isHashDisabled();
+ private static final String ACCOUNT_LOCK_ERROR_MESSAGE = "Account is locked for user %s in tenant %s. Cannot" +
+ " login until the account is unlocked.";
@Override
public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
@@ -98,6 +112,7 @@ public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
validateRefreshTokenInRequest(tokenReq, validationBean);
validateTokenBindingReference(tokenReq, validationBean);
+ validateAuthenticatedUser(validationBean, tokReqMsgCtx);
if (log.isDebugEnabled()) {
log.debug("Refresh token validation successful for Client id : " + tokenReq.getClientId() +
@@ -282,6 +297,63 @@ private boolean validateRefreshTokenStatus(RefreshTokenValidationDataDO validati
return true;
}
+ private boolean validateAuthenticatedUser(RefreshTokenValidationDataDO validationBean,
+ OAuthTokenReqMessageContext oAuthTokenReqMessageContext)
+ throws IdentityOAuth2Exception {
+
+ if (!OAuthServerConfiguration.getInstance().isValidateAuthenticatedUserForRefreshGrantEnabled()) {
+ return true;
+ }
+
+ AuthenticatedUser authenticatedUser = validationBean.getAuthorizedUser();
+ if (authenticatedUser != null) {
+ String username = null;
+ String tenantDomain = null;
+
+ if (authenticatedUser.isFederatedUser()) {
+ try {
+ FederatedAssociationManager federatedAssociationManager =
+ FrameworkUtils.getFederatedAssociationManager();
+ OAuthAppDO oAuthAppDO =
+ (OAuthAppDO) oAuthTokenReqMessageContext.getProperty(AccessTokenIssuer.OAUTH_APP_DO);
+ String oAuthAppTenantDomain = OAuth2Util.getTenantDomainOfOauthApp(oAuthAppDO);
+ String associatedLocalUsername =
+ federatedAssociationManager.getUserForFederatedAssociation(oAuthAppTenantDomain,
+ authenticatedUser.getFederatedIdPName(),
+ authenticatedUser.getAuthenticatedSubjectIdentifier());
+ if (associatedLocalUsername != null) {
+ username = associatedLocalUsername;
+ tenantDomain = oAuthAppTenantDomain;
+ }
+ } catch (FederatedAssociationManagerException | FrameworkException e) {
+ throw new IdentityOAuth2Exception(ERROR_WHILE_GETTING_USERNAME_ASSOCIATED_WITH_IDP.getCode(),
+ String.format(ERROR_WHILE_GETTING_USERNAME_ASSOCIATED_WITH_IDP.getMessage(),
+ authenticatedUser.getFederatedIdPName()), e);
+ }
+ } else {
+ username = UserCoreUtil.addDomainToName(authenticatedUser.getUserName(),
+ authenticatedUser.getUserStoreDomain());
+ tenantDomain = authenticatedUser.getTenantDomain();
+ }
+
+ if (username != null && tenantDomain != null) {
+ AccountLockService accountLockService = OAuth2ServiceComponentHolder.getAccountLockService();
+
+ try {
+ boolean accountLockStatus = accountLockService.isAccountLocked(username, tenantDomain);
+ if (accountLockStatus) {
+ throw new IdentityOAuth2Exception(UserCoreConstants.ErrorCode.USER_IS_LOCKED,
+ String.format(ACCOUNT_LOCK_ERROR_MESSAGE, username, tenantDomain));
+ }
+ } catch (AccountLockServiceException e) {
+ throw new IdentityOAuth2Exception(ERROR_WHILE_CHECKING_ACCOUNT_LOCK_STATUS.getCode(),
+ String.format(ERROR_WHILE_CHECKING_ACCOUNT_LOCK_STATUS.getMessage(), username), e);
+ }
+ }
+ }
+
+ return true;
+ }
private OAuth2AccessTokenRespDTO buildTokenResponse(OAuthTokenReqMessageContext tokReqMsgCtx,
AccessTokenDO accessTokenBean) {
diff --git a/pom.xml b/pom.xml
index c21df78ab3b..7c1f61d6950 100644
--- a/pom.xml
+++ b/pom.xml
@@ -289,6 +289,13 @@
${saml.common.util.version}
+
+
+ org.wso2.carbon.identity.event.handler.accountlock
+ org.wso2.carbon.identity.handler.event.account.lock
+ ${account.lock.service.version}
+
+
com.google.gdata.wso2
@@ -967,6 +974,10 @@
1.4.0
[1.4.0,1.5.0)
+
+ 1.9.11
+ [1.9.11, 2.0.0)
+
2.6.0.wso2v1
[2.6.0,3.0.0)
From cf9c07528390c2b29bb703caa5b7ff11db1ac0ab Mon Sep 17 00:00:00 2001
From: DilshanSenarath <74205483+DilshanSenarath@users.noreply.github.com>
Date: Mon, 14 Oct 2024 01:40:06 +0530
Subject: [PATCH 2/6] add unit tests for refresh grant user validation
---
.../org.wso2.carbon.identity.oauth/pom.xml | 6 +
.../config/OAuthServerConfigurationTest.java | 7 +
.../grant/RefreshGrantHandlerTest.java | 356 ++++++++----------
.../grant/RefreshGrantHandlerTestOld.java | 259 +++++++++++++
.../repository/conf/identity/identity.xml | 2 +
5 files changed, 422 insertions(+), 208 deletions(-)
create mode 100644 components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTestOld.java
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index c8d3e27b784..0c6974cdef7 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -552,6 +552,12 @@
+
+
+ org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponent
+ org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder
+
+
maven-resources-plugin
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfigurationTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfigurationTest.java
index 82370a75b2c..e99e8f54d78 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfigurationTest.java
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth/config/OAuthServerConfigurationTest.java
@@ -505,6 +505,13 @@ public void testGetSupportedTokenEndpointSigningAlgorithms() {
Assert.assertEquals(supportedTokenEndpointSigningAlgorithms.size(), 3);
}
+ @Test
+ public void testIsValidateAuthenticatedUserForRefreshGrantEnabled() throws Exception {
+
+ Assert.assertTrue(OAuthServerConfiguration.getInstance()
+ .isValidateAuthenticatedUserForRefreshGrantEnabled());
+ }
+
private String fillURLPlaceholdersForTest(String url) {
return url.replace("${carbon.protocol}", "https")
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 ce88014f3c8..9f089ec907e 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
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
- * WSO2 Inc. licenses this file to you under the Apache License,
+ * WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
@@ -11,249 +11,189 @@
* 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
+ * 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.token.handlers.grant;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
+import org.mockito.MockedStatic;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
-import org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl;
-import org.wso2.carbon.identity.application.mgt.internal.ApplicationManagementServiceComponent;
-import org.wso2.carbon.identity.application.mgt.internal.ApplicationManagementServiceComponentHolder;
-import org.wso2.carbon.identity.common.testng.WithCarbonHome;
-import org.wso2.carbon.identity.common.testng.WithH2Database;
-import org.wso2.carbon.identity.common.testng.WithRealmService;
+import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
+import org.wso2.carbon.identity.handler.event.account.lock.exception.AccountLockServiceException;
+import org.wso2.carbon.identity.handler.event.account.lock.service.AccountLockService;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
-import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO;
-import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
-import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
+import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
+import org.wso2.carbon.identity.oauth.tokenprocessor.DefaultRefreshTokenGrantProcessor;
+import org.wso2.carbon.identity.oauth.tokenprocessor.RefreshTokenGrantProcessor;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
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.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.test.common.testng.utils.MockAuthenticatedUser;
-import org.wso2.carbon.identity.testutil.Whitebox;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE;
-import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED;
-import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_INACTIVE;
-import static org.wso2.carbon.identity.oauth.common.OAuthConstants.UNASSIGNED_VALIDITY_PERIOD;
+import org.wso2.carbon.identity.user.profile.mgt.association.federation.FederatedAssociationManager;
+import org.wso2.carbon.identity.user.profile.mgt.association.federation.exception.FederatedAssociationManagerException;
+import org.wso2.carbon.user.core.UserCoreConstants;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+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;
/**
- * Test class for RefreshGrantHandler test cases.
+ * Unit tests for the RefreshGrantHandler class.
*/
-@WithCarbonHome
-@WithRealmService(injectToSingletons = { OAuthComponentServiceHolder.class,
- ApplicationManagementServiceComponentHolder.class })
-@WithH2Database(files = { "dbScripts/identity.sql", "dbScripts/insert_consumer_app.sql" })
public class RefreshGrantHandlerTest {
- private static final String TEST_USER_ID = "testUser";
- private static final String TEST_USER_DOMAIN = "testDomain";
- private RefreshGrantHandler refreshGrantHandler;
- private AuthenticatedUser authenticatedUser;
- private String[] scopes;
+ private RefreshTokenGrantProcessor refreshTokenGrantProcessor;
+ private OAuthTokenReqMessageContext oAuthTokenReqMessageContext;
+ private RefreshTokenValidationDataDO refreshTokenValidationDataDO;
+ private OAuthServerConfiguration oAuthServerConfiguration;
+ private OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO;
+ private OAuth2ServiceComponentHolder oAuth2ServiceComponentHolder;
- @BeforeClass
- protected void setUp() throws Exception {
- OAuth2ServiceComponentHolder.setApplicationMgtService(ApplicationManagementServiceImpl.getInstance());
- authenticatedUser = new MockAuthenticatedUser(TEST_USER_ID);
- authenticatedUser.setUserStoreDomain(TEST_USER_DOMAIN);
- scopes = new String[] { "scope1", "scope2" };
+ @BeforeMethod
+ public void init() {
+ refreshTokenGrantProcessor = mock(DefaultRefreshTokenGrantProcessor.class);
+ oAuthTokenReqMessageContext = mock(OAuthTokenReqMessageContext.class);
+ refreshTokenValidationDataDO = mock(RefreshTokenValidationDataDO.class);
+ oAuthServerConfiguration = mock(OAuthServerConfiguration.class);
+ oAuth2AccessTokenReqDTO = mock(OAuth2AccessTokenReqDTO.class);
+ oAuth2ServiceComponentHolder = mock(OAuth2ServiceComponentHolder.class);
}
- @BeforeMethod
- protected void setUpMethod() throws Exception {
+ @DataProvider(name = "validateGrantWhenUserIsLockedInUserStoreEnd")
+ public Object[][] validateGrantWhenUserIsLockedInUserStoreEnd() {
- ApplicationManagementServiceComponent applicationManagementServiceComponent =
- new ApplicationManagementServiceComponent();
- Whitebox.invokeMethod(applicationManagementServiceComponent, "buildFileBasedSPList", null);
- }
+ String userStoreDomain = "user-store-domain";
+ String tenantDomain = "tenant-domain";
+ String username = "user";
+ MockAuthenticatedUser user1 = new MockAuthenticatedUser(username);
+ user1.setUserStoreDomain(userStoreDomain);
+ user1.setTenantDomain(tenantDomain);
+
+ MockAuthenticatedUser user2 = new MockAuthenticatedUser(username);
- @DataProvider(name = "GetValidateGrantData")
- public Object[][] validateGrantData() {
+ String subjectIdentifier = "subject-identifier";
+ String federatedUserId = "federated-user-id";
+ String federatedIDPName = "federated-idp";
+ MockAuthenticatedUser federatedUser = new MockAuthenticatedUser(federatedUserId);
+ federatedUser.setAuthenticatedSubjectIdentifier(subjectIdentifier);
+ federatedUser.setFederatedUser(true);
+ federatedUser.setFederatedIdPName(federatedIDPName);
return new Object[][] {
- { "clientId1" },
- { "clientId2" },
- { "clientId2" }
+ { user1, null, null, false, null, false },
+ { user1, null, null, false, null, true },
+ { user1, null, null, true, null, true },
+ { federatedUser, null, null, false, null, true },
+ { federatedUser, user1, null, false, null, true },
+ { federatedUser, user1, null, true, null, true },
+ { federatedUser, user1, new FederatedAssociationManagerException("test error"), true, null, true },
+ { federatedUser, user1, new FrameworkException("test error"), true, null, true },
+ { federatedUser, user1, null, true, new AccountLockServiceException("test error"), true },
+ { null, null, null, false, null, true },
+ { user2, null, null, false, null, true }
};
}
- @Test(dataProvider = "GetValidateGrantData")
- public void testValidateGrant(String clientId)
+ /**
+ * Test scenarios for the `validateGrant` method when the user, locked at the user store level,
+ * attempts to use the refresh grant.
+ *
+ * @param user The user attempts to use the refresh grant.
+ * @param associatedUser Associated local user if the user is federated user.
+ * @param federatedAssociationManagerException Exception when resolving the local associated user.
+ * @param isUserLocked Whether the user is locked from user store end.
+ * @param accountLockServiceException Exception when checking the account lock status.
+ * @param isValidateAuthenticatedUserForRefreshGrant Whether the `ValidateAuthenticatedUserForRefreshGrant`
+ * config is enabled in identity.xml.
+ * @throws Exception Any uncaught exception thrown while running the test case.
+ */
+ @Test(dataProvider = "validateGrantWhenUserIsLockedInUserStoreEnd")
+ public void testValidateGrantWhenUserIsLockedInUserStoreEnd(AuthenticatedUser user,
+ AuthenticatedUser associatedUser,
+ Throwable federatedAssociationManagerException,
+ boolean isUserLocked,
+ Throwable accountLockServiceException,
+ boolean isValidateAuthenticatedUserForRefreshGrant)
throws Exception {
- OAuthAppDAO oAuthAppDAO = new OAuthAppDAO();
- oAuthAppDAO.removeConsumerApplication(clientId);
-
- OAuthAppDO oAuthAppDO = new OAuthAppDO();
- oAuthAppDO.setGrantTypes("implicit");
- oAuthAppDO.setOauthConsumerKey(clientId);
- oAuthAppDO.setUser(authenticatedUser);
- oAuthAppDO.setOauthVersion(OAuthConstants.OAuthVersions.VERSION_2);
-
- oAuthAppDAO.addOAuthApplication(oAuthAppDO);
-
- refreshGrantHandler = new RefreshGrantHandler();
- refreshGrantHandler.init();
-
- OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
- tokenReqDTO.setClientId(clientId);
- tokenReqDTO.setRefreshToken("refreshToken1");
- OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
-
- boolean isValid = refreshGrantHandler.validateGrant(tokenReqMessageContext);
- assertTrue(isValid, "Refresh token validation should be successful.");
- }
-
- @DataProvider(name = "validateGrantExceptionData")
- public Object[][] validateGrantExceptionData() {
-
- List accessTokenDOS = new ArrayList<>();
- AccessTokenDO accessTokenDO1 = new AccessTokenDO();
- accessTokenDO1.setTokenState(TOKEN_STATE_ACTIVE);
- accessTokenDO1.setRefreshToken("refreshToken1");
-
- AccessTokenDO accessTokenDO2 = new AccessTokenDO();
- accessTokenDO2.setTokenState(TOKEN_STATE_EXPIRED);
- accessTokenDO2.setRefreshToken("refreshToken2");
-
- accessTokenDOS.add(accessTokenDO1);
- accessTokenDOS.add(accessTokenDO2);
-
- return new Object[][] { { "clientId1", "refreshToken1", "accessToken1", TOKEN_STATE_INACTIVE, accessTokenDOS },
- { "clientId1", "refreshToken3", "accessToken1", TOKEN_STATE_EXPIRED, accessTokenDOS },
- { "clientId1", "refreshToken3", "accessToken1", TOKEN_STATE_EXPIRED, null },
- { "clientId1", "refreshToken1", null, null, accessTokenDOS }, };
- }
-
- @Test(dataProvider = "validateGrantExceptionData", expectedExceptions = IdentityOAuth2Exception.class)
- public void testValidateGrantForException(String clientId, String refreshToken, String accessToken,
- String tokenState, Object accessTokenObj) throws Exception {
-
- refreshGrantHandler = new RefreshGrantHandler();
- refreshGrantHandler.init();
-
- OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
- tokenReqDTO.setClientId(clientId);
- tokenReqDTO.setRefreshToken(refreshToken);
- OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
-
- refreshGrantHandler.validateGrant(tokenReqMessageContext);
- Assert.fail("Authenticated user cannot be null.");
- }
-
- @Test(dataProvider = "GetTokenIssuerData")
- public void testIssue(Long userAccessTokenExpiryTime, Long validityPeriod, String renewRefreshToken,
- String clientId) throws Exception {
-
- OAuthAppDAO oAuthAppDAO = new OAuthAppDAO();
- oAuthAppDAO.removeConsumerApplication(clientId);
- OAuthAppDO oAuthAppDO = new OAuthAppDO();
- oAuthAppDO.setUserAccessTokenExpiryTime(userAccessTokenExpiryTime);
- oAuthAppDO.setRefreshTokenExpiryTime(userAccessTokenExpiryTime);
- oAuthAppDO.setUser(authenticatedUser);
- oAuthAppDO.setOauthConsumerKey(clientId);
- oAuthAppDO.setOauthVersion(OAuthConstants.OAuthVersions.VERSION_2);
- oAuthAppDO.setRenewRefreshTokenEnabled(renewRefreshToken);
- oAuthAppDAO.addOAuthApplication(oAuthAppDO);
-
- refreshGrantHandler = new RefreshGrantHandler();
- refreshGrantHandler.init();
-
- OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
- tokenReqDTO.setClientId(clientId);
- tokenReqDTO.setRefreshToken("refreshToken1");
- tokenReqDTO.setScope(scopes);
-
- RefreshTokenValidationDataDO oldAccessToken = new RefreshTokenValidationDataDO();
- oldAccessToken.setTokenId("tokenId");
- oldAccessToken.setAccessToken("oldAccessToken");
-
- OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
- tokenReqMessageContext.addProperty("previousAccessToken", oldAccessToken);
- tokenReqMessageContext.setAuthorizedUser(authenticatedUser);
- tokenReqMessageContext.setValidityPeriod(validityPeriod);
- tokenReqMessageContext.setScope(scopes);
+ when(refreshTokenGrantProcessor.validateRefreshToken(any())).thenReturn(refreshTokenValidationDataDO);
+ when(refreshTokenValidationDataDO.getAuthorizedUser()).thenReturn(user);
+ when(refreshTokenGrantProcessor.isLatestRefreshToken(any(), any(), any())).thenReturn(true);
+ when(oAuthServerConfiguration.isValidateAuthenticatedUserForRefreshGrantEnabled()).thenReturn(
+ isValidateAuthenticatedUserForRefreshGrant);
+ when(oAuth2ServiceComponentHolder.getRefreshTokenGrantProcessor()).thenReturn(refreshTokenGrantProcessor);
+ when(oAuthTokenReqMessageContext.getOauth2AccessTokenReqDTO()).thenReturn(oAuth2AccessTokenReqDTO);
+
+ FederatedAssociationManager federatedAssociationManager = mock(FederatedAssociationManager.class);
+ if (federatedAssociationManagerException instanceof FederatedAssociationManagerException) {
+ when(federatedAssociationManager.getUserForFederatedAssociation(anyString(),
+ eq(user.getFederatedIdPName()), eq(user.getAuthenticatedSubjectIdentifier()))).thenThrow(
+ federatedAssociationManagerException);
+ } else if (associatedUser != null) {
+ when(federatedAssociationManager.getUserForFederatedAssociation(anyString(),
+ eq(user.getFederatedIdPName()), eq(user.getAuthenticatedSubjectIdentifier()))).thenReturn(
+ associatedUser.getUserName());
+ }
- OAuth2AccessTokenRespDTO actual = refreshGrantHandler.issue(tokenReqMessageContext);
- assertFalse(actual.isError());
- assertNotNull(actual.getRefreshToken());
- if (Objects.equals(renewRefreshToken, "true") || (renewRefreshToken == null)) {
- assertNotEquals("refreshToken1", actual.getRefreshToken());
+ AccountLockService accountLockService = mock(AccountLockService.class);
+ if (accountLockServiceException != null) {
+ when(accountLockService.isAccountLocked(anyString(), anyString())).thenThrow(
+ accountLockServiceException);
} else {
- assertEquals("refreshToken1", actual.getRefreshToken());
+ when(accountLockService.isAccountLocked(anyString(), anyString())).thenReturn(isUserLocked);
}
- }
-
- @Test(dataProvider = "GetValidateScopeData")
- public void validateScope(String[] requestedScopes, String[] grantedScopes, boolean expected, String message)
- throws Exception {
-
- OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
- tokenReqDTO.setScope(requestedScopes);
- tokenReqDTO.setClientId("clientId1");
- tokenReqDTO.setRefreshToken("refreshToken1");
- tokenReqDTO.setGrantType("refreshTokenGrant");
- OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
- tokenReqMessageContext.setScope(grantedScopes);
- refreshGrantHandler = new RefreshGrantHandler();
- refreshGrantHandler.init();
- boolean actual = refreshGrantHandler.validateScope(tokenReqMessageContext);
- assertEquals(actual, expected, message);
- }
-
- @DataProvider(name = "GetTokenIssuerData")
- public Object[][] tokenIssuerData() {
-
- return new Object[][] {
- { 0L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId1" },
- { 20L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId2" },
- { 20L, 20L, "true", "clientId3" },
- { 0L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId4" },
- { 20L, 20L, "false", "clientId5" },
- { 20L, 20L, null, "clientId6" },
- { 20L, 20L, "true", "clientId7" } };
- }
-
- @DataProvider(name = "GetValidateScopeData")
- public Object[][] validateScopeData() {
-
- String[] requestedScopes = new String[2];
- requestedScopes[0] = "scope1";
- requestedScopes[1] = "scope2";
-
- String[] grantedScopes = new String[1];
- grantedScopes[0] = "scope1";
-
- String[] grantedScopesWithRequestedScope = new String[1];
- grantedScopesWithRequestedScope[0] = "scope1";
- grantedScopesWithRequestedScope[0] = "scope2";
-
- return new Object[][] { { requestedScopes, grantedScopes, false, "scope validation should fail." },
- { requestedScopes, grantedScopesWithRequestedScope, false, "scope validation should fail." },
- { requestedScopes, new String[0], false, "scope validation should fail." },
- { new String[] { "scope_not_granted" }, grantedScopes, false, "scope validation should fail." }, };
+ refreshTokenValidationDataDO.setRefreshTokenState(OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE);
+ try {
+ try (MockedStatic oAuthServerConfigurationMockedStatic = mockStatic(
+ OAuthServerConfiguration.class);
+ MockedStatic oAuth2ServiceComponentHolderMockedStatic = mockStatic(
+ OAuth2ServiceComponentHolder.class);
+ MockedStatic frameworkUtilsMockedStatic = mockStatic(FrameworkUtils.class)) {
+ oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance)
+ .thenReturn(oAuthServerConfiguration);
+ oAuth2ServiceComponentHolderMockedStatic.when(OAuth2ServiceComponentHolder::getInstance)
+ .thenReturn(oAuth2ServiceComponentHolder);
+ oAuth2ServiceComponentHolderMockedStatic.when(OAuth2ServiceComponentHolder::getAccountLockService)
+ .thenReturn(accountLockService);
+ if (federatedAssociationManagerException instanceof FrameworkException) {
+ frameworkUtilsMockedStatic.when(FrameworkUtils::getFederatedAssociationManager)
+ .thenThrow(federatedAssociationManagerException);
+ } else {
+ frameworkUtilsMockedStatic.when(FrameworkUtils::getFederatedAssociationManager)
+ .thenReturn(federatedAssociationManager);
+ }
+
+ RefreshGrantHandler refreshGrantHandler = new RefreshGrantHandler();
+ boolean validateResult = refreshGrantHandler.validateGrant(oAuthTokenReqMessageContext);
+ assertTrue(validateResult);
+ }
+ } catch (IdentityOAuth2Exception e) {
+ if (federatedAssociationManagerException != null) {
+ assertEquals(ERROR_WHILE_GETTING_USERNAME_ASSOCIATED_WITH_IDP.getCode(), e.getErrorCode());
+ } else if (accountLockServiceException != null) {
+ assertEquals(ERROR_WHILE_CHECKING_ACCOUNT_LOCK_STATUS.getCode(), e.getErrorCode());
+ } else if (isUserLocked) {
+ assertEquals(UserCoreConstants.ErrorCode.USER_IS_LOCKED, e.getErrorCode());
+ } else {
+ fail("Unexpected exception is thrown.");
+ }
+ }
}
}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTestOld.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTestOld.java
new file mode 100644
index 00000000000..5901248aa87
--- /dev/null
+++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/RefreshGrantHandlerTestOld.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2017, 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.token.handlers.grant;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
+import org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl;
+import org.wso2.carbon.identity.application.mgt.internal.ApplicationManagementServiceComponent;
+import org.wso2.carbon.identity.application.mgt.internal.ApplicationManagementServiceComponentHolder;
+import org.wso2.carbon.identity.common.testng.WithCarbonHome;
+import org.wso2.carbon.identity.common.testng.WithH2Database;
+import org.wso2.carbon.identity.common.testng.WithRealmService;
+import org.wso2.carbon.identity.oauth.common.OAuthConstants;
+import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO;
+import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
+import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+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.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.test.common.testng.utils.MockAuthenticatedUser;
+import org.wso2.carbon.identity.testutil.Whitebox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE;
+import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED;
+import static org.wso2.carbon.identity.oauth.common.OAuthConstants.TokenStates.TOKEN_STATE_INACTIVE;
+import static org.wso2.carbon.identity.oauth.common.OAuthConstants.UNASSIGNED_VALIDITY_PERIOD;
+
+/**
+ * Test class for RefreshGrantHandler test cases.
+ */
+@WithCarbonHome
+@WithRealmService(injectToSingletons = { OAuthComponentServiceHolder.class,
+ ApplicationManagementServiceComponentHolder.class })
+@WithH2Database(files = { "dbScripts/identity.sql", "dbScripts/insert_consumer_app.sql" })
+public class RefreshGrantHandlerTestOld {
+
+ private static final String TEST_USER_ID = "testUser";
+ private static final String TEST_USER_DOMAIN = "testDomain";
+ private RefreshGrantHandler refreshGrantHandler;
+ private AuthenticatedUser authenticatedUser;
+ private String[] scopes;
+
+ @BeforeClass
+ protected void setUp() throws Exception {
+ OAuth2ServiceComponentHolder.setApplicationMgtService(ApplicationManagementServiceImpl.getInstance());
+ authenticatedUser = new MockAuthenticatedUser(TEST_USER_ID);
+ authenticatedUser.setUserStoreDomain(TEST_USER_DOMAIN);
+ scopes = new String[] { "scope1", "scope2" };
+ }
+
+ @BeforeMethod
+ protected void setUpMethod() throws Exception {
+
+ ApplicationManagementServiceComponent applicationManagementServiceComponent =
+ new ApplicationManagementServiceComponent();
+ Whitebox.invokeMethod(applicationManagementServiceComponent, "buildFileBasedSPList", null);
+ }
+
+ @DataProvider(name = "GetValidateGrantData")
+ public Object[][] validateGrantData() {
+
+ return new Object[][] {
+ { "clientId1" },
+ { "clientId2" },
+ { "clientId2" }
+ };
+ }
+
+ @Test(dataProvider = "GetValidateGrantData")
+ public void testValidateGrant(String clientId)
+ throws Exception {
+
+ OAuthAppDAO oAuthAppDAO = new OAuthAppDAO();
+ oAuthAppDAO.removeConsumerApplication(clientId);
+
+ OAuthAppDO oAuthAppDO = new OAuthAppDO();
+ oAuthAppDO.setGrantTypes("implicit");
+ oAuthAppDO.setOauthConsumerKey(clientId);
+ oAuthAppDO.setUser(authenticatedUser);
+ oAuthAppDO.setOauthVersion(OAuthConstants.OAuthVersions.VERSION_2);
+
+ oAuthAppDAO.addOAuthApplication(oAuthAppDO);
+
+ refreshGrantHandler = new RefreshGrantHandler();
+ refreshGrantHandler.init();
+
+ OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
+ tokenReqDTO.setClientId(clientId);
+ tokenReqDTO.setRefreshToken("refreshToken1");
+ OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
+
+ boolean isValid = refreshGrantHandler.validateGrant(tokenReqMessageContext);
+ assertTrue(isValid, "Refresh token validation should be successful.");
+ }
+
+ @DataProvider(name = "validateGrantExceptionData")
+ public Object[][] validateGrantExceptionData() {
+
+ List accessTokenDOS = new ArrayList<>();
+ AccessTokenDO accessTokenDO1 = new AccessTokenDO();
+ accessTokenDO1.setTokenState(TOKEN_STATE_ACTIVE);
+ accessTokenDO1.setRefreshToken("refreshToken1");
+
+ AccessTokenDO accessTokenDO2 = new AccessTokenDO();
+ accessTokenDO2.setTokenState(TOKEN_STATE_EXPIRED);
+ accessTokenDO2.setRefreshToken("refreshToken2");
+
+ accessTokenDOS.add(accessTokenDO1);
+ accessTokenDOS.add(accessTokenDO2);
+
+ return new Object[][] { { "clientId1", "refreshToken1", "accessToken1", TOKEN_STATE_INACTIVE, accessTokenDOS },
+ { "clientId1", "refreshToken3", "accessToken1", TOKEN_STATE_EXPIRED, accessTokenDOS },
+ { "clientId1", "refreshToken3", "accessToken1", TOKEN_STATE_EXPIRED, null },
+ { "clientId1", "refreshToken1", null, null, accessTokenDOS }, };
+ }
+
+ @Test(dataProvider = "validateGrantExceptionData", expectedExceptions = IdentityOAuth2Exception.class)
+ public void testValidateGrantForException(String clientId, String refreshToken, String accessToken,
+ String tokenState, Object accessTokenObj) throws Exception {
+
+ refreshGrantHandler = new RefreshGrantHandler();
+ refreshGrantHandler.init();
+
+ OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
+ tokenReqDTO.setClientId(clientId);
+ tokenReqDTO.setRefreshToken(refreshToken);
+ OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
+
+ refreshGrantHandler.validateGrant(tokenReqMessageContext);
+ Assert.fail("Authenticated user cannot be null.");
+ }
+
+ @Test(dataProvider = "GetTokenIssuerData")
+ public void testIssue(Long userAccessTokenExpiryTime, Long validityPeriod, String renewRefreshToken,
+ String clientId) throws Exception {
+
+ OAuthAppDAO oAuthAppDAO = new OAuthAppDAO();
+ oAuthAppDAO.removeConsumerApplication(clientId);
+ OAuthAppDO oAuthAppDO = new OAuthAppDO();
+ oAuthAppDO.setUserAccessTokenExpiryTime(userAccessTokenExpiryTime);
+ oAuthAppDO.setRefreshTokenExpiryTime(userAccessTokenExpiryTime);
+ oAuthAppDO.setUser(authenticatedUser);
+ oAuthAppDO.setOauthConsumerKey(clientId);
+ oAuthAppDO.setOauthVersion(OAuthConstants.OAuthVersions.VERSION_2);
+ oAuthAppDO.setRenewRefreshTokenEnabled(renewRefreshToken);
+ oAuthAppDAO.addOAuthApplication(oAuthAppDO);
+
+ refreshGrantHandler = new RefreshGrantHandler();
+ refreshGrantHandler.init();
+
+ OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
+ tokenReqDTO.setClientId(clientId);
+ tokenReqDTO.setRefreshToken("refreshToken1");
+ tokenReqDTO.setScope(scopes);
+
+ RefreshTokenValidationDataDO oldAccessToken = new RefreshTokenValidationDataDO();
+ oldAccessToken.setTokenId("tokenId");
+ oldAccessToken.setAccessToken("oldAccessToken");
+
+ OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
+ tokenReqMessageContext.addProperty("previousAccessToken", oldAccessToken);
+ tokenReqMessageContext.setAuthorizedUser(authenticatedUser);
+ tokenReqMessageContext.setValidityPeriod(validityPeriod);
+ tokenReqMessageContext.setScope(scopes);
+
+ OAuth2AccessTokenRespDTO actual = refreshGrantHandler.issue(tokenReqMessageContext);
+ assertFalse(actual.isError());
+ assertNotNull(actual.getRefreshToken());
+ if (Objects.equals(renewRefreshToken, "true") || (renewRefreshToken == null)) {
+ assertNotEquals("refreshToken1", actual.getRefreshToken());
+ } else {
+ assertEquals("refreshToken1", actual.getRefreshToken());
+ }
+ }
+
+ @Test(dataProvider = "GetValidateScopeData")
+ public void validateScope(String[] requestedScopes, String[] grantedScopes, boolean expected, String message)
+ throws Exception {
+
+ OAuth2AccessTokenReqDTO tokenReqDTO = new OAuth2AccessTokenReqDTO();
+ tokenReqDTO.setScope(requestedScopes);
+ tokenReqDTO.setClientId("clientId1");
+ tokenReqDTO.setRefreshToken("refreshToken1");
+ tokenReqDTO.setGrantType("refreshTokenGrant");
+ OAuthTokenReqMessageContext tokenReqMessageContext = new OAuthTokenReqMessageContext(tokenReqDTO);
+ tokenReqMessageContext.setScope(grantedScopes);
+
+ refreshGrantHandler = new RefreshGrantHandler();
+ refreshGrantHandler.init();
+ boolean actual = refreshGrantHandler.validateScope(tokenReqMessageContext);
+ assertEquals(actual, expected, message);
+ }
+
+ @DataProvider(name = "GetTokenIssuerData")
+ public Object[][] tokenIssuerData() {
+
+ return new Object[][] {
+ { 0L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId1" },
+ { 20L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId2" },
+ { 20L, 20L, "true", "clientId3" },
+ { 0L, UNASSIGNED_VALIDITY_PERIOD, "true", "clientId4" },
+ { 20L, 20L, "false", "clientId5" },
+ { 20L, 20L, null, "clientId6" },
+ { 20L, 20L, "true", "clientId7" } };
+ }
+
+ @DataProvider(name = "GetValidateScopeData")
+ public Object[][] validateScopeData() {
+
+ String[] requestedScopes = new String[2];
+ requestedScopes[0] = "scope1";
+ requestedScopes[1] = "scope2";
+
+ String[] grantedScopes = new String[1];
+ grantedScopes[0] = "scope1";
+
+ String[] grantedScopesWithRequestedScope = new String[1];
+ grantedScopesWithRequestedScope[0] = "scope1";
+ grantedScopesWithRequestedScope[0] = "scope2";
+
+ return new Object[][] { { requestedScopes, grantedScopes, false, "scope validation should fail." },
+ { requestedScopes, grantedScopesWithRequestedScope, false, "scope validation should fail." },
+ { requestedScopes, new String[0], false, "scope validation should fail." },
+ { new String[] { "scope_not_granted" }, grantedScopes, false, "scope validation should fail." }, };
+ }
+}
diff --git a/components/org.wso2.carbon.identity.oauth/src/test/resources/repository/conf/identity/identity.xml b/components/org.wso2.carbon.identity.oauth/src/test/resources/repository/conf/identity/identity.xml
index 8a4742cbbff..113ba6b289d 100644
--- a/components/org.wso2.carbon.identity.oauth/src/test/resources/repository/conf/identity/identity.xml
+++ b/components/org.wso2.carbon.identity.oauth/src/test/resources/repository/conf/identity/identity.xml
@@ -165,6 +165,8 @@
false
true
+
+ true
org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor
From c3ee286957a1c848a384e90db206428537ca0f08 Mon Sep 17 00:00:00 2001
From: DilshanSenarath <74205483+DilshanSenarath@users.noreply.github.com>
Date: Mon, 14 Oct 2024 01:43:32 +0530
Subject: [PATCH 3/6] add refresh grant handler test class to the testng.xml
---
.../src/test/resources/testng.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
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 ca82671d83c..a4849dc6749 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
@@ -110,7 +110,7 @@
-
+
@@ -182,7 +182,7 @@
-
+
From a16225f5c38ea86df03add26c388554c6bfd9031 Mon Sep 17 00:00:00 2001
From: DilshanSenarath <74205483+DilshanSenarath@users.noreply.github.com>
Date: Mon, 14 Oct 2024 01:59:50 +0530
Subject: [PATCH 4/6] fix the exclude pattern issue
---
components/org.wso2.carbon.identity.oauth/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 0c6974cdef7..4fb85fc4419 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -554,8 +554,8 @@
- org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponent
- org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder
+ org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.class
+ org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponentHolder.class
From 6e5f72362aec0df8e2f727f80941b7a25c47b17f Mon Sep 17 00:00:00 2001
From: DilshanSenarath <74205483+DilshanSenarath@users.noreply.github.com>
Date: Wed, 16 Oct 2024 15:37:36 +0530
Subject: [PATCH 5/6] update license headers
---
components/org.wso2.carbon.identity.oauth/pom.xml | 2 +-
.../identity/oauth/config/OAuthServerConfigurationTest.java | 2 +-
.../oauth2/token/handlers/grant/RefreshGrantHandlerTestOld.java | 2 +-
.../src/test/resources/repository/conf/identity/identity.xml | 2 +-
.../src/test/resources/testng.xml | 2 +-
pom.xml | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml
index 0f2e9fb6854..3a3f49a5df7 100644
--- a/components/org.wso2.carbon.identity.oauth/pom.xml
+++ b/components/org.wso2.carbon.identity.oauth/pom.xml
@@ -1,6 +1,6 @@