diff --git a/components/org.wso2.carbon.identity.oauth/pom.xml b/components/org.wso2.carbon.identity.oauth/pom.xml index e8e1a2cf88a..55f2a1216da 100644 --- a/components/org.wso2.carbon.identity.oauth/pom.xml +++ b/components/org.wso2.carbon.identity.oauth/pom.xml @@ -605,7 +605,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - **/IdentityOathEventListenerTest.java,**/AccessTokenIssuerTest.java, + **/IdentityOathEventListenerTest.java,**/DeprecatedAccessTokenIssuerTest.java, **/OAuthUserStoreConfigListenerImplTest.java,**/NTLMAuthenticationGrantHandlerWithHandshakeTest.java, **/AuthorizationCodeGrantHandlerTest.java,**/OAuthTenantMgtListenerImplTest.java 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 3f5d4bfb266..8ce1ede27e3 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 @@ -90,6 +90,7 @@ import org.wso2.carbon.identity.oauth2.validators.JDBCPermissionBasedInternalScopeValidator; import org.wso2.carbon.identity.oauth2.validators.RoleBasedInternalScopeValidator; import org.wso2.carbon.identity.openidconnect.IDTokenBuilder; +import org.wso2.carbon.identity.openidconnect.OIDCConstants; import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.common.AbstractUserStoreManager; @@ -128,6 +129,7 @@ import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.EXTENDED_REFRESH_TOKEN_DEFAULT_TIME; import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.INTERNAL_LOGIN_SCOPE; import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.validateRequestTenantDomain; +import static org.wso2.carbon.identity.openidconnect.OIDCConstants.EXISTING_TOKEN_USED; import static org.wso2.carbon.identity.openidconnect.OIDCConstants.ID_TOKEN_USER_CLAIMS_PROP_KEY; /** @@ -141,6 +143,7 @@ public class AccessTokenIssuer { public static final String OAUTH_APP_DO = "OAuthAppDO"; private static final String SERVICE_PROVIDERS_SUB_CLAIM = "ServiceProviders.UseUsernameAsSubClaim"; private final AuthorizationDetailsValidator authorizationDetailsValidator; + private static final String ENABLE_POST_TOKEN_ISSUE_EVENT = "PostTokenIssueEvent.Enable"; /** * Private constructor which will not allow to create objects of this class from outside @@ -417,7 +420,7 @@ private AuthorizationGrantCacheEntry getAuthzGrantCacheEntryFromDeviceCode(OAuth } private void persistImpersonationInfoToTokenReqCtx(AuthorizationGrantCacheEntry authorizationGrantCacheEntry, - OAuthTokenReqMessageContext tokReqMsgCtx) { + OAuthTokenReqMessageContext tokReqMsgCtx) { boolean isUserSessionImpersonationEnabled = OAuthServerConfiguration.getInstance() .isUserSessionImpersonationEnabled(); @@ -1364,6 +1367,11 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO, OAuthEventInterceptor oAuthEventInterceptorProxy = OAuthComponentServiceHolder.getInstance() .getOAuthEventInterceptorProxy(); + try { + triggerPostIssueTokenEvent(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); + } catch (IdentityOAuth2Exception | OrganizationManagementException e) { + log.error("Error while triggering post issue token event.", e); + } if (isRefresh) { if (oAuthEventInterceptorProxy != null && oAuthEventInterceptorProxy.isEnabled()) { @@ -1394,6 +1402,65 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO, } } + private static void triggerPostIssueTokenEvent(OAuth2AccessTokenReqDTO tokenReqDTO, + OAuth2AccessTokenRespDTO tokenRespDTO, + OAuthTokenReqMessageContext tokReqMsgCtx) + throws IdentityOAuth2Exception, OrganizationManagementException { + + if (!Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_POST_TOKEN_ISSUE_EVENT))) { + if (log.isDebugEnabled()) { + log.debug("Token event publishing is disabled. Hence skipping the post issue token event."); + } + return; + } + if (tokenReqDTO == null || tokenRespDTO == null || tokReqMsgCtx == null) { + if (log.isDebugEnabled()) { + log.debug("Token request DTO, token response DTO or token request message context is null. " + + "Skipping the post issue token event."); + } + return; + } + if (tokenRespDTO.isError()) { + if (log.isDebugEnabled()) { + log.debug("Token response DTO is in error state. Hence skipping the post issue token event."); + } + return; + } + + String tenantDomain = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getTenantDomain(); + String organizationId = OAuthComponentServiceHolder.getInstance().getOrganizationManager() + .resolveOrganizationId(tenantDomain); + String accessingOrganizationId = StringUtils.EMPTY; + if (tokReqMsgCtx.getAuthorizedUser() != null + && tokReqMsgCtx.getAuthorizedUser().getAccessingOrganization() != null) { + accessingOrganizationId = tokReqMsgCtx.getAuthorizedUser().getAccessingOrganization(); + } + + Map eventProperties = new HashMap<>(); + eventProperties.put(OIDCConstants.Event.TOKEN_ID, tokenRespDTO.getTokenId()); + eventProperties.put(OIDCConstants.Event.TENANT_DOMAIN, tenantDomain); + eventProperties.put(OIDCConstants.Event.USER_TYPE, tokReqMsgCtx.getProperty(OAuthConstants.UserType.USER_TYPE)); + eventProperties.put(OIDCConstants.Event.CLIENT_ID, tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId()); + eventProperties.put(OIDCConstants.Event.GRANT_TYPE, tokenReqDTO.getGrantType()); + eventProperties.put(OIDCConstants.Event.ISSUED_TIME, String.valueOf(tokReqMsgCtx.getAccessTokenIssuedTime())); + eventProperties.put(OIDCConstants.Event.ISSUER_ORGANIZATION_ID, organizationId); + eventProperties.put(OIDCConstants.Event.ACCESSING_ORGANIZATION_ID, accessingOrganizationId); + eventProperties.put(OIDCConstants.Event.APP_RESIDENT_TENANT_ID, IdentityTenantUtil.getLoginTenantId()); + eventProperties.put(OIDCConstants.Event.EXISTING_TOKEN_USED, String.valueOf(existingTokenUsed(tokReqMsgCtx))); + eventProperties.put(OIDCConstants.Event.SERVICE_PROVIDER, OAuth2Util.getServiceProvider( + tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId(), tenantDomain).getApplicationName()); + OAuth2TokenUtil.postIssueToken(eventProperties); + } + + private static Boolean existingTokenUsed(OAuthTokenReqMessageContext tokReqMsgCtx) { + + Boolean existingTokenUsed = (Boolean) tokReqMsgCtx.getProperty(EXISTING_TOKEN_USED); + if (existingTokenUsed == null) { + existingTokenUsed = false; + } + return existingTokenUsed; + } + /** * Copies the cache entry against the authorization code/device code and adds an entry against the access token. * This is done to reuse the calculated user claims for subsequent usages such as user info calls. @@ -1474,8 +1541,8 @@ private void persistCustomizedAccessTokenAttributesForRefreshToken(OAuth2AccessT AuthorizationGrantCache.getInstance().addToCacheByToken(newCacheKey, authorizationGrantCacheEntry); log.debug("Customized audience list and access token attributes from pre issue access token actions " + - "are persisted in the AuthorizationGrantCache against the token id: " + - tokenRespDTO.getTokenId()); + "are persisted in the AuthorizationGrantCache against the token id: " + + tokenRespDTO.getTokenId()); } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtil.java index c9a2d1c0742..a3de16caece 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtil.java @@ -39,6 +39,7 @@ import java.text.ParseException; import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.wso2.carbon.identity.openidconnect.OIDCConstants.Event.IS_REQUEST_OBJECT_FLOW; import static org.wso2.carbon.identity.openidconnect.OIDCConstants.Event.NEW_ACCESS_TOKEN; @@ -82,6 +83,31 @@ public static void postIssueAccessToken(String tokenId, String sessionDataKey) t } } + /** + * Uses to publish token issuance details. + * + * @param eventProperties Map containing token issuance details. + * @throws IdentityOAuth2Exception when an error occurs while publishing the event. + */ + public static void postIssueToken(Map eventProperties) throws IdentityOAuth2Exception { + + String eventName = OIDCConstants.Event.POST_ISSUE_ACCESS_TOKEN_V2; + Event postIssueTokenEvent = new Event(eventName, eventProperties); + IdentityEventService identityEventService = OpenIDConnectServiceComponentHolder.getIdentityEventService(); + try { + if (identityEventService != null) { + identityEventService.handleEvent(postIssueTokenEvent); + if (log.isDebugEnabled()) { + log.debug("The event " + eventName + " triggered after the token " + + eventProperties.get(OIDCConstants.Event.TOKEN_ID) + " is issued."); + } + } + } catch (IdentityEventException e) { + throw new IdentityOAuth2Exception("Error while invoking the request object persistence handler when " + + "issuing the access token id: " + eventProperties.get(OIDCConstants.Event.TOKEN_ID)); + } + } + /** * Uses to revoke access tokens from the request object related tables after token revocation * happens from access token related tables. diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/OIDCConstants.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/OIDCConstants.java index dc5ce098854..14a59ac4509 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/OIDCConstants.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/OIDCConstants.java @@ -28,6 +28,7 @@ public class OIDCConstants { public static final String IDN_OIDC_REQ_OBJECT_CLAIMS = "STORE_IDN_OIDC_REQ_OBJECT_CLAIMS"; public static final String HAS_NON_OIDC_CLAIMS = "hasNonOIDCClaims"; public static final String ID_TOKEN_USER_CLAIMS_PROP_KEY = "IDTokenUserClaims"; + public static final String EXISTING_TOKEN_USED = "existingTokenUsed"; /** * This class is used to define constants related to OIDC event specific features. @@ -39,6 +40,7 @@ public class Event { public static final String SESSION_DATA_KEY = "SESSION_DATA_KEY"; public static final String POST_ISSUE_CODE = "POST_ISSUE_CODE"; public static final String POST_ISSUE_ACCESS_TOKEN = "POST_ISSUE_ACCESS_TOKEN"; + public static final String POST_ISSUE_ACCESS_TOKEN_V2 = "POST_ISSUE_ACCESS_TOKEN_V2"; public static final String HANDLE_REQUEST_OBJECT = "handleRequestObject"; public static final String POST_REVOKE_ACESS_TOKEN = "POST_REVOKE_ACESS_TOKEN"; public static final String POST_REVOKE_ACESS_TOKEN_BY_ID = "POST_REVOKE_ACESS_TOKEN_BY_ID"; @@ -47,10 +49,19 @@ public class Event { public static final String ACEESS_TOKENS = "ACEESS_TOKENS"; public static final String CODES = "CODES"; public static final String TOKEN_STATE = "TOKEN_STATE"; + public static final String GRANT_TYPE = "GRANT_TYPE"; + public static final String CLIENT_ID = "CLIENT_ID"; + public static final String TENANT_DOMAIN = "TENANT_DOMAIN"; + public static final String USER_TYPE = "USER_TYPE"; public static final String NEW_ACCESS_TOKEN = "NEW_ACCESS_TOKEN"; public static final String OLD_ACCESS_TOKEN = "OLD_ACCESS_TOKEN"; public static final String POST_REFRESH_TOKEN = "POST_REFRESH_TOKEN"; public static final String IS_REQUEST_OBJECT_FLOW = "IS_REQUEST_OBJECT_FLOW"; + public static final String APP_RESIDENT_TENANT_ID = "APP_RESIDENT_TENANT_ID"; + public static final String ISSUED_TIME = "ISSUED_TIME"; + public static final String ISSUER_ORGANIZATION_ID = "ISSUER_ORGANIZATION_ID"; + public static final String ACCESSING_ORGANIZATION_ID = "ACCESSING_ORGANIZATION_ID"; + public static final String EXISTING_TOKEN_USED = "EXISTING_TOKEN_USED"; + public static final String SERVICE_PROVIDER = "SERVICE_PROVIDER"; } } - diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuerTest.java index 4214fbfe3b6..db9ca35f749 100644 --- a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuerTest.java +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuerTest.java @@ -1,770 +1,300 @@ /* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). * - * 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 + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. + * 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; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.oltu.oauth2.common.error.OAuthError; -import org.apache.oltu.oauth2.common.message.types.GrantType; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.mockito.MockedStatic; +import org.mockito.testng.MockitoTestNGListener; import org.testng.Assert; +import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; +import org.testng.annotations.Listeners; import org.testng.annotations.Test; +import org.wso2.carbon.base.CarbonBaseConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.LocalAndOutboundAuthenticationConfig; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.base.IdentityException; +import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.core.util.IdentityConfigParser; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.cache.AppInfoCache; -import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; +import org.wso2.carbon.identity.oauth.cache.OAuthCache; import org.wso2.carbon.identity.oauth.common.OAuthConstants; -import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth2.IDTokenValidationFailureException; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.ResponseHeader; +import org.wso2.carbon.identity.oauth.event.OAuthEventInterceptor; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; +import org.wso2.carbon.identity.oauth.rar.core.AuthorizationDetailsSchemaValidator; import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext; import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO; -import org.wso2.carbon.identity.oauth2.test.utils.CommonTestUtils; +import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; +import org.wso2.carbon.identity.oauth2.rar.AuthorizationDetailsService; +import org.wso2.carbon.identity.oauth2.rar.core.AuthorizationDetailsProcessorFactory; import org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationGrantHandler; -import org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler; +import org.wso2.carbon.identity.oauth2.util.AuthzUtil; +import org.wso2.carbon.identity.oauth2.util.OAuth2TokenUtil; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; -import org.wso2.carbon.identity.oauth2.validators.JDBCPermissionBasedInternalScopeValidator; -import org.wso2.carbon.identity.openidconnect.IDTokenBuilder; -import org.wso2.carbon.utils.CarbonUtils; -import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import org.wso2.carbon.identity.openidconnect.OIDCConstants; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.user.core.UserRealm; +import org.wso2.carbon.user.core.UserStoreException; +import org.wso2.carbon.user.core.common.AbstractUserStoreManager; import java.lang.reflect.Field; -import java.util.Arrays; +import java.nio.file.Paths; import java.util.HashMap; -import java.util.Hashtable; import java.util.Map; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OauthAppStates.APP_STATE_ACTIVE; /** - * Unit test cases for {@link AccessTokenIssuer} + * Unit test for {@link AccessTokenIssuer}. */ - +@Listeners(MockitoTestNGListener.class) +@WithCarbonHome public class AccessTokenIssuerTest { - public static final String SOME_CLIENT_ID = "some-client-id"; + private static final String ENABLE_POST_TOKEN_ISSUE_EVENT = "PostTokenIssueEvent.Enable"; + private final int testAppResidentTenantId = 1; + private final String testAccessingOrganizationId = "dExLASaD1Flb_fx7ZecfAA3n1HRka"; + private final String testTenantDomain = "carbon.super"; + private final String testClientId = "dExLASaD1Flb_fx7ZecfAA3n1HRka"; + private final String testOrganizationId = "exLASaD1Flb_fx7ZecfAA3n1HRkaf"; + private final String testTokenId = "dExLASaD1Flb_fx7ZecfAA3n1HRka12345"; + private final String testApplicationName = "TestApplication"; + private AutoCloseable mocks; @Mock - private OAuthServerConfiguration oAuthServerConfiguration; - + private IdentityConfigParser identityConfigParserMock; @Mock - private OAuthAppDO mockOAuthAppDO; - + private OAuthComponentServiceHolder oAuthComponentServiceHolderMock; @Mock - private PasswordGrantHandler passwordGrantHandler; - + private OAuthServerConfiguration mockedOAuthServerConfig; @Mock - private OAuth2AccessTokenRespDTO mockOAuth2AccessTokenRespDTO; + private OAuthAppDO appDO; - @Mock - private JDBCPermissionBasedInternalScopeValidator scopeValidator; - - private static final String DUMMY_GRANT_TYPE = "dummy_grant_type"; - private static final String ID_TOKEN = "dummyIDToken"; - private static final String[] SCOPES_WITHOUT_OPENID = new String[]{"scope1", "scope2"}; - private static final String[] SCOPES_WITH_OPENID = new String[]{"scope1", OAuthConstants.Scope.OPENID}; - -// @BeforeMethod -// public void setUp() throws Exception { -// -// mockStatic(CarbonUtils.class); -// -// mockStatic(OAuthServerConfiguration.class); -// when(OAuthServerConfiguration.getInstance()).thenReturn(oAuthServerConfiguration); -// when(oAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(3600L); -// -// mockStatic(OAuth2Util.class); -// when(OAuth2Util.getAppInformationByClientId(anyString())).thenReturn(mockOAuthAppDO); -// when(mockOAuthAppDO.getState()).thenReturn(APP_STATE_ACTIVE); -// when(OAuth2Util.getTenantDomainOfOauthApp(any(OAuthAppDO.class))) -// .thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); -// } -// -// @AfterMethod -// public void tearDown() throws Exception { -// // Reset the singleton -// Field field = AccessTokenIssuer.class.getDeclaredField("instance"); -// field.setAccessible(true); -// field.set(null, null); -// } -// -// @DataProvider(name = "appConfigProvider") -// public Object[][] provideAppConfigData() { -// -// return new Object[][]{ -// {null}, -// {mock(AppInfoCache.class)} -// }; -// } -// -// @Test(dataProvider = "appConfigProvider") -// public void testGetInstance(Object appInfoCache) throws Exception { -// -// mockStatic(AppInfoCache.class); -// when(AppInfoCache.getInstance()).thenReturn((AppInfoCache) appInfoCache); -// CommonTestUtils.testSingleton(AccessTokenIssuer.getInstance(), AccessTokenIssuer.getInstance()); -// } -// -// @DataProvider(name = "AccessTokenIssue") -// public Object[][] accessTokenIssue() { -// // isOfTypeApplicationUser, -// // isAuthorizedClient, -// // isValidGrant, -// // isAuthorizedAccessDelegation, -// // isValidScope, -// // isAuthenticatedClient, -// // isTokenIssuingSuccess -// return new Object[][]{ -// {true, true, true, true, true, true}, -// {false, true, true, true, true, false}, -// {true, false, true, true, true, false}, -// {true, true, false, true, true, false}, -// {true, true, true, false, true, false}, -// {true, true, true, true, false, false}, -// }; -// } -// -// @Test(dataProvider = "AccessTokenIssue") -// public void testIssue(boolean isAuthorizedClient, -// boolean isValidGrant, -// boolean isAuthorizedAccessDelegation, -// boolean isValidScope, -// boolean isAuthenticatedClient, -// boolean isTokenIssueSuccess) throws IdentityException { -// -// mockPasswordGrantHandler(isAuthorizedClient, isValidGrant, isAuthorizedAccessDelegation, isValidScope); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(OAuthConstants.GrantTypes.PASSWORD); -// reqDTO.setClientId(SOME_CLIENT_ID); -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setAuthenticated(isAuthenticatedClient); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// AccessTokenIssuer tokenIssuer = AccessTokenIssuer.getInstance(); -// OAuth2AccessTokenRespDTO tokenRespDTO = tokenIssuer.issue(reqDTO); -// -// if (isTokenIssueSuccess) { -// Assert.assertFalse(tokenRespDTO.isError()); -// } -// } -// -// /** -// * Multiple Client Authentication mechanisms used to authenticate the request. -// * -// * @throws Exception -// */ -// @Test -// public void testIssueFailedMultipleClientAuthentication() throws Exception { -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.addAuthenticator("ClientAuthenticator1"); -// oAuthClientAuthnContext.addAuthenticator("ClientAuthenticator2"); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.INVALID_REQUEST, "Error Code has been " + -// "changed. Previously it was: " + OAuthError.TokenResponse.INVALID_REQUEST); -// } -// -// @DataProvider(name = "tenantDataProvider") -// public Object[][] getTenantDomainData() { -// -// return new Object[][]{ -// {"non_super_tenant.com"}, -// {null} -// }; -// } -// -// /** -// * Tests whether cross tenant token requests fail in tenant qualified URL mode. -// * -// * @throws Exception -// */ -// @Test (dataProvider = "tenantDataProvider" , expectedExceptions = InvalidOAuthClientException.class) -// public void testCrossTenantTokenRequestError(String tenantInContext) throws Exception { -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType("password"); -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setAuthenticated(true); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// mockStatic(IdentityTenantUtil.class); -// when(IdentityTenantUtil.isTenantQualifiedUrlsEnabled()).thenReturn(true); -// when(IdentityTenantUtil.getTenantDomainFromContext()).thenReturn(tenantInContext); -// when(OAuth2Util.class, "validateRequestTenantDomain", anyString()).thenCallRealMethod(); -// -// mockPasswordGrantHandler(true, true, true, true); -// -// AccessTokenIssuer.getInstance().issue(reqDTO); -// } -// -// /** -// * No authorization grant handler found for the given grant type. -// * -// * @throws Exception -// */ -// @Test -// public void testIssueNoAuthorizationGrantHandler() throws Exception { -// -// when(oAuthServerConfiguration.getSupportedGrantTypes()) -// .thenReturn(new HashMap()); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setAuthenticated(true); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE); -// } -// -// /** -// * No client authenticators to handle authentication but the grant type is restricted to confidential clients. -// * -// * @throws Exception -// */ -// @Test -// public void testIssueWithNoClientAuthentication() throws Exception { -// -// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); -// when(dummyGrantHandler.isConfidentialClient()).thenReturn(true); -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), -// OAuth2ErrorCodes.INVALID_CLIENT); -// } -// -// @DataProvider(name = "unauthorizedClientErrorConditionProvider") -// public Object[][] getUnauthorizedClientErrorConditions() { -// -// return new Object[][]{ -// // whether to throw an exception or not for a valid grant, Exception message -// {true, "Exception when authorizing client."}, -// {false, "The authenticated client is not authorized to use this authorization grant type"} -// }; -// } -// -// @Test(dataProvider = "unauthorizedClientErrorConditionProvider") -// public void testIssueErrorUnauthorizedClient(boolean throwException, -// String exceptionMsg) throws Exception { -// -// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); -// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); -// // Not a confidential client -// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(true); -// -// if (throwException) { -// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))) -// .thenThrow(new IdentityOAuth2Exception(exceptionMsg)); -// } else { -// // Unauthorized client -// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(false); -// } -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.UNAUTHORIZED_CLIENT); -// assertEquals(tokenRespDTO.getErrorMsg(), exceptionMsg); -// } -// -// @DataProvider(name = "invalidGrantErrorDataProvider") -// public Object[][] getInvalidGrantErrorData() { -// -// return new Object[][]{ -// // whether to throw an exception or not for a valid grant, Exception message -// {true, "Exception when processing oauth2 grant."}, -// {false, "Provided Authorization Grant is invalid"} -// }; -// } -// -// @Test(dataProvider = "invalidGrantErrorDataProvider") -// public void testIssueValidateGrantError(boolean throwException, -// String exceptionMsg) throws Exception { -// -// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); -// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); -// // Not a confidential client -// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(true); -// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(true); -// -// if (throwException) { -// // validate grant will throw an exception -// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))) -// .thenThrow(new IdentityOAuth2Exception(exceptionMsg)); -// } else { -// // validate grant will return false -// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(false); -// } -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); -// -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.INVALID_GRANT); -// assertEquals(tokenRespDTO.getErrorMsg(), exceptionMsg); -// } -// -// /** -// * Exception thrown when issuing access token by the Grant Handler -// * -// * @throws Exception -// */ -// @Test -// public void testIssueErrorWhenIssue2() throws Exception { -// -// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(true); -// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// OAuth2AccessTokenRespDTO accessTokenRespDTO = new OAuth2AccessTokenRespDTO(); -// accessTokenRespDTO.setError(true); -// return accessTokenRespDTO; -// } -// }); -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// reqDTO.setClientId(SOME_CLIENT_ID); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// } -// -// @DataProvider(name = "scopeDataProvider") -// public Object[][] provideDummyData() { -// -// return new Object[][]{ -// {null, null}, -// {new String[0], null}, -// {SCOPES_WITHOUT_OPENID, "scope1 scope2"}, -// // scopes are not sorted in the OAuth2AccessTokenRespDTO -// {new String[]{"z", "y", "x"}, "z y x"} -// }; -// } -// -// /** -// * Exception thrown when issuing access token by the Grant Handler -// * -// * @throws Exception -// */ -// @Test(dataProvider = "scopeDataProvider") -// public void testIssueWithScopes(String[] scopes, -// String expectedScopeString) throws Exception { -// -// when(OAuth2Util.buildScopeString(Matchers.anyObject())).thenCallRealMethod(); -// -// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(false); -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// reqDTO.setScope((String[]) ArrayUtils.clone(scopes)); -// -// final ResponseHeader responseHeader = new ResponseHeader(); -// responseHeader.setKey("Header"); -// responseHeader.setValue("HeaderValue"); -// final ResponseHeader[] responseHeaders = new ResponseHeader[]{responseHeader}; -// // Mock Issue -// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// OAuthTokenReqMessageContext context = -// invocationOnMock.getArgument(0); -// // set some response headers -// context.addProperty(OAuthConstants.RESPONSE_HEADERS_PROPERTY, responseHeaders); -// -// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); -// context.setScope(scopeArray); -// return new OAuth2AccessTokenRespDTO(); -// } -// }); -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// whenNew(JDBCPermissionBasedInternalScopeValidator.class).withNoArguments() -// .thenReturn(scopeValidator); -// when(scopeValidator.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(null); -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// -// assertNotNull(tokenRespDTO); -// assertFalse(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getAuthorizedScopes(), expectedScopeString); -// -// // Assert response headers set by the grant handler -// assertNotNull(tokenRespDTO.getResponseHeaders()); -// assertTrue(Arrays.deepEquals(tokenRespDTO.getResponseHeaders(), responseHeaders)); -// -// } -// -// @DataProvider(name = "grantTypeDataProvider") -// public Object[][] provideGrantTypes() { -// -// return new Object[][]{ -// {GrantType.AUTHORIZATION_CODE.toString()}, -// {GrantType.PASSWORD.toString()}, -// }; -// } -// -// @Test(dataProvider = "grantTypeDataProvider") -// public void testIssueWithOpenIdScope(String grantType) throws Exception { -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(grantType); -// reqDTO.setScope((String[]) ArrayUtils.clone(SCOPES_WITH_OPENID)); -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// setupOIDCScopeTest(grantType, true); -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// -// assertNotNull(tokenRespDTO); -// assertFalse(tokenRespDTO.isError()); -// assertTrue(Arrays.deepEquals(tokenRespDTO.getAuthorizedScopes().split(" "), SCOPES_WITH_OPENID)); -// assertNotNull(tokenRespDTO.getIDToken()); -// assertEquals(tokenRespDTO.getIDToken(), ID_TOKEN); -// } -// -// @Test -// public void testIssueWithOpenIdScopeFailure() throws Exception { -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// reqDTO.setScope(SCOPES_WITH_OPENID); -// -// setupOIDCScopeTest(DUMMY_GRANT_TYPE, false); -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// -// assertNotNull(tokenRespDTO); -// assertTrue(tokenRespDTO.isError()); -// assertEquals(tokenRespDTO.getErrorCode(), OAuth2ErrorCodes.SERVER_ERROR); -// // ID Token should not be set -// assertNull(tokenRespDTO.getIDToken()); -// } -// -// @DataProvider(name = "clientAuthContextDataProvider") -// public Object[][] clientAuthContextDataProvider() { -// -// return new Object[][]{ -// -// // Authenticaion has failed from a single authenticator with invalid_client error code. -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", null, OAuth2ErrorCodes -// .INVALID_CLIENT, true, false}, -// -// // Authentication success scenario. -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, true, "BasicAuthenticator", null, null, true, true}, -// -// // Authentication has failed from a single authenticator with invalid_request error code -// {"sampleID", OAuth2ErrorCodes.INVALID_REQUEST, false, "BasicAuthenticator", null, OAuth2ErrorCodes -// .INVALID_REQUEST, true, false}, -// -// // Multiple authenticators are engaged. Eventhough the error message set to context is -// // invalid_client, the actual error message should be invalid_request. -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", "AnotherAuthenticator", -// OAuth2ErrorCodes -// .INVALID_REQUEST, true, false}, -// -// // Non confidential grant type. Hence authentication is not required. -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", null, -// null, false, true}, -// -// // Multiple authenticators are engaged. Hence invalid request. -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", "AnotherAuthenticator", -// OAuth2ErrorCodes.INVALID_REQUEST, false, false}, -// -// // No authenticator engaged. Hence authentication should fail -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, null, null, -// OAuth2ErrorCodes.INVALID_CLIENT, true, false}, -// -// // Non confidential apps doesn't need authentication -// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, null, null, -// null, false, true}, -// }; -// -// } -// -// /** -// * Make sure oauth client authenticaion is done with context data. -// * -// * @throws Exception -// */ -// @Test(dataProvider = "clientAuthContextDataProvider") -// public void testClientAuthenticaion(String clientId, String errorCode, boolean isAuthenticated, String -// authenticator1, String authenticator2, String expectedErrorCode, boolean isConfidential, boolean -// authnResult) throws Exception { -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId(clientId); -// oAuthClientAuthnContext.setErrorCode(errorCode); -// oAuthClientAuthnContext.setAuthenticated(isAuthenticated); -// -// if (StringUtils.isNotEmpty(authenticator1)) { -// oAuthClientAuthnContext.addAuthenticator(authenticator1); -// } -// if (StringUtils.isNotEmpty(authenticator2)) { -// oAuthClientAuthnContext.addAuthenticator(authenticator2); -// } -// -// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(true); -// -// final ResponseHeader responseHeader = new ResponseHeader(); -// responseHeader.setKey("Header"); -// responseHeader.setValue("HeaderValue"); -// final ResponseHeader[] responseHeaders = new ResponseHeader[]{responseHeader}; -// -// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// OAuthTokenReqMessageContext context = -// invocationOnMock.getArgument(0); -// // set some response headers -// context.addProperty(OAuthConstants.RESPONSE_HEADERS_PROPERTY, responseHeaders); -// -// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); -// context.setScope(scopeArray); -// return new OAuth2AccessTokenRespDTO(); -// } -// }); -// -// when(dummyGrantHandler.isConfidentialClient()).thenReturn(isConfidential); -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// -// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); -// assertNotNull(tokenRespDTO); -// assertEquals(tokenRespDTO.isError(), !authnResult); -// assertEquals(tokenRespDTO.getErrorCode(), expectedErrorCode); -// } -// -// /** -// * Test whether the client ID sent in error response for a invalid client token request, is properly encoded. -// * -// * @throws Exception -// */ -// @Test -// public void testIssueWithInvalidClient() throws Exception { -// -// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); -// oAuthClientAuthnContext.setClientId("sampleID"); -// oAuthClientAuthnContext.setErrorCode(OAuth2ErrorCodes.INVALID_CLIENT); -// oAuthClientAuthnContext.setAuthenticated(false); -// -// String malicousClientID = ""; -// String encodedClientID = "<img src=a onerror=alert(1)>"; -// -// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); -// reqDTO.setGrantType(DUMMY_GRANT_TYPE); -// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); -// reqDTO.setClientId(malicousClientID); -// when(mockOAuthAppDO.getState()).thenReturn(null); -// -// try { -// AccessTokenIssuer.getInstance().issue(reqDTO); -// } catch (InvalidOAuthClientException ex) { -// assertTrue(ex.getMessage().contains(encodedClientID)); -// } -// } -// -// private AuthorizationGrantHandler getMockGrantHandlerForSuccess(boolean isOfTypeApplicationUser) -// throws IdentityOAuth2Exception { -// -// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); -// // Not a confidential client -// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); -// // This grant issue token for an APPLICATION -// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(isOfTypeApplicationUser); -// // Unauthorized client -// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(true); -// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(true); -// when(dummyGrantHandler.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(true); -// when(dummyGrantHandler.authorizeAccessDelegation(any(OAuthTokenReqMessageContext.class))) -// .thenReturn(true); -// return dummyGrantHandler; -// } -// -// private void mockOAuth2ServerConfiguration(Map authorizationGrantHandlerMap) { -// -// when(oAuthServerConfiguration.getSupportedGrantTypes()).thenReturn(authorizationGrantHandlerMap); -// } -// -// private void setupOIDCScopeTest(String grantType, -// boolean success) throws IdentityOAuth2Exception { -// -// AuthorizationGrantHandler grantHandler = getMockGrantHandlerForSuccess(false); -// -// when(OAuth2Util.buildScopeString(Matchers.anyObject())).thenCallRealMethod(); -// when(OAuth2Util.isOIDCAuthzRequest(Matchers.anyObject())).thenCallRealMethod(); -// -// IDTokenBuilder idTokenBuilder; -// if (success) { -// idTokenBuilder = getMockIDTokenBuilderForSuccess(); -// } else { -// idTokenBuilder = getMockIDTokenBuilderForFailure(); -// } -// -// when(oAuthServerConfiguration.getOpenIDConnectIDTokenBuilder()).thenReturn(idTokenBuilder); -// -// // Mock Issue method of the grant handler -// when(grantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// OAuthTokenReqMessageContext context = -// invocationOnMock.getArgument(0); -// -// // set the scope sent in the request -// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); -// -// // Set the scope array for OIDC -// context.setScope(scopeArray); -// return new OAuth2AccessTokenRespDTO(); -// } -// }); -// -// HashMap authorizationGrantHandlers = new HashMap<>(); -// authorizationGrantHandlers.put(grantType, grantHandler); -// -// mockOAuth2ServerConfiguration(authorizationGrantHandlers); -// } -// -// private IDTokenBuilder getMockIDTokenBuilderForSuccess() throws IdentityOAuth2Exception { -// -// IDTokenBuilder idTokenBuilder = mock(IDTokenBuilder.class); -// when(idTokenBuilder.buildIDToken(any(OAuthTokenReqMessageContext.class), any(OAuth2AccessTokenRespDTO.class))) -// .then(new Answer() { -// @Override -// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { -// -// return ID_TOKEN; -// } -// }); -// return idTokenBuilder; -// } -// -// private IDTokenBuilder getMockIDTokenBuilderForFailure() throws IdentityOAuth2Exception { -// -// IDTokenBuilder idTokenBuilder = mock(IDTokenBuilder.class); -// when(idTokenBuilder.buildIDToken(any(OAuthTokenReqMessageContext.class), any(OAuth2AccessTokenRespDTO.class))) -// .thenThrow(new IDTokenValidationFailureException("ID Token Validation failed")); -// return idTokenBuilder; -// } -// -// private void mockPasswordGrantHandler(boolean isAuthorizedClient, boolean isValidGrant, -// boolean isAuthorizedAccessDelegation, boolean isValidScope) -// throws IdentityOAuth2Exception { -// -// Map authzGrantHandlers = new Hashtable<>(); -// -// when(passwordGrantHandler.isOfTypeApplicationUser()).thenReturn(true); -// when(passwordGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))) -// .thenReturn(isAuthorizedClient); -// when(passwordGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(isValidGrant); -// when(passwordGrantHandler.authorizeAccessDelegation(any(OAuthTokenReqMessageContext.class))) -// .thenReturn(isAuthorizedAccessDelegation); -// when(passwordGrantHandler.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(isValidScope); -// when(passwordGrantHandler.issue(any(OAuthTokenReqMessageContext.class))) -// .thenReturn(new OAuth2AccessTokenRespDTO()); -// authzGrantHandlers.put("password", passwordGrantHandler); -// when(passwordGrantHandler.isConfidentialClient()).thenReturn(true); -// -// when(oAuthServerConfiguration.getSupportedGrantTypes()).thenReturn(authzGrantHandlers); -// } + @AfterClass + public void cleanUp() throws Exception { + + PrivilegedCarbonContext.endTenantFlow(); + System.clearProperty(CarbonBaseConstants.CARBON_HOME); + mocks.close(); + } + + @BeforeMethod + public void setUp() throws Exception { + + setSystemProperties(); + clearAccessTokenIssuerInstance(); + mocks = openMocks(this); + } + + @AfterMethod + public void resetTest() throws Exception { + + clearAccessTokenIssuerInstance(); + } + + private void clearAccessTokenIssuerInstance() throws Exception { + + Field instanceField = AccessTokenIssuer.class.getDeclaredField("instance"); + instanceField.setAccessible(true); + instanceField.set(null, null); + instanceField.setAccessible(false); + } + + private void setSystemProperties() { + + System.setProperty(CarbonBaseConstants.CARBON_HOME, + Paths.get(System.getProperty("user.dir"), "src", "test", "resources").toString()); + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(testTenantDomain); + } + + @DataProvider + public Object[][] oAuth2AccessTokenReqDTODataProvider() { + + OAuth2AccessTokenReqDTO dto = mock(OAuth2AccessTokenReqDTO.class); + OAuthClientAuthnContext context = mock(OAuthClientAuthnContext.class); + when(dto.getClientId()).thenReturn(testClientId); + when(dto.getGrantType()).thenReturn(OAuthConstants.GrantTypes.CLIENT_CREDENTIALS); + when(dto.getScope()).thenReturn(new String[]{"scope1", "scope2"}); + when(dto.getTenantDomain()).thenReturn(testTenantDomain); + when(dto.getoAuthClientAuthnContext()).thenReturn(context); + when(context.isMultipleAuthenticatorsEngaged()).thenReturn(false); + when(context.isAuthenticated()).thenReturn(true); + return new Object[][]{{dto}, {dto}}; + } + + @Test(dataProvider = "oAuth2AccessTokenReqDTODataProvider") + public void testTriggerPostIssueTokenEvent(OAuth2AccessTokenReqDTO dto) throws IdentityException, + IdentityApplicationManagementException, UserStoreException, OrganizationManagementException { + + try ( + MockedStatic loggerUtilsMockedStatic = mockStatic(LoggerUtils.class); + MockedStatic identityConfigParserMockedStatic + = mockStatic(IdentityConfigParser.class); + MockedStatic oAuthComponentServiceHolderMockedStatic + = mockStatic(OAuthComponentServiceHolder.class); + MockedStatic oAuthServerConfigurationMockedStatic + = mockStatic(OAuthServerConfiguration.class); + MockedStatic authorizationDetailsProcessorFactoryMockedStatic + = mockStatic(AuthorizationDetailsProcessorFactory.class); + MockedStatic oAuth2ServiceComponentHolderMockedStatic + = mockStatic(OAuth2ServiceComponentHolder.class); + MockedStatic appInfoCacheMockedStatic = mockStatic(AppInfoCache.class); + MockedStatic identityTenantUtil = mockStatic(IdentityTenantUtil.class); + MockedStatic authzUtil = mockStatic(AuthzUtil.class); + MockedStatic oAuthCache = mockStatic(OAuthCache.class); + MockedStatic oAuth2TokenUtil = mockStatic(OAuth2TokenUtil.class); + MockedStatic identityUtil = mockStatic(IdentityUtil.class) + ) { + OAuth2AccessTokenRespDTO tokenResp = mock(OAuth2AccessTokenRespDTO.class); + when(tokenResp.getTokenId()).thenReturn(testTokenId); + + AuthorizationGrantHandler grantHandler = mock(AuthorizationGrantHandler.class); + when(grantHandler.isAuthorizedClient(any())).thenReturn(true); + when(grantHandler.validateGrant(any())).thenReturn(true); + when(grantHandler.authorizeAccessDelegation(any())).thenReturn(true); + when(grantHandler.validateScope(any())).thenReturn(true); + when(grantHandler.issue(any())).thenReturn(tokenResp); + + Map supportedGrantTypes = new HashMap<>(); + supportedGrantTypes.put(OAuthConstants.GrantTypes.CLIENT_CREDENTIALS, grantHandler); + when(mockedOAuthServerConfig.getSupportedGrantTypes()).thenReturn(supportedGrantTypes); + oAuthServerConfigurationMockedStatic.when(OAuthServerConfiguration::getInstance) + .thenReturn(mockedOAuthServerConfig); + try ( + MockedStatic oAuth2Util = mockStatic(OAuth2Util.class)) { + loggerUtilsMockedStatic.when(LoggerUtils::isDiagnosticLogsEnabled).thenReturn(true); + identityConfigParserMockedStatic.when(IdentityConfigParser::getInstance) + .thenReturn(identityConfigParserMock); + oAuthComponentServiceHolderMockedStatic.when(OAuthComponentServiceHolder::getInstance) + .thenReturn(oAuthComponentServiceHolderMock); + + authorizationDetailsProcessorFactoryMockedStatic.when(AuthorizationDetailsProcessorFactory::getInstance) + .thenReturn(mock(AuthorizationDetailsProcessorFactory.class)); + + OAuthCache cache = mock(OAuthCache.class); + oAuthCache.when(OAuthCache::getInstance).thenReturn(cache); + when(oAuthComponentServiceHolderMock.getOAuthEventInterceptorProxy()) + .thenReturn(mock(OAuthEventInterceptor.class)); + + OrganizationManager organizationManager = mock(OrganizationManager.class); + when(oAuthComponentServiceHolderMock.getOrganizationManager()).thenReturn(organizationManager); + when(organizationManager.resolveOrganizationId(testTenantDomain)).thenReturn(testOrganizationId); + + OAuth2ServiceComponentHolder componentHolder = mock(OAuth2ServiceComponentHolder.class); + when(componentHolder.getAuthorizationDetailsService()) + .thenReturn(mock(AuthorizationDetailsService.class)); + when(componentHolder.getAuthorizationDetailsSchemaValidator()) + .thenReturn(mock(AuthorizationDetailsSchemaValidator.class)); + oAuth2ServiceComponentHolderMockedStatic.when(OAuth2ServiceComponentHolder::getInstance) + .thenReturn(componentHolder); + + AppInfoCache appInfoCache = mock(AppInfoCache.class); + appInfoCacheMockedStatic.when(AppInfoCache::getInstance).thenReturn(appInfoCache); + + AuthenticatedUser appOwner = mock(AuthenticatedUser.class); + when(appOwner.getUserId()).thenReturn("12345"); + when(appOwner.getTenantDomain()).thenReturn(testTenantDomain); + when(appOwner.getUserStoreDomain()).thenReturn("PRIMARY"); + when(appOwner.toFullQualifiedUsername()).thenReturn("PRIMARY/testUser@carbon.super"); + when(appOwner.getAccessingOrganization()).thenReturn(testAccessingOrganizationId); + + when(appDO.getState()).thenReturn(APP_STATE_ACTIVE); + when(appDO.getAppOwner()).thenReturn(appOwner); + + ServiceProvider sp = mock(ServiceProvider.class); + when(sp.getApplicationName()).thenReturn(testApplicationName); + + ApplicationManagementService appMgtService = mock(ApplicationManagementService.class); + LocalAndOutboundAuthenticationConfig authConfig = mock(LocalAndOutboundAuthenticationConfig.class); + when(authConfig.getSubjectClaimUri()).thenReturn("test.subject.claim.uri"); + when(sp.getLocalAndOutBoundAuthenticationConfig()).thenReturn(authConfig); + when(appMgtService.getServiceProviderByClientId(anyString(), anyString(), anyString())) + .thenReturn(sp); + when(OAuth2ServiceComponentHolder.getApplicationMgtService()).thenReturn(appMgtService); + + oAuth2Util.when(() -> OAuth2Util.isAppVersionAllowed(anyString(), anyString())).thenReturn(true); + oAuth2Util.when(() -> OAuth2Util.getAppInformationByClientId(anyString(), anyString())) + .thenReturn(appDO); + oAuth2Util.when(() -> OAuth2Util.getServiceProvider(testClientId, testTenantDomain)).thenReturn(sp); + + UserRealm userRealm = mock(UserRealm.class); + AbstractUserStoreManager userStore = mock(AbstractUserStoreManager.class); + when(userStore.getUserClaimValueWithID(any(), any(), nullable(String.class))) + .thenReturn("testUserClaimValue"); + when(userRealm.getUserStoreManager()).thenReturn(userStore); + + identityTenantUtil.when(() -> IdentityTenantUtil.getRealm(any(), any())).thenReturn(userRealm); + identityTenantUtil.when(IdentityTenantUtil::getLoginTenantId).thenReturn(testAppResidentTenantId); + + authzUtil.when(AuthzUtil::isLegacyAuthzRuntime).thenReturn(false); + identityUtil.when(() -> IdentityUtil.getProperty(ENABLE_POST_TOKEN_ISSUE_EVENT)).thenReturn("true"); + AccessTokenIssuer.getInstance().issue(dto); + + oAuth2TokenUtil.verify(() -> OAuth2TokenUtil.postIssueToken( + argThat((eventProperties) -> { + Assert.assertEquals(eventProperties.get(OIDCConstants.Event.TOKEN_ID), + testTokenId); + Assert.assertEquals(eventProperties.get(OIDCConstants.Event.TENANT_DOMAIN), + testTenantDomain); + Assert.assertEquals(eventProperties.get(OIDCConstants.Event.USER_TYPE), + OAuthConstants.UserType.APPLICATION); + Assert.assertEquals(eventProperties.get(OIDCConstants.Event.CLIENT_ID), + testClientId); + Assert.assertEquals(eventProperties.get(OIDCConstants.Event.GRANT_TYPE), + OAuthConstants.GrantTypes.CLIENT_CREDENTIALS); + Assert.assertEquals(eventProperties.get( + OIDCConstants.Event.ISSUER_ORGANIZATION_ID), testOrganizationId); + Assert.assertEquals( + eventProperties.get(OIDCConstants.Event.APP_RESIDENT_TENANT_ID), + testAppResidentTenantId); + Assert.assertEquals( + eventProperties.get(OIDCConstants.Event.ACCESSING_ORGANIZATION_ID), + testAccessingOrganizationId); + Assert.assertEquals(eventProperties.get( + OIDCConstants.Event.SERVICE_PROVIDER), + testApplicationName); + return true; + } + )), + times(1)); + } + } + } } diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/DeprecatedAccessTokenIssuerTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/DeprecatedAccessTokenIssuerTest.java new file mode 100644 index 00000000000..782e18d9f5d --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/token/DeprecatedAccessTokenIssuerTest.java @@ -0,0 +1,735 @@ +/* + * 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; + +import org.mockito.Mock; +import org.wso2.carbon.identity.oauth.common.OAuthConstants; +import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; +import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO; +import org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler; +import org.wso2.carbon.identity.oauth2.validators.JDBCPermissionBasedInternalScopeValidator; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +/** + * Unit test cases for {@link AccessTokenIssuer} + */ + +public class DeprecatedAccessTokenIssuerTest { + + public static final String SOME_CLIENT_ID = "some-client-id"; + @Mock + private OAuthServerConfiguration oAuthServerConfiguration; + + @Mock + private OAuthAppDO mockOAuthAppDO; + + @Mock + private PasswordGrantHandler passwordGrantHandler; + + @Mock + private OAuth2AccessTokenRespDTO mockOAuth2AccessTokenRespDTO; + + @Mock + private JDBCPermissionBasedInternalScopeValidator scopeValidator; + + private static final String DUMMY_GRANT_TYPE = "dummy_grant_type"; + private static final String ID_TOKEN = "dummyIDToken"; + private static final String[] SCOPES_WITHOUT_OPENID = new String[]{"scope1", "scope2"}; + private static final String[] SCOPES_WITH_OPENID = new String[]{"scope1", OAuthConstants.Scope.OPENID}; + +// @BeforeMethod +// public void setUp() throws Exception { +// +// mockStatic(CarbonUtils.class); +// +// mockStatic(OAuthServerConfiguration.class); +// when(OAuthServerConfiguration.getInstance()).thenReturn(oAuthServerConfiguration); +// when(oAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(3600L); +// +// mockStatic(OAuth2Util.class); +// when(OAuth2Util.getAppInformationByClientId(anyString())).thenReturn(mockOAuthAppDO); +// when(mockOAuthAppDO.getState()).thenReturn(APP_STATE_ACTIVE); +// when(OAuth2Util.getTenantDomainOfOauthApp(any(OAuthAppDO.class))) +// .thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); +// } +// +// @AfterMethod +// public void tearDown() throws Exception { +// // Reset the singleton +// Field field = AccessTokenIssuer.class.getDeclaredField("instance"); +// field.setAccessible(true); +// field.set(null, null); +// } +// +// @DataProvider(name = "appConfigProvider") +// public Object[][] provideAppConfigData() { +// +// return new Object[][]{ +// {null}, +// {mock(AppInfoCache.class)} +// }; +// } +// +// @Test(dataProvider = "appConfigProvider") +// public void testGetInstance(Object appInfoCache) throws Exception { +// +// mockStatic(AppInfoCache.class); +// when(AppInfoCache.getInstance()).thenReturn((AppInfoCache) appInfoCache); +// CommonTestUtils.testSingleton(AccessTokenIssuer.getInstance(), AccessTokenIssuer.getInstance()); +// } +// +// @DataProvider(name = "AccessTokenIssue") +// public Object[][] accessTokenIssue() { +// // isOfTypeApplicationUser, +// // isAuthorizedClient, +// // isValidGrant, +// // isAuthorizedAccessDelegation, +// // isValidScope, +// // isAuthenticatedClient, +// // isTokenIssuingSuccess +// return new Object[][]{ +// {true, true, true, true, true, true}, +// {false, true, true, true, true, false}, +// {true, false, true, true, true, false}, +// {true, true, false, true, true, false}, +// {true, true, true, false, true, false}, +// {true, true, true, true, false, false}, +// }; +// } +// +// @Test(dataProvider = "AccessTokenIssue") +// public void testIssue(boolean isAuthorizedClient, +// boolean isValidGrant, +// boolean isAuthorizedAccessDelegation, +// boolean isValidScope, +// boolean isAuthenticatedClient, +// boolean isTokenIssueSuccess) throws IdentityException { +// +// mockPasswordGrantHandler(isAuthorizedClient, isValidGrant, isAuthorizedAccessDelegation, isValidScope); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(OAuthConstants.GrantTypes.PASSWORD); +// reqDTO.setClientId(SOME_CLIENT_ID); +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setAuthenticated(isAuthenticatedClient); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// AccessTokenIssuer tokenIssuer = AccessTokenIssuer.getInstance(); +// OAuth2AccessTokenRespDTO tokenRespDTO = tokenIssuer.issue(reqDTO); +// +// if (isTokenIssueSuccess) { +// Assert.assertFalse(tokenRespDTO.isError()); +// } +// } +// +// /** +// * Multiple Client Authentication mechanisms used to authenticate the request. +// * +// * @throws Exception +// */ +// @Test +// public void testIssueFailedMultipleClientAuthentication() throws Exception { +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.addAuthenticator("ClientAuthenticator1"); +// oAuthClientAuthnContext.addAuthenticator("ClientAuthenticator2"); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.INVALID_REQUEST, "Error Code has been " + +// "changed. Previously it was: " + OAuthError.TokenResponse.INVALID_REQUEST); +// } +// +// @DataProvider(name = "tenantDataProvider") +// public Object[][] getTenantDomainData() { +// +// return new Object[][]{ +// {"non_super_tenant.com"}, +// {null} +// }; +// } +// +// /** +// * Tests whether cross tenant token requests fail in tenant qualified URL mode. +// * +// * @throws Exception +// */ +// @Test (dataProvider = "tenantDataProvider" , expectedExceptions = InvalidOAuthClientException.class) +// public void testCrossTenantTokenRequestError(String tenantInContext) throws Exception { +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType("password"); +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setAuthenticated(true); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// mockStatic(IdentityTenantUtil.class); +// when(IdentityTenantUtil.isTenantQualifiedUrlsEnabled()).thenReturn(true); +// when(IdentityTenantUtil.getTenantDomainFromContext()).thenReturn(tenantInContext); +// when(OAuth2Util.class, "validateRequestTenantDomain", anyString()).thenCallRealMethod(); +// +// mockPasswordGrantHandler(true, true, true, true); +// +// AccessTokenIssuer.getInstance().issue(reqDTO); +// } +// +// /** +// * No authorization grant handler found for the given grant type. +// * +// * @throws Exception +// */ +// @Test +// public void testIssueNoAuthorizationGrantHandler() throws Exception { +// +// when(oAuthServerConfiguration.getSupportedGrantTypes()) +// .thenReturn(new HashMap()); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setAuthenticated(true); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE); +// } +// +// /** +// * No client authenticators to handle authentication but the grant type is restricted to confidential clients. +// * +// * @throws Exception +// */ +// @Test +// public void testIssueWithNoClientAuthentication() throws Exception { +// +// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); +// when(dummyGrantHandler.isConfidentialClient()).thenReturn(true); +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), +// OAuth2ErrorCodes.INVALID_CLIENT); +// } +// +// @DataProvider(name = "unauthorizedClientErrorConditionProvider") +// public Object[][] getUnauthorizedClientErrorConditions() { +// +// return new Object[][]{ +// // whether to throw an exception or not for a valid grant, Exception message +// {true, "Exception when authorizing client."}, +// {false, "The authenticated client is not authorized to use this authorization grant type"} +// }; +// } +// +// @Test(dataProvider = "unauthorizedClientErrorConditionProvider") +// public void testIssueErrorUnauthorizedClient(boolean throwException, +// String exceptionMsg) throws Exception { +// +// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); +// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); +// // Not a confidential client +// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(true); +// +// if (throwException) { +// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))) +// .thenThrow(new IdentityOAuth2Exception(exceptionMsg)); +// } else { +// // Unauthorized client +// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(false); +// } +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.UNAUTHORIZED_CLIENT); +// assertEquals(tokenRespDTO.getErrorMsg(), exceptionMsg); +// } +// +// @DataProvider(name = "invalidGrantErrorDataProvider") +// public Object[][] getInvalidGrantErrorData() { +// +// return new Object[][]{ +// // whether to throw an exception or not for a valid grant, Exception message +// {true, "Exception when processing oauth2 grant."}, +// {false, "Provided Authorization Grant is invalid"} +// }; +// } +// +// @Test(dataProvider = "invalidGrantErrorDataProvider") +// public void testIssueValidateGrantError(boolean throwException, +// String exceptionMsg) throws Exception { +// +// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); +// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); +// // Not a confidential client +// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(true); +// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(true); +// +// if (throwException) { +// // validate grant will throw an exception +// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))) +// .thenThrow(new IdentityOAuth2Exception(exceptionMsg)); +// } else { +// // validate grant will return false +// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(false); +// } +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); +// +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), OAuthError.TokenResponse.INVALID_GRANT); +// assertEquals(tokenRespDTO.getErrorMsg(), exceptionMsg); +// } +// +// /** +// * Exception thrown when issuing access token by the Grant Handler +// * +// * @throws Exception +// */ +// @Test +// public void testIssueErrorWhenIssue2() throws Exception { +// +// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(true); +// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// OAuth2AccessTokenRespDTO accessTokenRespDTO = new OAuth2AccessTokenRespDTO(); +// accessTokenRespDTO.setError(true); +// return accessTokenRespDTO; +// } +// }); +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// reqDTO.setClientId(SOME_CLIENT_ID); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// } +// +// @DataProvider(name = "scopeDataProvider") +// public Object[][] provideDummyData() { +// +// return new Object[][]{ +// {null, null}, +// {new String[0], null}, +// {SCOPES_WITHOUT_OPENID, "scope1 scope2"}, +// // scopes are not sorted in the OAuth2AccessTokenRespDTO +// {new String[]{"z", "y", "x"}, "z y x"} +// }; +// } +// +// /** +// * Exception thrown when issuing access token by the Grant Handler +// * +// * @throws Exception +// */ +// @Test(dataProvider = "scopeDataProvider") +// public void testIssueWithScopes(String[] scopes, +// String expectedScopeString) throws Exception { +// +// when(OAuth2Util.buildScopeString(Matchers.anyObject())).thenCallRealMethod(); +// +// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(false); +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// reqDTO.setScope((String[]) ArrayUtils.clone(scopes)); +// +// final ResponseHeader responseHeader = new ResponseHeader(); +// responseHeader.setKey("Header"); +// responseHeader.setValue("HeaderValue"); +// final ResponseHeader[] responseHeaders = new ResponseHeader[]{responseHeader}; +// // Mock Issue +// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// OAuthTokenReqMessageContext context = +// invocationOnMock.getArgument(0); +// // set some response headers +// context.addProperty(OAuthConstants.RESPONSE_HEADERS_PROPERTY, responseHeaders); +// +// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); +// context.setScope(scopeArray); +// return new OAuth2AccessTokenRespDTO(); +// } +// }); +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// whenNew(JDBCPermissionBasedInternalScopeValidator.class).withNoArguments() +// .thenReturn(scopeValidator); +// when(scopeValidator.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(null); +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// +// assertNotNull(tokenRespDTO); +// assertFalse(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getAuthorizedScopes(), expectedScopeString); +// +// // Assert response headers set by the grant handler +// assertNotNull(tokenRespDTO.getResponseHeaders()); +// assertTrue(Arrays.deepEquals(tokenRespDTO.getResponseHeaders(), responseHeaders)); +// +// } +// +// @DataProvider(name = "grantTypeDataProvider") +// public Object[][] provideGrantTypes() { +// +// return new Object[][]{ +// {GrantType.AUTHORIZATION_CODE.toString()}, +// {GrantType.PASSWORD.toString()}, +// }; +// } +// +// @Test(dataProvider = "grantTypeDataProvider") +// public void testIssueWithOpenIdScope(String grantType) throws Exception { +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(grantType); +// reqDTO.setScope((String[]) ArrayUtils.clone(SCOPES_WITH_OPENID)); +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// setupOIDCScopeTest(grantType, true); +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// +// assertNotNull(tokenRespDTO); +// assertFalse(tokenRespDTO.isError()); +// assertTrue(Arrays.deepEquals(tokenRespDTO.getAuthorizedScopes().split(" "), SCOPES_WITH_OPENID)); +// assertNotNull(tokenRespDTO.getIDToken()); +// assertEquals(tokenRespDTO.getIDToken(), ID_TOKEN); +// } +// +// @Test +// public void testIssueWithOpenIdScopeFailure() throws Exception { +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// reqDTO.setScope(SCOPES_WITH_OPENID); +// +// setupOIDCScopeTest(DUMMY_GRANT_TYPE, false); +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(SOME_CLIENT_ID); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// +// assertNotNull(tokenRespDTO); +// assertTrue(tokenRespDTO.isError()); +// assertEquals(tokenRespDTO.getErrorCode(), OAuth2ErrorCodes.SERVER_ERROR); +// // ID Token should not be set +// assertNull(tokenRespDTO.getIDToken()); +// } +// +// @DataProvider(name = "clientAuthContextDataProvider") +// public Object[][] clientAuthContextDataProvider() { +// +// return new Object[][]{ +// +// // Authenticaion has failed from a single authenticator with invalid_client error code. +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", null, OAuth2ErrorCodes +// .INVALID_CLIENT, true, false}, +// +// // Authentication success scenario. +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, true, "BasicAuthenticator", null, null, true, true}, +// +// // Authentication has failed from a single authenticator with invalid_request error code +// {"sampleID", OAuth2ErrorCodes.INVALID_REQUEST, false, "BasicAuthenticator", null, OAuth2ErrorCodes +// .INVALID_REQUEST, true, false}, +// +// // Multiple authenticators are engaged. Eventhough the error message set to context is +// // invalid_client, the actual error message should be invalid_request. +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", "AnotherAuthenticator", +// OAuth2ErrorCodes +// .INVALID_REQUEST, true, false}, +// +// // Non confidential grant type. Hence authentication is not required. +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", null, +// null, false, true}, +// +// // Multiple authenticators are engaged. Hence invalid request. +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, "BasicAuthenticator", "AnotherAuthenticator", +// OAuth2ErrorCodes.INVALID_REQUEST, false, false}, +// +// // No authenticator engaged. Hence authentication should fail +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, null, null, +// OAuth2ErrorCodes.INVALID_CLIENT, true, false}, +// +// // Non confidential apps doesn't need authentication +// {"sampleID", OAuth2ErrorCodes.INVALID_CLIENT, false, null, null, +// null, false, true}, +// }; +// +// } +// +// /** +// * Make sure oauth client authenticaion is done with context data. +// * +// * @throws Exception +// */ +// @Test(dataProvider = "clientAuthContextDataProvider") +// public void testClientAuthenticaion(String clientId, String errorCode, boolean isAuthenticated, String +// authenticator1, String authenticator2, String expectedErrorCode, boolean isConfidential, boolean +// authnResult) throws Exception { +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId(clientId); +// oAuthClientAuthnContext.setErrorCode(errorCode); +// oAuthClientAuthnContext.setAuthenticated(isAuthenticated); +// +// if (StringUtils.isNotEmpty(authenticator1)) { +// oAuthClientAuthnContext.addAuthenticator(authenticator1); +// } +// if (StringUtils.isNotEmpty(authenticator2)) { +// oAuthClientAuthnContext.addAuthenticator(authenticator2); +// } +// +// AuthorizationGrantHandler dummyGrantHandler = getMockGrantHandlerForSuccess(true); +// +// final ResponseHeader responseHeader = new ResponseHeader(); +// responseHeader.setKey("Header"); +// responseHeader.setValue("HeaderValue"); +// final ResponseHeader[] responseHeaders = new ResponseHeader[]{responseHeader}; +// +// when(dummyGrantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// OAuthTokenReqMessageContext context = +// invocationOnMock.getArgument(0); +// // set some response headers +// context.addProperty(OAuthConstants.RESPONSE_HEADERS_PROPERTY, responseHeaders); +// +// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); +// context.setScope(scopeArray); +// return new OAuth2AccessTokenRespDTO(); +// } +// }); +// +// when(dummyGrantHandler.isConfidentialClient()).thenReturn(isConfidential); +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(DUMMY_GRANT_TYPE, dummyGrantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// +// OAuth2AccessTokenRespDTO tokenRespDTO = AccessTokenIssuer.getInstance().issue(reqDTO); +// assertNotNull(tokenRespDTO); +// assertEquals(tokenRespDTO.isError(), !authnResult); +// assertEquals(tokenRespDTO.getErrorCode(), expectedErrorCode); +// } +// +// /** +// * Test whether the client ID sent in error response for a invalid client token request, is properly encoded. +// * +// * @throws Exception +// */ +// @Test +// public void testIssueWithInvalidClient() throws Exception { +// +// OAuthClientAuthnContext oAuthClientAuthnContext = new OAuthClientAuthnContext(); +// oAuthClientAuthnContext.setClientId("sampleID"); +// oAuthClientAuthnContext.setErrorCode(OAuth2ErrorCodes.INVALID_CLIENT); +// oAuthClientAuthnContext.setAuthenticated(false); +// +// String malicousClientID = ""; +// String encodedClientID = "<img src=a onerror=alert(1)>"; +// +// OAuth2AccessTokenReqDTO reqDTO = new OAuth2AccessTokenReqDTO(); +// reqDTO.setGrantType(DUMMY_GRANT_TYPE); +// reqDTO.setoAuthClientAuthnContext(oAuthClientAuthnContext); +// reqDTO.setClientId(malicousClientID); +// when(mockOAuthAppDO.getState()).thenReturn(null); +// +// try { +// AccessTokenIssuer.getInstance().issue(reqDTO); +// } catch (InvalidOAuthClientException ex) { +// assertTrue(ex.getMessage().contains(encodedClientID)); +// } +// } +// +// private AuthorizationGrantHandler getMockGrantHandlerForSuccess(boolean isOfTypeApplicationUser) +// throws IdentityOAuth2Exception { +// +// AuthorizationGrantHandler dummyGrantHandler = mock(AuthorizationGrantHandler.class); +// // Not a confidential client +// when(dummyGrantHandler.isConfidentialClient()).thenReturn(false); +// // This grant issue token for an APPLICATION +// when(dummyGrantHandler.isOfTypeApplicationUser()).thenReturn(isOfTypeApplicationUser); +// // Unauthorized client +// when(dummyGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))).thenReturn(true); +// when(dummyGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(true); +// when(dummyGrantHandler.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(true); +// when(dummyGrantHandler.authorizeAccessDelegation(any(OAuthTokenReqMessageContext.class))) +// .thenReturn(true); +// return dummyGrantHandler; +// } +// +// private void mockOAuth2ServerConfiguration(Map authorizationGrantHandlerMap) { +// +// when(oAuthServerConfiguration.getSupportedGrantTypes()).thenReturn(authorizationGrantHandlerMap); +// } +// +// private void setupOIDCScopeTest(String grantType, +// boolean success) throws IdentityOAuth2Exception { +// +// AuthorizationGrantHandler grantHandler = getMockGrantHandlerForSuccess(false); +// +// when(OAuth2Util.buildScopeString(Matchers.anyObject())).thenCallRealMethod(); +// when(OAuth2Util.isOIDCAuthzRequest(Matchers.anyObject())).thenCallRealMethod(); +// +// IDTokenBuilder idTokenBuilder; +// if (success) { +// idTokenBuilder = getMockIDTokenBuilderForSuccess(); +// } else { +// idTokenBuilder = getMockIDTokenBuilderForFailure(); +// } +// +// when(oAuthServerConfiguration.getOpenIDConnectIDTokenBuilder()).thenReturn(idTokenBuilder); +// +// // Mock Issue method of the grant handler +// when(grantHandler.issue(any(OAuthTokenReqMessageContext.class))).then(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// OAuthTokenReqMessageContext context = +// invocationOnMock.getArgument(0); +// +// // set the scope sent in the request +// String[] scopeArray = context.getOauth2AccessTokenReqDTO().getScope(); +// +// // Set the scope array for OIDC +// context.setScope(scopeArray); +// return new OAuth2AccessTokenRespDTO(); +// } +// }); +// +// HashMap authorizationGrantHandlers = new HashMap<>(); +// authorizationGrantHandlers.put(grantType, grantHandler); +// +// mockOAuth2ServerConfiguration(authorizationGrantHandlers); +// } +// +// private IDTokenBuilder getMockIDTokenBuilderForSuccess() throws IdentityOAuth2Exception { +// +// IDTokenBuilder idTokenBuilder = mock(IDTokenBuilder.class); +// when(idTokenBuilder.buildIDToken(any(OAuthTokenReqMessageContext.class), any(OAuth2AccessTokenRespDTO.class))) +// .then(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocationOnMock) throws Throwable { +// +// return ID_TOKEN; +// } +// }); +// return idTokenBuilder; +// } +// +// private IDTokenBuilder getMockIDTokenBuilderForFailure() throws IdentityOAuth2Exception { +// +// IDTokenBuilder idTokenBuilder = mock(IDTokenBuilder.class); +// when(idTokenBuilder.buildIDToken(any(OAuthTokenReqMessageContext.class), any(OAuth2AccessTokenRespDTO.class))) +// .thenThrow(new IDTokenValidationFailureException("ID Token Validation failed")); +// return idTokenBuilder; +// } +// +// private void mockPasswordGrantHandler(boolean isAuthorizedClient, boolean isValidGrant, +// boolean isAuthorizedAccessDelegation, boolean isValidScope) +// throws IdentityOAuth2Exception { +// +// Map authzGrantHandlers = new Hashtable<>(); +// +// when(passwordGrantHandler.isOfTypeApplicationUser()).thenReturn(true); +// when(passwordGrantHandler.isAuthorizedClient(any(OAuthTokenReqMessageContext.class))) +// .thenReturn(isAuthorizedClient); +// when(passwordGrantHandler.validateGrant(any(OAuthTokenReqMessageContext.class))).thenReturn(isValidGrant); +// when(passwordGrantHandler.authorizeAccessDelegation(any(OAuthTokenReqMessageContext.class))) +// .thenReturn(isAuthorizedAccessDelegation); +// when(passwordGrantHandler.validateScope(any(OAuthTokenReqMessageContext.class))).thenReturn(isValidScope); +// when(passwordGrantHandler.issue(any(OAuthTokenReqMessageContext.class))) +// .thenReturn(new OAuth2AccessTokenRespDTO()); +// authzGrantHandlers.put("password", passwordGrantHandler); +// when(passwordGrantHandler.isConfidentialClient()).thenReturn(true); +// +// when(oAuthServerConfiguration.getSupportedGrantTypes()).thenReturn(authzGrantHandlers); +// } +} diff --git a/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtilTest.java b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtilTest.java new file mode 100644 index 00000000000..fcdc135c265 --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/test/java/org/wso2/carbon/identity/oauth2/util/OAuth2TokenUtilTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.identity.oauth2.util; + +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.event.IdentityEventException; +import org.wso2.carbon.identity.event.event.Event; +import org.wso2.carbon.identity.event.services.IdentityEventService; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.openidconnect.OIDCConstants; +import org.wso2.carbon.identity.openidconnect.internal.OpenIDConnectServiceComponentHolder; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mockStatic; + +/** + * Unit tests for OAuth2TokenUtil class. + */ +@Listeners(MockitoTestNGListener.class) +@WithCarbonHome +public class OAuth2TokenUtilTest { + + @Mock + private IdentityEventService identityEventService; + + @DataProvider + public static Object[][] postTokenDataProvider() { + + Map eventProperties = new HashMap<>(); + eventProperties.put(OIDCConstants.Event.TOKEN_ID, "12345"); + eventProperties.put(OIDCConstants.Event.USER_TYPE, "Bearer"); + eventProperties.put(OIDCConstants.Event.TENANT_DOMAIN, "carbon.super"); + eventProperties.put(OIDCConstants.Event.CLIENT_ID, "client123"); + eventProperties.put(OIDCConstants.Event.GRANT_TYPE, "client_credentials"); + eventProperties.put(OIDCConstants.Event.APP_RESIDENT_TENANT_ID, 1); + eventProperties.put(OIDCConstants.Event.ISSUED_TIME, "2023-10-01T12:00:00Z"); + eventProperties.put(OIDCConstants.Event.ACCESSING_ORGANIZATION_ID, "org123"); + + return new Object[][] { + { + eventProperties + } + }; + } + + @Test(dataProvider = "postTokenDataProvider") + public void testPostIssueToken(Map eventProperties) throws Exception { + + try ( + MockedStatic openIDConnectServiceComponentHolder + = mockStatic(OpenIDConnectServiceComponentHolder.class); + ) { + openIDConnectServiceComponentHolder.when(OpenIDConnectServiceComponentHolder::getIdentityEventService) + .thenReturn(identityEventService); + OAuth2TokenUtil.postIssueToken(eventProperties); + } + } + + @Test(dataProvider = "postTokenDataProvider") + public void testPostIssueTokenWithException(Map eventProperties) throws Exception { + + try ( + MockedStatic openIDConnectServiceComponentHolder + = mockStatic(OpenIDConnectServiceComponentHolder.class); + ) { + openIDConnectServiceComponentHolder.when(OpenIDConnectServiceComponentHolder::getIdentityEventService) + .thenReturn(identityEventService); + doThrow(new IdentityEventException("Error posting token issuance event")) + .when(identityEventService).handleEvent(any(Event.class)); + OAuth2TokenUtil.postIssueToken(eventProperties); + } catch (IdentityOAuth2Exception e) { + // Expected exception, test should pass. + Assert.assertEquals(e.getMessage(), "Error while invoking the request object " + + "persistence handler when issuing the access token id: " + + eventProperties.get(OIDCConstants.Event.TOKEN_ID)); + } + } +} 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 94781c2f5ac..50e699c83fd 100755 --- a/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml +++ b/components/org.wso2.carbon.identity.oauth/src/test/resources/testng.xml @@ -108,7 +108,8 @@ - + + @@ -188,7 +189,8 @@ - + +