diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenClientCredentialsGrantTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenClientCredentialsGrantTestCase.java index 0f26c5ea36e..57b3af4cb9f 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenClientCredentialsGrantTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenClientCredentialsGrantTestCase.java @@ -43,7 +43,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.wso2.carbon.automation.engine.context.TestUserMode; -import org.wso2.identity.integration.test.mocks.MockServer; +import org.wso2.identity.integration.test.actions.mockserver.ActionsMockServer; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.ActionModel; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.AuthenticationType; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.Endpoint; @@ -141,6 +141,7 @@ public class PreIssueAccessTokenClientCredentialsGrantTestCase extends ActionsBa private String userId; private String roleId; private JWTClaimsSet jwtClaims; + private ActionsMockServer actionsMockServer; /** * Initializes Test environment and sets up necessary configurations. @@ -187,7 +188,9 @@ protected boolean isRedirectable(String method) { addUserWithRole(applicationId, customScopes); - MockServer.createMockServer(MOCK_SERVER_ENDPOINT); + actionsMockServer = new ActionsMockServer(); + + actionsMockServer.createMockServer(MOCK_SERVER_ENDPOINT); actionId = createPreIssueAccessTokenAction(); } @@ -199,7 +202,7 @@ public void atEnd() throws Exception { deleteApp(applicationId); deleteDomainAPI(domainAPIId); scim2RestClient.deleteUser(userId); - MockServer.shutDownMockServer(); + actionsMockServer.shutDownMockServer(); restClient.closeHttpClient(); scim2RestClient.closeHttpClient(); actionsRestClient.closeHttpClient(); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenPasswordGrantTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenPasswordGrantTestCase.java index 10b7f3273ab..d3745d8a7e2 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenPasswordGrantTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/PreIssueAccessTokenPasswordGrantTestCase.java @@ -18,6 +18,7 @@ package org.wso2.identity.integration.test.actions; +import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import org.apache.commons.lang.ArrayUtils; @@ -41,9 +42,21 @@ import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.wso2.carbon.automation.engine.context.TestUserMode; -import org.wso2.identity.integration.test.mocks.MockServer; +import org.wso2.identity.integration.test.actions.mockserver.ActionsMockServer; +import org.wso2.identity.integration.test.actions.model.AccessToken; +import org.wso2.identity.integration.test.actions.model.ActionType; +import org.wso2.identity.integration.test.actions.model.AllowedOperation; +import org.wso2.identity.integration.test.actions.model.Operation; +import org.wso2.identity.integration.test.actions.model.PreIssueAccessTokenActionRequest; +import org.wso2.identity.integration.test.actions.model.PreIssueAccessTokenEvent; +import org.wso2.identity.integration.test.actions.model.Tenant; +import org.wso2.identity.integration.test.actions.model.TokenRequest; +import org.wso2.identity.integration.test.actions.model.User; +import org.wso2.identity.integration.test.actions.model.UserStore; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.ActionModel; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.AuthenticationType; import org.wso2.identity.integration.test.rest.api.server.action.management.v1.model.Endpoint; @@ -60,19 +73,22 @@ import org.wso2.identity.integration.test.rest.api.user.common.model.UserObject; import org.wso2.identity.integration.test.restclients.SCIM2RestClient; import org.wso2.identity.integration.test.utils.CarbonUtils; +import org.wso2.identity.integration.test.utils.FileUtils; import org.wso2.identity.integration.test.utils.OAuth2Constant; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.wso2.identity.integration.test.utils.OAuth2Constant.ACCESS_TOKEN_ENDPOINT; @@ -99,20 +115,11 @@ public class PreIssueAccessTokenPasswordGrantTestCase extends ActionsBaseTestCas private static final String PASSWORD_GRANT_TYPE = "password"; private static final String APPLICATION_AUDIENCE = "APPLICATION"; private static final String TEST_ROLE_APPLICATION = "test_role_application"; - - private static final String INTERNAL_ACTION_MANAGEMENT_VIEW = "internal_action_mgt_view"; - private static final String INTERNAL_ACTION_MANAGEMENT_CREATE = "internal_action_mgt_create"; - private static final String INTERNAL_ACTION_MANAGEMENT_UPDATE = "internal_action_mgt_update"; - private static final String INTERNAL_ACTION_MANAGEMENT_DELETE = "internal_action_mgt_delete"; private static final String INTERNAL_ORG_USER_MANAGEMENT_LIST = "internal_org_user_mgt_list"; private static final String INTERNAL_ORG_USER_MANAGEMENT_VIEW = "internal_org_user_mgt_view"; private static final String INTERNAL_ORG_USER_MANAGEMENT_CREATE = "internal_org_user_mgt_create"; private static final String INTERNAL_ORG_USER_MANAGEMENT_UPDATE = "internal_org_user_mgt_update"; private static final String INTERNAL_ORG_USER_MANAGEMENT_DELETE = "internal_org_user_mgt_delete"; - private static final String INTERNAL_APPLICATION_MANAGEMENT_VIEW = "internal_application_mgt_view"; - private static final String INTERNAL_APPLICATION_MANAGEMENT_UPDATE = "internal_application_mgt_update"; - private static final String INTERNAL_API_RESOURCE_VIEW = "internal_api_resource_view"; - private static final String INTERNAL_API_RESOURCE_CREATE = "internal_api_resource_create"; private static final String CUSTOM_SCOPE_1 = "test_custom_scope_1"; private static final String CUSTOM_SCOPE_2 = "test_custom_scope_2"; private static final String CUSTOM_SCOPE_3 = "test_custom_scope_3"; @@ -122,24 +129,49 @@ public class PreIssueAccessTokenPasswordGrantTestCase extends ActionsBaseTestCas private static final String NEW_SCOPE_4 = "replaced_scope"; private static final String SCIM2_USERS_API = "/o/scim2/Users"; - private static final String ACTIONS_API = "/api/server/v1/actions"; - private static final String APPLICATION_MANAGEMENT_API = "/api/server/v1/applications"; - private static final String API_RESOURCE_MANAGEMENT_API = "/api/server/v1/api-resources"; - private static final String MOCK_SERVER_ENDPOINT = "/test/action"; - protected SCIM2RestClient scim2RestClient; + private static final String CLAIMS_PATH_PREFIX = "/accessToken/claims/"; + private static final String SCOPES_PATH_PREFIX = "/accessToken/scopes/"; + private static final String MOCK_SERVER_ENDPOINT_RESOURCE_PATH = "/test/action"; + private static final int UPDATED_EXPIRY_TIME_PERIOD = 7200; + private static final int CURRENT_EXPIRY_TIME_PERIOD = 3600; + private static final String MOCK_SERVER_AUTH_BASIC_USERNAME = "test"; + private static final String MOCK_SERVER_AUTH_BASIC_PASSWORD = "test"; + private SCIM2RestClient scim2RestClient; private Lookup cookieSpecRegistry; private RequestConfig requestConfig; private CloseableHttpClient client; private List customScopes; + private List requestedScopes; private String accessToken; private String clientId; private String clientSecret; + private String subjectType; + private String tokenType; private String actionId; private String applicationId; private String domainAPIId; private String userId; private String roleId; + private String tenantId; private JWTClaimsSet jwtClaims; + private TestUserMode userMode; + private ActionsMockServer actionsMockServer; + + @Factory(dataProvider = "testExecutionContextProvider") + public PreIssueAccessTokenPasswordGrantTestCase(TestUserMode testUserMode) { + + this.userMode = testUserMode; + this.tenantId = testUserMode == TestUserMode.SUPER_TENANT_USER ? "-1234" : "1"; + } + + @DataProvider(name = "testExecutionContextProvider") + public static Object[][] getTestExecutionContext() { + + return new Object[][]{ + {TestUserMode.SUPER_TENANT_USER}, + {TestUserMode.TENANT_USER} + }; + } /** * Initializes Test environment and sets up necessary configurations. @@ -149,7 +181,7 @@ public class PreIssueAccessTokenPasswordGrantTestCase extends ActionsBaseTestCas @BeforeClass(alwaysRun = true) public void testInit() throws Exception { - super.init(TestUserMode.TENANT_USER); + super.init(userMode); cookieSpecRegistry = RegistryBuilder.create() .register(CookieSpecs.DEFAULT, new RFC6265CookieSpecProvider()) @@ -177,32 +209,51 @@ protected boolean isRedirectable(String method) { OpenIDConnectConfiguration oidcConfig = getOIDCInboundDetailsOfApplication(applicationId); clientId = oidcConfig.getClientId(); clientSecret = oidcConfig.getClientSecret(); + subjectType = oidcConfig.getSubject().getSubjectType(); + tokenType = oidcConfig.getAccessToken().getType(); + if (!CarbonUtils.isLegacyAuthzRuntimeEnabled()) { - authorizeSystemAPIs(applicationId, new ArrayList<>(Arrays.asList(SCIM2_USERS_API, ACTIONS_API, - APPLICATION_MANAGEMENT_API, API_RESOURCE_MANAGEMENT_API))); + authorizeSystemAPIs(applicationId, Collections.singletonList(SCIM2_USERS_API)); } domainAPIId = createDomainAPI(EXTERNAL_SERVICE_NAME, EXTERNAL_SERVICE_URI, customScopes); authorizeDomainAPIs(applicationId, domainAPIId, customScopes); - addUserWithRole(applicationId, customScopes); - MockServer.createMockServer(MOCK_SERVER_ENDPOINT); + requestedScopes = new ArrayList<>(); + Collections.addAll(requestedScopes, + INTERNAL_ORG_USER_MANAGEMENT_LIST, + INTERNAL_ORG_USER_MANAGEMENT_VIEW, + INTERNAL_ORG_USER_MANAGEMENT_CREATE, + INTERNAL_ORG_USER_MANAGEMENT_UPDATE, + INTERNAL_ORG_USER_MANAGEMENT_DELETE); + requestedScopes.addAll(customScopes); + actionId = createPreIssueAccessTokenAction(); + + actionsMockServer = new ActionsMockServer(); + actionsMockServer.startServer(); + actionsMockServer.setupStub(MOCK_SERVER_ENDPOINT_RESOURCE_PATH, + "Basic " + getBase64EncodedString(MOCK_SERVER_AUTH_BASIC_USERNAME, MOCK_SERVER_AUTH_BASIC_PASSWORD), + FileUtils.readFileInClassPathAsString("actions/response/pre-issue-access-token-response.json")); } @AfterClass(alwaysRun = true) public void atEnd() throws Exception { + actionsMockServer.stopServer(); + deleteAction(PRE_ISSUE_ACCESS_TOKEN_API_PATH, actionId); deleteRole(roleId); deleteApp(applicationId); deleteDomainAPI(domainAPIId); scim2RestClient.deleteUser(userId); - MockServer.shutDownMockServer(); + restClient.closeHttpClient(); scim2RestClient.closeHttpClient(); actionsRestClient.closeHttpClient(); client.close(); + + actionsMockServer = null; accessToken = null; jwtClaims = null; } @@ -215,19 +266,7 @@ public void testGetAccessTokenWithPasswordGrant() throws Exception { parameters.add(new BasicNameValuePair("username", TEST_USER)); parameters.add(new BasicNameValuePair("password", ADMIN_WSO2)); - List permissions = new ArrayList<>(); - Collections.addAll(permissions, - INTERNAL_ORG_USER_MANAGEMENT_LIST, - INTERNAL_ORG_USER_MANAGEMENT_VIEW, - INTERNAL_ORG_USER_MANAGEMENT_CREATE, - INTERNAL_ORG_USER_MANAGEMENT_UPDATE, - INTERNAL_ORG_USER_MANAGEMENT_DELETE - ); - permissions.addAll(customScopes); - - String scopes = permissions.stream() - .map(String::toLowerCase) - .collect(Collectors.joining(" ")); + String scopes = String.join(" ", requestedScopes); parameters.add(new BasicNameValuePair("scope", scopes)); List
headers = new ArrayList<>(); @@ -250,7 +289,21 @@ public void testGetAccessTokenWithPasswordGrant() throws Exception { assertNotNull(jwtClaims); } - @Test(groups = "wso2.is", description = "Verify the presence of the updated scopes in the access token") + @Test(groups = "wso2.is", dependsOnMethods = "testGetAccessTokenWithPasswordGrant", description = + "Verify the pre issue access token action request") + public void testPreIssueAccessTokenActionRequest() throws Exception { + + String actualRequestPayload = actionsMockServer.getReceivedRequestPayload(MOCK_SERVER_ENDPOINT_RESOURCE_PATH); + PreIssueAccessTokenActionRequest actualRequest = + new ObjectMapper().readValue(actualRequestPayload, PreIssueAccessTokenActionRequest.class); + + PreIssueAccessTokenActionRequest expectedRequest = getRequest(); + + assertEquals(actualRequest, expectedRequest); + } + + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the updated scopes in the access token") public void testTokenScopeOperations() throws Exception { String[] scopes = jwtClaims.getStringClaim("scope").split("\\s+"); @@ -263,7 +316,8 @@ public void testTokenScopeOperations() throws Exception { Assert.assertFalse(ArrayUtils.contains(scopes, CUSTOM_SCOPE_2)); } - @Test(groups = "wso2.is", description = "Verify the presence of the updated aud claims in the access token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the updated aud claims in the access token") public void testTokenAUDClaimOperations() throws Exception { String[] audValueArray = jwtClaims.getStringArrayClaim("aud"); @@ -275,34 +329,33 @@ public void testTokenAUDClaimOperations() throws Exception { Assert.assertFalse(ArrayUtils.contains(audValueArray, clientId)); } - @Test(groups = "wso2.is", description = "Verify the presence of the specified custom string claim in the access " + - "token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the specified custom string claim in the access token") public void testTokenStringClaimAddOperation() throws Exception { String claimStr = jwtClaims.getStringClaim("custom_claim_string_1"); Assert.assertEquals(claimStr, "testCustomClaim1"); - } - @Test(groups = "wso2.is", description = "Verify the presence of the specified custom number claim in the access " + - "token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the specified custom number claim in the access token") public void testTokenNumberClaimAddOperation() throws Exception { Number claimValue = jwtClaims.getIntegerClaim("custom_claim_number_1"); Assert.assertEquals(claimValue, 78); - } - @Test(groups = "wso2.is", description = "Verify the presence of the specified custom boolean claim in the access " + - "token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the specified custom boolean claim in the access " + + "token") public void testTokenBooleanClaimAddOperation() throws Exception { Boolean claimValue = jwtClaims.getBooleanClaim("custom_claim_boolean_1"); Assert.assertTrue(claimValue); } - @Test(groups = "wso2.is", description = "Verify the presence of the specified custom string array claim in the " + - "access token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the presence of the specified custom string array claim in the access token") public void testTokenStringArrayClaimAddOperation() throws Exception { @@ -312,14 +365,88 @@ public void testTokenStringArrayClaimAddOperation() Assert.assertEquals(claimArray, claimArray1); } - @Test(groups = "wso2.is", description = "Verify the replacement of the 'expires_in' claim in the access token") + @Test(groups = "wso2.is", dependsOnMethods = "testPreIssueAccessTokenActionRequest", description = + "Verify the replacement of the 'expires_in' claim in the access token") public void testTokenExpiresInClaimReplaceOperation() throws Exception { Date exp = jwtClaims.getDateClaim("exp"); Date iat = jwtClaims.getDateClaim("iat"); long expiresIn = (exp.getTime() - iat.getTime()) / 1000; - Assert.assertEquals(expiresIn, 7200); + Assert.assertEquals(expiresIn, UPDATED_EXPIRY_TIME_PERIOD); + } + + private PreIssueAccessTokenActionRequest getRequest() { + + TokenRequest tokenRequest = createTokenRequest(); + AccessToken accessTokenInRequest = createAccessToken(); + + Tenant tenant = new Tenant(tenantId, tenantInfo.getDomain()); + User user = new User(userId); + UserStore userStore = + new UserStore(Base64.getEncoder().encodeToString("PRIMARY".getBytes(StandardCharsets.UTF_8)), + "PRIMARY"); + + PreIssueAccessTokenEvent event = new PreIssueAccessTokenEvent.Builder() + .request(tokenRequest) + .accessToken(accessTokenInRequest) + .tenant(tenant) + .organization(null) + .user(user) + .userStore(userStore) + .build(); + + List allowedOperations = Arrays.asList( + createAllowedOperation(Operation.ADD, Arrays.asList(CLAIMS_PATH_PREFIX, SCOPES_PATH_PREFIX, + CLAIMS_PATH_PREFIX + AccessToken.ClaimNames.AUD.getName() + "/")), + createAllowedOperation(Operation.REMOVE, Arrays.asList(SCOPES_PATH_PREFIX, + CLAIMS_PATH_PREFIX + AccessToken.ClaimNames.AUD.getName() + "/")), + createAllowedOperation(Operation.REPLACE, Arrays.asList(SCOPES_PATH_PREFIX, + CLAIMS_PATH_PREFIX + AccessToken.ClaimNames.AUD.getName() + "/", + CLAIMS_PATH_PREFIX + AccessToken.ClaimNames.EXPIRES_IN.getName())) + ); + + return new PreIssueAccessTokenActionRequest.Builder() + .actionType(ActionType.PRE_ISSUE_ACCESS_TOKEN) + .event(event) + .allowedOperations(allowedOperations) + .build(); + } + + private TokenRequest createTokenRequest() { + + return new TokenRequest.Builder() + .grantType(PASSWORD_GRANT_TYPE) + .scopes(requestedScopes) + .clientId(clientId) + .build(); + } + + private AccessToken createAccessToken() { + + List claims = new ArrayList<>(); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.ISS.getName(), + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain()))); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.CLIENT_ID.getName(), clientId)); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.AUTHORIZED_USER_TYPE.getName(), "APPLICATION_USER")); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.EXPIRES_IN.getName(), CURRENT_EXPIRY_TIME_PERIOD)); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.AUD.getName(), Collections.singletonList(clientId))); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.SUBJECT_TYPE.getName(), subjectType)); + claims.add(new AccessToken.Claim(AccessToken.ClaimNames.SUB.getName(), userId)); + + return new AccessToken.Builder() + .tokenType(tokenType) + .claims(claims) + .scopes(requestedScopes) + .build(); + } + + private AllowedOperation createAllowedOperation(Operation op, List paths) { + + AllowedOperation operation = new AllowedOperation(); + operation.setOp(op); + operation.setPaths(new ArrayList<>(paths)); + return operation; } /** @@ -328,10 +455,10 @@ public void testTokenExpiresInClaimReplaceOperation() throws Exception { private String createPreIssueAccessTokenAction() { AuthenticationType authenticationType = new AuthenticationType(); - authenticationType.setType(AuthenticationType.TypeEnum.BASIC); // todo handle mock server authorization + authenticationType.setType(AuthenticationType.TypeEnum.BASIC); Map authProperties = new HashMap<>(); - authProperties.put(USERNAME_PROPERTY, TEST_USER); - authProperties.put(PASSWORD_PROPERTY, ADMIN_WSO2); + authProperties.put(USERNAME_PROPERTY, MOCK_SERVER_AUTH_BASIC_USERNAME); + authProperties.put(PASSWORD_PROPERTY, MOCK_SERVER_AUTH_BASIC_PASSWORD); authenticationType.setProperties(authProperties); Endpoint endpoint = new Endpoint(); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/mocks/MockServer.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/mockserver/ActionsMockServer.java similarity index 72% rename from modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/mocks/MockServer.java rename to modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/mockserver/ActionsMockServer.java index 6717928b02b..d5b34470f24 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/mocks/MockServer.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/mockserver/ActionsMockServer.java @@ -1,11 +1,37 @@ -package org.wso2.identity.integration.test.mocks; +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.mockserver; import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder; +import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import org.apache.commons.lang.StringUtils; + +import java.util.List; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; @@ -14,16 +40,49 @@ * This class starts a mock server on a specified port and sets up predefined * responses for POST requests to simulate various operations relation to action execution. */ -public class MockServer { +public class ActionsMockServer { + + private WireMockServer wireMockServer; + + public void startServer() { - private static WireMockServer wireMockServer; + wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().port(8587)); + wireMockServer.start(); + } + + public void stopServer() { + + if (wireMockServer != null && wireMockServer.isRunning()) { + wireMockServer.stop(); + } + } + + public void setupStub(String url, String authMethod, String responseBody) { + + wireMockServer.stubFor(post(urlEqualTo(url)) + .withHeader("Authorization", matching(authMethod)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBody(responseBody))); + } + + public String getReceivedRequestPayload(String url) { + + List requestList = wireMockServer.findAll(postRequestedFor(urlEqualTo(url))); + if (requestList == null || requestList.isEmpty()) { + return StringUtils.EMPTY; + } + + return requestList.get(0).getBodyAsString(); + } /** * Create a mock server with wiremock. * * @throws Exception If an error occurred while creating the server */ - public static void createMockServer(String mockEndpoint) throws Exception { + public void createMockServer(String mockEndpoint) throws Exception { wireMockServer = new WireMockServer(wireMockConfig().port(8587)); @@ -142,7 +201,7 @@ public static void createMockServer(String mockEndpoint) throws Exception { /** * Shut down the wiremock server instance. */ - public static void shutDownMockServer() { + public void shutDownMockServer() { wireMockServer.stop(); } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AccessToken.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AccessToken.java new file mode 100644 index 00000000000..e4477777bcc --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AccessToken.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * This class represents the model of the access token sent in the request payload + * to the API endpoint of the pre issue access token action. + */ +@JsonDeserialize(builder = AccessToken.Builder.class) +public class AccessToken { + + private final String tokenType; + List scopes; + List claims; + + private AccessToken(Builder builder) { + + this.tokenType = builder.tokenType; + this.scopes = builder.scopes; + this.claims = builder.claims; + } + + public String getTokenType() { + + return tokenType; + } + + public List getScopes() { + + return scopes; + } + + public List getClaims() { + + return claims; + } + + public Claim getClaim(String name) { + + if (claims != null) { + for (Claim claim : claims) { + if (claim.getName().equals(name)) { + return claim; + } + } + } + + return null; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AccessToken that = (AccessToken) o; + return Objects.equals(tokenType, that.tokenType) && (scopes == null ? that.scopes == null : + scopes.size() == that.scopes.size() && scopes.containsAll(that.scopes)) && + (claims == null ? that.claims == null : + claims.size() == that.claims.size() && claims.containsAll(that.claims)); + } + + @Override + public int hashCode() { + + return Objects.hash(tokenType, scopes, claims); + } + + /** + * Enum for standard claim names. + */ + public enum ClaimNames { + + SUB("sub"), + ISS("iss"), + AUD("aud"), + CLIENT_ID("client_id"), + AUTHORIZED_USER_TYPE("aut"), + EXPIRES_IN("expires_in"), + + TOKEN_BINDING_REF("binding_ref"), + TOKEN_BINDING_TYPE("binding_type"), + SUBJECT_TYPE("subject_type"); + + private final String name; + + ClaimNames(String name) { + + this.name = name; + } + + public static boolean contains(String name) { + + return Arrays.stream(ClaimNames.values()) + .anyMatch(claimName -> claimName.name.equals(name)); + } + + public String getName() { + + return name; + } + } + + /** + * Model class for claims. + */ + public static class Claim { + + private String name; + private Object value; + + public Claim() { + + } + + public Claim(String name, Object value) { + + this.name = name; + this.value = value; + } + + public String getName() { + + return name; + } + + public void setName(String name) { + + this.name = name; + } + + public Object getValue() { + + return value; + } + + public void setValue(Object value) { + + this.value = value; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Claim claim = (Claim) o; + return Objects.equals(name, claim.name) && Objects.equals(value, claim.value); + } + + @Override + public int hashCode() { + + return Objects.hash(name, value); + } + } + + /** + * Builder for AccessToken. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + + private String tokenType; + private List scopes = new ArrayList<>(); + private List claims = new ArrayList<>(); + + public Builder tokenType(String tokenType) { + + this.tokenType = tokenType; + return this; + } + + public Builder scopes(List scopes) { + + this.scopes = scopes; + return this; + } + + public Builder claims(List claims) { + + this.claims = claims; + return this; + } + + public Builder addClaim(String name, Object value) { + + this.claims.add(new Claim(name, value)); + return this; + } + + public Builder addScope(String scope) { + + this.scopes.add(scope); + return this; + } + + public String getTokenType() { + + return tokenType; + } + + public List getScopes() { + + return scopes; + } + + public List getClaims() { + + return claims; + } + + public Claim getClaim(String name) { + + if (claims != null) { + for (Claim claim : claims) { + if (claim.getName().equals(name)) { + return claim; + } + } + } + + return null; + } + + public AccessToken build() { + + return new AccessToken(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/ActionType.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/ActionType.java new file mode 100644 index 00000000000..94c7cb8fb45 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/ActionType.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +/** + * This class models the Action Type. + */ +public enum ActionType { + PRE_ISSUE_ACCESS_TOKEN, +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AllowedOperation.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AllowedOperation.java new file mode 100644 index 00000000000..ac7df1d46aa --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/AllowedOperation.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.List; +import java.util.Objects; + +/** + * This class models the Allowed Operation sent in the request payload to the API endpoint of a particular action. + */ +public class AllowedOperation { + + private Operation op; + + private List paths; + + public Operation getOp() { + + return op; + } + + public void setOp(Operation op) { + + this.op = op; + } + + public List getPaths() { + + return paths; + } + + public void setPaths(List paths) { + + this.paths = paths; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AllowedOperation that = (AllowedOperation) o; + return op == that.op && + Objects.equals(paths, that.paths); + } + + @Override + public int hashCode() { + + return Objects.hash(op, paths); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Application.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Application.java new file mode 100644 index 00000000000..81e78cb4700 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Application.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Objects; + +/** + * This class models the Application sent in the request payload to the API endpoint of a particular action. + */ +public class Application { + + private String id; + private String name; + + public Application(String id, String name) { + + this.id = id; + this.name = name; + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + + return name; + } + + public void setName(String name) { + + this.name = name; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Application that = (Application) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + + return Objects.hash(id, name); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Event.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Event.java new file mode 100644 index 00000000000..327393e177d --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Event.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +/** + * This class models the common properties of the Event sent in the request payload to the API endpoint of a particular action. + */ +public class Event { + + protected Tenant tenant; + protected Organization organization; + protected User user; + protected UserStore userStore; + protected Application application; + + public Tenant getTenant() { + + return tenant; + } + + public Organization getOrganization() { + + return organization; + } + + public User getUser() { + + return user; + } + + public UserStore getUserStore() { + + return userStore; + } + + public Application getApplication() { + + return application; + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Operation.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Operation.java new file mode 100644 index 00000000000..c0f70c7c8f8 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Operation.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * This class models the Operation types allowed. + */ +public enum Operation { + + ADD("add"), + REMOVE("remove"), + REPLACE("replace"), + REDIRECT("redirect"); + + private final String value; + + Operation(String value) { + + this.value = value; + } + + @JsonCreator + public static Operation forValue(String value) { + + for (Operation op : Operation.values()) { + if (op.getValue().equals(value)) { + return op; + } + } + throw new IllegalArgumentException("Invalid operation value: " + value); + } + + @JsonValue + public String getValue() { + + return value; + } +} + diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Organization.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Organization.java new file mode 100644 index 00000000000..0e8d4a9a747 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Organization.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Objects; + +/** + * This class models the Organization sent in the request payload to the API endpoint of a particular action. + */ +public class Organization { + + private String id; + + private String name; + + public Organization(String id, String name) { + + this.id = id; + this.name = name; + } + + public Organization() { + + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + + return name; + } + + public void setName(String name) { + + this.name = name; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Organization that = (Organization) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + + return Objects.hash(id, name); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenActionRequest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenActionRequest.java new file mode 100644 index 00000000000..f3df3425c1b --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenActionRequest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +import java.util.List; +import java.util.Objects; + +/** + * This class represents the model of the pre issue access token action request sent in the request payload + * to the API endpoint of the pre issue access token action. + */ +@JsonDeserialize(builder = PreIssueAccessTokenActionRequest.Builder.class) +public class PreIssueAccessTokenActionRequest { + + private final ActionType actionType; + private final String flowId; + private final String requestId; + private final PreIssueAccessTokenEvent event; + private final List allowedOperations; + + public PreIssueAccessTokenActionRequest(Builder builder) { + + this.actionType = builder.actionType; + this.flowId = builder.flowId; + this.requestId = builder.requestId; + this.event = builder.event; + this.allowedOperations = builder.allowedOperations; + } + + public ActionType getActionType() { + + return actionType; + } + + public String getFlowId() { + + return flowId; + } + + public String getRequestId() { + + return requestId; + } + + public PreIssueAccessTokenEvent getEvent() { + + return event; + } + + public List getAllowedOperations() { + + return allowedOperations; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PreIssueAccessTokenActionRequest that = (PreIssueAccessTokenActionRequest) o; + return actionType == that.actionType && + Objects.equals(event, that.event) && + Objects.equals(allowedOperations, that.allowedOperations); + } + + @Override + public int hashCode() { + + return Objects.hash(actionType, event, allowedOperations); + } + + /** + * Builder for the {@link PreIssueAccessTokenActionRequest}. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + + private ActionType actionType; + private String flowId; + private String requestId; + private PreIssueAccessTokenEvent event; + private List allowedOperations; + + public Builder actionType(ActionType actionType) { + + this.actionType = actionType; + return this; + } + + public Builder flowId(String flowId) { + + this.flowId = flowId; + return this; + } + + public Builder requestId(String requestId) { + + this.requestId = requestId; + return this; + } + + public Builder event(PreIssueAccessTokenEvent event) { + + this.event = event; + return this; + } + + public Builder allowedOperations(List allowedOperations) { + + this.allowedOperations = allowedOperations; + return this; + } + + public PreIssueAccessTokenActionRequest build() { + + return new PreIssueAccessTokenActionRequest(this); + } + } +} + diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenEvent.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenEvent.java new file mode 100644 index 00000000000..e293edf1d66 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/PreIssueAccessTokenEvent.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +import java.util.Objects; + +/** + * This class models the Event sent in the request payload to the API endpoint of a pre issue access token action. + */ +@JsonDeserialize(builder = PreIssueAccessTokenEvent.Builder.class) +public class PreIssueAccessTokenEvent extends Event { + + private TokenRequest request; + private final AccessToken accessToken; + + private PreIssueAccessTokenEvent(Builder builder) { + + this.accessToken = builder.accessToken; + this.request = builder.request; + this.organization = builder.organization; + this.tenant = builder.tenant; + this.user = builder.user; + this.userStore = builder.userStore; + } + + public TokenRequest getRequest() { + + return request; + } + + public AccessToken getAccessToken() { + + return accessToken; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PreIssueAccessTokenEvent that = (PreIssueAccessTokenEvent) o; + return Objects.equals(request, that.request) && + Objects.equals(accessToken, that.accessToken) && + Objects.equals(tenant, that.tenant) && + Objects.equals(user, that.user) && + Objects.equals(userStore, that.userStore); + } + + @Override + public int hashCode() { + + return Objects.hash(request, accessToken, tenant, user, userStore); + } + + /** + * Builder for the PreIssueAccessTokenEvent. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + + private AccessToken accessToken; + private TokenRequest request; + private Organization organization; + private Tenant tenant; + private User user; + + private UserStore userStore; + + public Builder accessToken(AccessToken accessToken) { + + this.accessToken = accessToken; + return this; + } + + public Builder request(TokenRequest request) { + + this.request = request; + return this; + } + + public Builder organization(Organization organization) { + + this.organization = organization; + return this; + } + + public Builder tenant(Tenant tenant) { + + this.tenant = tenant; + return this; + } + + public Builder user(User user) { + + this.user = user; + return this; + } + + public Builder userStore(UserStore userStore) { + + this.userStore = userStore; + return this; + } + + public PreIssueAccessTokenEvent build() { + + return new PreIssueAccessTokenEvent(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Request.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Request.java new file mode 100644 index 00000000000..282cc052ab0 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Request.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * This class models the common properties of the Request that is sent in the request payload + * to the API endpoint of a particular action. + */ +public class Request { + + protected Map additionalHeaders = new HashMap<>(); + protected Map additionalParams = new HashMap<>(); + + public Map getAdditionalHeaders() { + + return additionalHeaders != null ? Collections.unmodifiableMap(additionalHeaders) : Collections.emptyMap(); + } + + public void setAdditionalHeaders(Map additionalHeaders) { + + this.additionalHeaders = additionalHeaders; + } + + public Map getAdditionalParams() { + + return additionalParams != null ? Collections.unmodifiableMap(additionalParams) : Collections.emptyMap(); + } + + public void setAdditionalParams(Map additionalParams) { + + this.additionalParams = additionalParams; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Request request = (Request) o; + return Objects.equals(additionalHeaders, request.additionalHeaders) && + Objects.equals(additionalParams, request.additionalParams); + } + + @Override + public int hashCode() { + + return Objects.hash(additionalHeaders, additionalParams); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Tenant.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Tenant.java new file mode 100644 index 00000000000..d5c29bd5e52 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/Tenant.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Objects; + +/** + * This class models the Tenant sent in the request payload to the API endpoint of a particular action. + */ +public class Tenant { + + private String id; + private String name; + + public Tenant(String id, String name) { + + this.id = id; + this.name = name; + } + + public Tenant() { + + } + + public String getId() { + + return id; + } + + public String getName() { + + return name; + } + + public void setId(String id) { + + this.id = id; + } + + public void setName(String name) { + + this.name = name; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Tenant tenant = (Tenant) o; + return Objects.equals(id, tenant.id) && Objects.equals(name, tenant.name); + } + + @Override + public int hashCode() { + + return Objects.hash(id, name); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/TokenRequest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/TokenRequest.java new file mode 100644 index 00000000000..29c16fd39b9 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/TokenRequest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * This class models the request in the request payload to the API endpoint of a pre issue access token action. + */ +@JsonDeserialize(builder = TokenRequest.Builder.class) +public class TokenRequest extends Request { + + private final String clientId; + private final String grantType; + private final String redirectUri; + private final List scopes; + + private TokenRequest(Builder builder) { + + this.clientId = builder.clientId; + this.grantType = builder.grantType; + this.redirectUri = builder.redirectUri; + this.scopes = builder.scopes; + this.additionalHeaders = builder.additionalHeaders; + this.additionalParams = builder.additionalParams; + } + + public String getClientId() { + + return clientId; + } + + public String getGrantType() { + + return grantType; + } + + public String getRedirectUri() { + + return redirectUri; + } + + public List getScopes() { + + return scopes; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; // Call superclass equals method + TokenRequest that = (TokenRequest) o; + return Objects.equals(clientId, that.clientId) && Objects.equals(grantType, that.grantType) && + Objects.equals(redirectUri, that.redirectUri) && (scopes == null ? that.scopes == null : + scopes.size() == that.scopes.size() && scopes.containsAll(that.scopes)); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), clientId, grantType, redirectUri, scopes); + } + + /** + * Builder for TokenRequest. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + + private final Map additionalHeaders = new HashMap<>(); + private final Map additionalParams = new HashMap<>(); + private String clientId; + private String grantType; + private String redirectUri; + private List scopes = new ArrayList<>(); + + public Builder clientId(String clientId) { + + this.clientId = clientId; + return this; + } + + public Builder grantType(String grantType) { + + this.grantType = grantType; + return this; + } + + public Builder redirectUri(String redirectUri) { + + this.redirectUri = redirectUri; + return this; + } + + public Builder scopes(List scopes) { + + this.scopes = scopes; + return this; + } + + public Builder addAdditionalHeader(String key, String[] value) { + + this.additionalHeaders.put(key, value); + return this; + } + + public Builder addAdditionalParam(String key, String[] value) { + + this.additionalParams.put(key, value); + return this; + } + + public TokenRequest build() { + + return new TokenRequest(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/User.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/User.java new file mode 100644 index 00000000000..186b38211d2 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/User.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Objects; + +/** + * This class models the User sent in the request payload to the API endpoint of a particular action. + */ +public class User { + + private String id; + + public User(String id) { + + this.id = id; + } + + public User() { + + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id); + } + + @Override + public int hashCode() { + + return Objects.hash(id); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/UserStore.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/UserStore.java new file mode 100644 index 00000000000..9c4c7339c28 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/actions/model/UserStore.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.actions.model; + +import java.util.Objects; + +/** + * This class models the UserStore sent in the request payload to the API endpoint of a particular action. + */ +public class UserStore { + + private String id; + private String name; + + public UserStore(String id, String name) { + + this.id = id; + this.name = name; + } + + public UserStore() { + + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + + return name; + } + + public void setName(String name) { + + this.name = name; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UserStore userStore = (UserStore) o; + return Objects.equals(id, userStore.id) && Objects.equals(name, userStore.name); + } + + @Override + public int hashCode() { + + return Objects.hash(id, name); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/utils/FileUtils.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/utils/FileUtils.java new file mode 100644 index 00000000000..b2ea30b8b03 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/utils/FileUtils.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.identity.integration.test.utils; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Objects; + +/** + * Utility class for file operations. + */ +public class FileUtils { + + public static String readFileAsString(String filePath) throws IOException { + + return new String(Files.readAllBytes(Paths.get(filePath))); + } + + public static String readFileInClassPathAsString(String path) throws IOException, URISyntaxException { + + ClassLoader classLoader = FileUtils.class.getClassLoader(); + URI fileUri = Objects.requireNonNull(classLoader.getResource(path)).toURI(); + return new String(Files.readAllBytes(Paths.get(fileUri))); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/actions/response/pre-issue-access-token-response.json b/modules/integration/tests-integration/tests-backend/src/test/resources/actions/response/pre-issue-access-token-response.json new file mode 100644 index 00000000000..e2feae3bd65 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/actions/response/pre-issue-access-token-response.json @@ -0,0 +1,94 @@ +{ + "actionStatus": "SUCCESS", + "operations": [ + { + "op": "add", + "path": "/accessToken/scopes/-", + "value": "new_test_custom_scope_1" + }, + { + "op": "add", + "path": "/accessToken/scopes/-", + "value": "new_test_custom_scope_2" + }, + { + "op": "add", + "path": "/accessToken/scopes/-", + "value": "new_test_custom_scope_3" + }, + { + "op": "add", + "path": "/accessToken/claims/aud/-", + "value": "zzz1.com" + }, + { + "op": "add", + "path": "/accessToken/claims/aud/-", + "value": "zzz2.com" + }, + { + "op": "add", + "path": "/accessToken/claims/aud/-", + "value": "zzz3.com" + }, + { + "op": "add", + "path": "/accessToken/claims/-", + "value": { + "name": "custom_claim_string_1", + "value": "testCustomClaim1" + } + }, + { + "op": "add", + "path": "/accessToken/claims/-", + "value": { + "name": "custom_claim_number_1", + "value": 78 + } + }, + { + "op": "add", + "path": "/accessToken/claims/-", + "value": { + "name": "custom_claim_boolean_1", + "value": true + } + }, + { + "op": "add", + "path": "/accessToken/claims/-", + "value": { + "name": "custom_claim_string_array_1", + "value": [ + "TestCustomClaim1", + "TestCustomClaim2", + "TestCustomClaim3" + ] + } + }, + { + "op": "replace", + "path": "/accessToken/scopes/7", + "value": "replaced_scope" + }, + { + "op": "replace", + "path": "/accessToken/claims/aud/-", + "value": "zzzR.com" + }, + { + "op": "replace", + "path": "/accessToken/claims/expires_in", + "value": 7200 + }, + { + "op": "remove", + "path": "/accessToken/scopes/6" + }, + { + "op": "remove", + "path": "/accessToken/claims/aud/-" + } + ] +} \ No newline at end of file