From 47ea880de42cfc0e582b2f3a6d384fb8ea2bbab1 Mon Sep 17 00:00:00 2001 From: malithie Date: Wed, 4 Sep 2024 02:54:09 +0530 Subject: [PATCH] Add code grant test case for JWT tokens. --- ...uthorizationCodeGrantJWTTokenTestCase.java | 409 ++++++++++++++++++ .../OAuth2RefreshGrantJWTTokenTestCase.java | 222 ++++++++++ .../OAuth2ServiceAbstractIntegrationTest.java | 78 ++++ .../dataprovider/model/ApplicationConfig.java | 138 ++++++ .../model/AuthorizedAccessTokenContext.java | 126 ++++++ .../dataprovider/model/AuthorizingUser.java | 94 ++++ .../dataprovider/model/TokenScopes.java | 66 +++ .../dataprovider/model/UserClaimConfig.java | 64 +++ .../src/test/resources/testng.xml | 1 + 9 files changed, 1198 insertions(+) create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2AuthorizationCodeGrantJWTTokenTestCase.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2RefreshGrantJWTTokenTestCase.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/ApplicationConfig.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizedAccessTokenContext.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizingUser.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/TokenScopes.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/UserClaimConfig.java diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2AuthorizationCodeGrantJWTTokenTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2AuthorizationCodeGrantJWTTokenTestCase.java new file mode 100644 index 00000000000..c7763ccf0d1 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2AuthorizationCodeGrantJWTTokenTestCase.java @@ -0,0 +1,409 @@ +/* + * 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.oauth2; + +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.config.Lookup; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.cookie.CookieSpecProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.cookie.RFC6265CookieSpecProvider; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +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.oauth2.dataprovider.model.ApplicationConfig; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.AuthorizedAccessTokenContext; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.AuthorizingUser; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.TokenScopes; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.UserClaimConfig; +import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.ApplicationResponseModel; +import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.OpenIDConnectConfiguration; +import org.wso2.identity.integration.test.rest.api.user.common.model.Email; +import org.wso2.identity.integration.test.rest.api.user.common.model.Name; +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.DataExtractUtil; +import org.wso2.identity.integration.test.utils.OAuth2Constant; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.DataExtractUtil.KeyValue; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.ACCESS_TOKEN_ENDPOINT; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZATION_HEADER; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE; + +public class OAuth2AuthorizationCodeGrantJWTTokenTestCase extends OAuth2ServiceAbstractIntegrationTest { + + private Lookup cookieSpecRegistry; + private RequestConfig requestConfig; + private CloseableHttpClient client; + private SCIM2RestClient scim2RestClient; + + private ApplicationConfig applicationConfig; + private TokenScopes tokenScopes; + private AuthorizingUser authorizingUser; + + private String applicationId; + private String clientId; + private String clientSecret; + + private String accessToken; + private String refreshToken; + private String sessionDataKey; + private String authorizationCode; + private JWTClaimsSet accessTokenClaims; + + @Factory(dataProvider = "testExecutionContextProvider") + public OAuth2AuthorizationCodeGrantJWTTokenTestCase(ApplicationConfig applicationConfig, TokenScopes tokenScopes, + AuthorizingUser authorizingUser) { + + this.applicationConfig = applicationConfig; + this.tokenScopes = tokenScopes; + this.authorizingUser = authorizingUser; + } + + @DataProvider(name = "testExecutionContextProvider") + public static Object[][] getTestExecutionContext() { + + UserClaimConfig emailClaimConfig = new UserClaimConfig.Builder().localClaimUri( + "http://wso2.org/claims/emailaddress").oidcClaimUri("email").build(); + UserClaimConfig givenNameClaimConfig = new UserClaimConfig.Builder().localClaimUri( + "http://wso2.org/claims/givenname").oidcClaimUri("given_name").build(); + UserClaimConfig familyNameClaimConfig = + new UserClaimConfig.Builder().localClaimUri("http://wso2.org/claims/lastname") + .oidcClaimUri("family_name").build(); + + return new Object[][]{ + {new ApplicationConfig.Builder().tokenType(ApplicationConfig.TokenType.JWT) + .grantTypes(Arrays.asList("authorization_code", "refresh_token")).expiryTime(300) + .audienceList(Arrays.asList("audience1", "audience2", "audience3")) + .claimsList(Arrays.asList(emailClaimConfig, givenNameClaimConfig, familyNameClaimConfig)) + .skipConsent(true).build(), + new TokenScopes.Builder().requestedScopes(Arrays.asList("openid", "email", "profile")) + .grantedScopes(Arrays.asList("openid", "email", "profile")).build(), + new AuthorizingUser.Builder().username("alice").password("Alice@123").userClaims( + new HashMap() {{ + put(emailClaimConfig, "alice@aol.com"); + }}).build()} + //todo: add another iteration for authorized api scopes + }; + } + + @BeforeClass(alwaysRun = true) + public void testInit() throws Exception { + + super.init(TestUserMode.TENANT_ADMIN); + + cookieSpecRegistry = RegistryBuilder.create() + .register(CookieSpecs.DEFAULT, new RFC6265CookieSpecProvider()) + .build(); + requestConfig = RequestConfig.custom() + .setCookieSpec(CookieSpecs.DEFAULT) + .build(); + client = HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfig) + .setDefaultCookieSpecRegistry(cookieSpecRegistry) + .setRedirectStrategy(new DefaultRedirectStrategy() { + @Override + protected boolean isRedirectable(String method) { + + return false; + } + }).build(); + + scim2RestClient = new SCIM2RestClient(serverURL, tenantInfo); + + String userId = addUser(authorizingUser); + authorizingUser.setUserId(userId); + + addApp(); + } + + @AfterClass(alwaysRun = true) + public void atEnd() throws Exception { + + deleteApp(applicationId); + deleteUser(authorizingUser.getUserId()); + restClient.closeHttpClient(); + client.close(); + } + + @Test(groups = "wso2.is", description = "Initiate authorize request.") + public void testSendAuthorizeRequest() throws Exception { + + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", clientId)); + urlParameters.add(new BasicNameValuePair("redirect_uri", OAuth2Constant.CALLBACK_URL)); + urlParameters.add(new BasicNameValuePair("scope", String.join(" ", tokenScopes.getRequestedScopes()))); + + HttpResponse response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); + + Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); + assertNotNull(locationHeader, "Location header expected for authorize request is not available."); + EntityUtils.consume(response.getEntity()); + + response = sendGetRequest(client, locationHeader.getValue()); + + Map keyPositionMap = new HashMap<>(1); + keyPositionMap.put("name=\"sessionDataKey\"", 1); + List keyValues = DataExtractUtil.extractDataFromResponse(response, keyPositionMap); + assertNotNull(keyValues, "SessionDataKey key value is null"); + + sessionDataKey = keyValues.get(0).getValue(); + assertNotNull(sessionDataKey, "Session data key is null."); + EntityUtils.consume(response.getEntity()); + } + + @Test(groups = "wso2.is", description = "Perform login", dependsOnMethods = "testSendAuthorizeRequest") + public void testSendLoginPost() throws Exception { + + HttpResponse response = sendLoginPostForCustomUsers(client, sessionDataKey, authorizingUser.getUsername(), + authorizingUser.getPassword()); + + Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); + assertNotNull(locationHeader, "Location header expected post login is not available."); + EntityUtils.consume(response.getEntity()); + + response = sendGetRequest(client, locationHeader.getValue()); + locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); + assertNotNull(locationHeader, "Redirection URL to the application with authorization code is null."); + EntityUtils.consume(response.getEntity()); + + authorizationCode = getAuthorizationCodeFromURL(locationHeader.getValue()); + assertNotNull(authorizationCode); + } + + @Test(groups = "wso2.is", description = "Get access token", dependsOnMethods = "testSendLoginPost") + public void testGetAccessToken() throws Exception { + + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("code", authorizationCode)); + urlParameters.add(new BasicNameValuePair("grant_type", OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE)); + urlParameters.add(new BasicNameValuePair("redirect_uri", OAuth2Constant.CALLBACK_URL)); + urlParameters.add(new BasicNameValuePair("client_id", clientId)); + + List
headers = new ArrayList<>(); + headers.add(new BasicHeader(AUTHORIZATION_HEADER, + OAuth2Constant.BASIC_HEADER + " " + getBase64EncodedString(clientId, clientSecret))); + headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded")); + headers.add(new BasicHeader("User-Agent", OAuth2Constant.USER_AGENT)); + + HttpResponse response = sendPostRequest(client, headers, urlParameters, + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + assertNotNull(response, "Failed to receive a response for access token request."); + + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + JSONObject jsonResponse = new JSONObject(responseString); + + assertTrue(jsonResponse.has("access_token"), "Access token not found in the token response."); + assertTrue(jsonResponse.has("refresh_token"), "Refresh token not found in the token response."); + assertTrue(jsonResponse.has("expires_in"), "Expiry time not found in the token response."); + assertTrue(jsonResponse.has("token_type"), "Token type not found in the token response."); + + accessToken = jsonResponse.getString("access_token"); + assertNotNull(accessToken, "Access token is null."); + refreshToken = jsonResponse.getString("refresh_token"); + assertNotNull(refreshToken, "Refresh token is null."); + + int expiresIn = jsonResponse.getInt("expires_in"); + assertEquals(expiresIn, applicationConfig.getExpiryTime(), "Invalid expiry time for the access token."); + + String tokenType = jsonResponse.getString("token_type"); + assertEquals(tokenType, "Bearer", "Invalid token type for the access token."); + } + + @Test(groups = "wso2.is", description = "Extract access token claims", dependsOnMethods = "testGetAccessToken") + public void testExtractJWTAccessTokenClaims() throws Exception { + + accessTokenClaims = getJWTClaimSetFromToken(accessToken); + assertNotNull(accessTokenClaims); + } + + @Test(groups = "wso2.is", description = "Validate JWT token identifier", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateJWTID() { + + assertNotNull(accessTokenClaims.getJWTID()); + } + + @Test(groups = "wso2.is", description = "Validate issuer", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateIssuer() { + + assertEquals(accessTokenClaims.getIssuer(), + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + } + + @Test(groups = "wso2.is", description = "Validate client id", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateClientId() { + + assertEquals(accessTokenClaims.getClaim("client_id"), clientId); + } + + @Test(groups = "wso2.is", description = "Validate audiences", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateAudiences() { + + List audienceList = accessTokenClaims.getAudience(); + assertEquals(audienceList.get(0), clientId, "Audience value does not include the client id."); + + List expectedAudiences = applicationConfig.getAudienceList(); + for (String expectedAudience : expectedAudiences) { + assertTrue(audienceList.contains(expectedAudience), + "Audience " + expectedAudience + " not found in the access token."); + } + } + + @Test(groups = "wso2.is", description = "Validate expiry time", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateExpiryTime() { + + // Convert expiry time to seconds as that is how expiry is incorporated in the JWT token claims. + assertEquals(accessTokenClaims.getExpirationTime().getTime() / 1000, + calculateExpiryTime(accessTokenClaims.getIssueTime().getTime() / 1000, + applicationConfig.getExpiryTime()), + "Invalid expiry time for the access token."); + } + + @Test(groups = "wso2.is", description = "Validate scopes", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateScopes() throws Exception { + + assertNotNull(accessTokenClaims.getStringClaim("scope")); + List authorizedScopes = Arrays.asList(accessTokenClaims.getStringClaim("scope").split(" ")); + List expectedScopes = tokenScopes.getGrantedScopes(); + for (String expectedScope : expectedScopes) { + assertTrue(authorizedScopes.contains(expectedScope), + "Scope " + expectedScope + " not found in the access token."); + } + } + + @Test(groups = "wso2.is", description = "Validate additional user claims", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testValidateAdditionalUserClaims() { + + applicationConfig.getRequestedClaimList().forEach(claim -> { + if (authorizingUser.getUserClaims().get(claim) != null) { + assertNotNull(accessTokenClaims.getClaim(claim.getOidcClaimUri()), + "Claim " + claim.getOidcClaimUri() + " not found in the access token."); + assertEquals(accessTokenClaims.getClaim(claim.getOidcClaimUri()), + authorizingUser.getUserClaims().get(claim), + "Value for claim " + claim.getOidcClaimUri() + " is incorrect in the access token."); + } + }); + } + + @Test(groups = "wso2.is", description = "Validate additional user claims", dependsOnMethods = "testExtractJWTAccessTokenClaims") + public void testRefreshTokenGrant() throws Exception { + + AuthorizedAccessTokenContext tokenContext = + new AuthorizedAccessTokenContext.Builder().accessToken(accessToken).refreshToken(refreshToken) + .grantType(OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE).accessTokenClaims(accessTokenClaims) + .clientId(clientId).clientSecret(clientSecret).build(); + + OAuth2RefreshGrantJWTTokenTestCase refreshGrantJWTTokenTestCase = + new OAuth2RefreshGrantJWTTokenTestCase(applicationConfig, tokenScopes, authorizingUser, tokenContext); + + refreshGrantJWTTokenTestCase.testGetAccessTokenFromRefreshToken(); + refreshGrantJWTTokenTestCase.testValidateJWTID(); + refreshGrantJWTTokenTestCase.testValidateIssuer(); + refreshGrantJWTTokenTestCase.testValidateClientId(); + refreshGrantJWTTokenTestCase.testValidateAudiences(); + refreshGrantJWTTokenTestCase.testValidateExpiryTime(); + refreshGrantJWTTokenTestCase.testValidateScopes(); + refreshGrantJWTTokenTestCase.testValidateAdditionalUserClaims(); + } + + private String addUser(AuthorizingUser user) throws Exception { + + UserObject userInfo = new UserObject(); + userInfo.setUserName(user.getUsername()); + userInfo.setPassword(user.getPassword()); + + for (Map.Entry entry : user.getUserClaims().entrySet()) { + if (entry.getKey().getOidcClaimUri().equals("email")) { + userInfo.addEmail(new Email().value((String) entry.getValue())); + } else if (entry.getKey().getOidcClaimUri().equals("given_name")) { + userInfo.setName(new Name().givenName((String) entry.getValue())); + } else if (entry.getKey().getOidcClaimUri().equals("family_name")) { + userInfo.getName().setFamilyName((String) entry.getValue()); + } + } + + return scim2RestClient.createUser(userInfo); + } + + private void deleteUser(String userId) throws Exception { + + scim2RestClient.deleteUser(userId); + } + + private void addApp() throws Exception { + + ApplicationResponseModel application = addApplication(applicationConfig); + applicationId = application.getId(); + + OpenIDConnectConfiguration oidcConfig = getOIDCInboundDetailsOfApplication(applicationId); + clientId = oidcConfig.getClientId(); + clientSecret = oidcConfig.getClientSecret(); + } + + private String getAuthorizationCodeFromURL(String location) { + + URI uri = URI.create(location); + return URLEncodedUtils.parse(uri, StandardCharsets.UTF_8).stream() + .filter(param -> "code".equals(param.getName())) + .map(NameValuePair::getValue) + .findFirst() + .orElse(null); + } + + private long calculateExpiryTime(long issuedTime, long expiryPeriodInSeconds) { + + return issuedTime + expiryPeriodInSeconds; + } + + private JWTClaimsSet getJWTClaimSetFromToken(String jwtToken) throws ParseException { + + SignedJWT signedJWT = SignedJWT.parse(jwtToken); + return signedJWT.getJWTClaimsSet(); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2RefreshGrantJWTTokenTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2RefreshGrantJWTTokenTestCase.java new file mode 100644 index 00000000000..793005b0a8b --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2RefreshGrantJWTTokenTestCase.java @@ -0,0 +1,222 @@ +/* + * 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.oauth2; + +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Lookup; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.cookie.CookieSpecProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.cookie.RFC6265CookieSpecProvider; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +import org.testng.annotations.Test; +import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.ApplicationConfig; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.AuthorizedAccessTokenContext; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.AuthorizingUser; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.TokenScopes; +import org.wso2.identity.integration.test.utils.OAuth2Constant; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +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; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZATION_HEADER; + +public class OAuth2RefreshGrantJWTTokenTestCase extends OAuth2ServiceAbstractIntegrationTest { + + private Lookup cookieSpecRegistry; + private RequestConfig requestConfig; + private CloseableHttpClient client; + + private ApplicationConfig applicationConfig; + private TokenScopes tokenScopes; + private AuthorizingUser authorizingUser; + private AuthorizedAccessTokenContext authorizedAccessTokenContext; + + private String accessToken; + private JWTClaimsSet accessTokenClaims; + + public OAuth2RefreshGrantJWTTokenTestCase(ApplicationConfig applicationConfig, TokenScopes tokenScopes, + AuthorizingUser authorizingUser, + AuthorizedAccessTokenContext authorizedAccessTokenContext) + throws Exception { + + this.applicationConfig = applicationConfig; + this.tokenScopes = tokenScopes; + this.authorizingUser = authorizingUser; + this.authorizedAccessTokenContext = authorizedAccessTokenContext; + + super.init(TestUserMode.TENANT_ADMIN); + + cookieSpecRegistry = RegistryBuilder.create() + .register(CookieSpecs.DEFAULT, new RFC6265CookieSpecProvider()) + .build(); + requestConfig = RequestConfig.custom() + .setCookieSpec(CookieSpecs.DEFAULT) + .build(); + client = HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfig) + .setDefaultCookieSpecRegistry(cookieSpecRegistry) + .setRedirectStrategy(new DefaultRedirectStrategy() { + @Override + protected boolean isRedirectable(String method) { + + return false; + } + }).build(); + } + + @Test(groups = "wso2.is", description = "Get access token from refresh token") + public void testGetAccessTokenFromRefreshToken() throws Exception { + + List parameters = new ArrayList<>(); + parameters.add(new BasicNameValuePair("grant_type", OAuth2Constant.OAUTH2_GRANT_TYPE_REFRESH_TOKEN)); + parameters.add(new BasicNameValuePair(OAuth2Constant.OAUTH2_GRANT_TYPE_REFRESH_TOKEN, + authorizedAccessTokenContext.getRefreshToken())); + + List
headers = new ArrayList<>(); + headers.add(new BasicHeader(AUTHORIZATION_HEADER, + OAuth2Constant.BASIC_HEADER + " " + getBase64EncodedString(authorizedAccessTokenContext.getClientId(), + authorizedAccessTokenContext.getClientSecret()))); + headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded")); + headers.add(new BasicHeader("User-Agent", OAuth2Constant.USER_AGENT)); + + HttpResponse response = sendPostRequest(client, headers, parameters, + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + JSONObject jsonResponse = new JSONObject(responseString); + + assertTrue(jsonResponse.has("access_token"), "Access token not found in the token response."); + assertTrue(jsonResponse.has("refresh_token"), "Refresh token not found in the token response."); + assertTrue(jsonResponse.has("expires_in"), "Expiry time not found in the token response."); + assertTrue(jsonResponse.has("token_type"), "Token type not found in the token response."); + + accessToken = jsonResponse.getString("access_token"); + assertNotNull(accessToken, "Access token is null."); + + String refreshToken = jsonResponse.getString("refresh_token"); + assertNotNull(refreshToken, "Refresh token is null."); + + int expiresIn = jsonResponse.getInt("expires_in"); + assertEquals(expiresIn, applicationConfig.getExpiryTime(), "Invalid expiry time for the access token."); + + String tokenType = jsonResponse.getString("token_type"); + assertEquals(tokenType, "Bearer", "Invalid token type for the access token."); + + accessTokenClaims = getJWTClaimSetFromToken(accessToken); + assertNotNull(accessTokenClaims); + } + + @Test(groups = "wso2.is", description = "Validate JWT token identifier", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateJWTID() { + + assertNotNull(accessTokenClaims.getJWTID()); + } + + @Test(groups = "wso2.is", description = "Validate issuer", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateIssuer() { + + assertEquals(accessTokenClaims.getIssuer(), + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + } + + @Test(groups = "wso2.is", description = "Validate client id", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateClientId() { + + assertEquals(accessTokenClaims.getClaim("client_id"), authorizedAccessTokenContext.getClientId()); + } + + @Test(groups = "wso2.is", description = "Validate audiences", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateAudiences() { + + List audienceList = accessTokenClaims.getAudience(); + assertEquals(audienceList.get(0), authorizedAccessTokenContext.getClientId(), + "Audience value does not include the client id."); + + List expectedAudiences = applicationConfig.getAudienceList(); + for (String expectedAudience : expectedAudiences) { + assertTrue(audienceList.contains(expectedAudience), + "Audience " + expectedAudience + " not found in the access token."); + } + } + + @Test(groups = "wso2.is", description = "Validate expiry time", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateExpiryTime() { + + // Convert expiry time to seconds as that is how expiry is incorporated in the JWT token claims. + assertEquals(accessTokenClaims.getExpirationTime().getTime() / 1000, + calculateExpiryTime(accessTokenClaims.getIssueTime().getTime() / 1000, + applicationConfig.getExpiryTime()), + "Invalid expiry time for the access token."); + } + + @Test(groups = "wso2.is", description = "Validate scopes", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateScopes() throws Exception { + + assertNotNull(accessTokenClaims.getStringClaim("scope")); + List authorizedScopes = Arrays.asList(accessTokenClaims.getStringClaim("scope").split(" ")); + List expectedScopes = tokenScopes.getGrantedScopes(); + for (String expectedScope : expectedScopes) { + assertTrue(authorizedScopes.contains(expectedScope), + "Scope " + expectedScope + " not found in the access token."); + } + } + + @Test(groups = "wso2.is", description = "Validate additional user claims", dependsOnMethods = "testGetAccessTokenFromRefreshToken") + public void testValidateAdditionalUserClaims() { + + applicationConfig.getRequestedClaimList().forEach(claim -> { + if (authorizingUser.getUserClaims().get(claim) != null) { + assertNotNull(accessTokenClaims.getClaim(claim.getOidcClaimUri()), + "Claim " + claim.getOidcClaimUri() + " not found in the access token."); + assertEquals(accessTokenClaims.getClaim(claim.getOidcClaimUri()), + authorizingUser.getUserClaims().get(claim), + "Value for claim " + claim.getOidcClaimUri() + " is incorrect in the access token."); + } + }); + } + + private JWTClaimsSet getJWTClaimSetFromToken(String jwtToken) throws ParseException { + + SignedJWT signedJWT = SignedJWT.parse(jwtToken); + return signedJWT.getJWTClaimsSet(); + } + + private long calculateExpiryTime(long issuedTime, long expiryPeriodInSeconds) { + + return issuedTime + expiryPeriodInSeconds; + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceAbstractIntegrationTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceAbstractIntegrationTest.java index 386b97836b2..d4a56857990 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceAbstractIntegrationTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceAbstractIntegrationTest.java @@ -52,6 +52,9 @@ import org.wso2.identity.integration.common.clients.oauth.OauthAdminClient; import org.wso2.identity.integration.common.clients.usermgt.remote.RemoteUserStoreManagerServiceClient; import org.wso2.identity.integration.common.utils.ISIntegrationTest; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.ApplicationConfig; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.AuthorizingUser; +import org.wso2.identity.integration.test.oauth2.dataprovider.model.UserClaimConfig; import org.wso2.identity.integration.test.rest.api.server.api.resource.v1.model.APIResourceListItem; import org.wso2.identity.integration.test.rest.api.server.api.resource.v1.model.ScopeGetModel; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.AccessTokenConfiguration; @@ -65,6 +68,7 @@ import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.ClaimConfiguration.DialectEnum; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.ClaimMappings; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.DomainAPICreationModel; +import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.IdTokenConfiguration; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.InboundProtocols; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.OpenIDConnectConfiguration; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.RequestedClaimConfiguration; @@ -85,6 +89,7 @@ import java.util.stream.Collectors; import static org.wso2.identity.integration.test.saml.SAMLFederationDynamicQueryParametersTestCase.INBOUND_AUTH_TYPE; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.CALLBACK_URL; import static org.wso2.identity.integration.test.utils.OAuth2Constant.OAUTH_APPLICATION_NAME; /** @@ -146,6 +151,55 @@ public OAuthConsumerAppDTO createApplication() throws Exception { return createApplication(appDTO, SERVICE_PROVIDER_NAME); } + /** + * Create application with the given app configurations. + * Audience list and requested claims are considered optional. + * Rest of the configurations are considered mandatory for the application creation from applicationConfig. + * + * @param applicationConfig Application configurations needed for the test case. + * @return Application model created in the server. + * @throws Exception + */ + public ApplicationResponseModel addApplication(ApplicationConfig applicationConfig) throws Exception { + + if (applicationConfig == null) { + return getBasicOAuthApplication(CALLBACK_URL); + } + + ApplicationModel application = new ApplicationModel(); + application.setName(OAUTH_APPLICATION_NAME); + + OpenIDConnectConfiguration oidcConfig = new OpenIDConnectConfiguration(); + oidcConfig.setGrantTypes(applicationConfig.getGrantTypes()); + oidcConfig.setCallbackURLs(Collections.singletonList(OAuth2Constant.CALLBACK_URL)); + + AccessTokenConfiguration accessTokenConfiguration = new AccessTokenConfiguration(); + accessTokenConfiguration.type(applicationConfig.getTokenType().getTokenTypeProperty()); + accessTokenConfiguration.applicationAccessTokenExpiryInSeconds(applicationConfig.getExpiryTime()); + accessTokenConfiguration.userAccessTokenExpiryInSeconds(applicationConfig.getExpiryTime()); + oidcConfig.accessToken(accessTokenConfiguration); + + if (applicationConfig.getAudienceList() != null && !applicationConfig.getRequestedClaimList().isEmpty()) { + oidcConfig.idToken(new IdTokenConfiguration().audience(applicationConfig.getAudienceList())); + } + + InboundProtocols inboundProtocolsConfig = new InboundProtocols(); + inboundProtocolsConfig.setOidc(oidcConfig); + application.setInboundProtocolConfiguration(inboundProtocolsConfig); + + if (applicationConfig.getRequestedClaimList() != null && !applicationConfig.getRequestedClaimList().isEmpty()) { + application.setClaimConfiguration( + buildClaimConfigurationForRequestedClaims(applicationConfig.getRequestedClaimList())); + } + + application.advancedConfigurations( + new AdvancedApplicationConfiguration().skipLoginConsent(applicationConfig.isSkipConsent()) + .skipLogoutConsent(applicationConfig.isSkipConsent())); + + String appId = restClient.createApplication(application); + return restClient.getApplication(appId); + } + public ApplicationResponseModel addApplication() throws Exception { ApplicationModel application = new ApplicationModel(); @@ -466,6 +520,16 @@ public HttpResponse sendPostRequestWithParameters(HttpClient client, List headerList, List urlParameters, + String url) throws IOException { + + HttpPost request = new HttpPost(url); + request.setHeaders(headerList.toArray(new Header[0])); + request.setEntity(new UrlEncodedFormEntity(urlParameters)); + + return client.execute(request); + } + /** * Send Get request. * @@ -1195,4 +1259,18 @@ public void authorizeDomainAPIs(String applicationId, String domainAPIId, List requestedClaimList) { + + ClaimConfiguration claimConfiguration = new ClaimConfiguration().dialect(DialectEnum.LOCAL); + for (UserClaimConfig claim : requestedClaimList) { + RequestedClaimConfiguration requestedClaimConfiguration = new RequestedClaimConfiguration(); + requestedClaimConfiguration.setClaim( + new org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.Claim().uri( + claim.getLocalClaimUri())); + claimConfiguration.addRequestedClaimsItem(requestedClaimConfiguration); + } + + return claimConfiguration; + } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/ApplicationConfig.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/ApplicationConfig.java new file mode 100644 index 00000000000..3fdfaf2ad4c --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/ApplicationConfig.java @@ -0,0 +1,138 @@ +/* + * 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.oauth2.dataprovider.model; + +import java.util.List; + +public class ApplicationConfig { + + private TokenType tokenType; + private long expiryTime; + private List audienceList; + private List requestedClaimList; + private List grantTypes; + private boolean skipConsent; + + private ApplicationConfig(Builder builder) { + + this.tokenType = builder.tokenType; + this.expiryTime = builder.expiryTime; + this.audienceList = builder.audienceList; + this.requestedClaimList = builder.claimsList; + this.grantTypes = builder.grantTypes; + this.skipConsent = builder.skipConsent; + } + + public TokenType getTokenType() { + + return tokenType; + } + + public long getExpiryTime() { + + return expiryTime; + } + + public List getAudienceList() { + + return audienceList; + } + + public List getRequestedClaimList() { + + return requestedClaimList; + } + + public List getGrantTypes() { + + return grantTypes; + } + + public boolean isSkipConsent() { + + return skipConsent; + } + + public enum TokenType { + JWT("JWT"), OPAQUE("Default"); + + String tokenTypeProperty; + + TokenType(String tokenTypeProperty) { + + this.tokenTypeProperty = tokenTypeProperty; + } + + public String getTokenTypeProperty() { + + return tokenTypeProperty; + } + } + + public static class Builder { + + private TokenType tokenType; + private int expiryTime; + private List audienceList; + private List claimsList; + private List grantTypes; + private boolean skipConsent; + + public Builder tokenType(TokenType tokenType) { + + this.tokenType = tokenType; + return this; + } + + public Builder expiryTime(int expiryTime) { + + this.expiryTime = expiryTime; + return this; + } + + public Builder audienceList(List audienceList) { + + this.audienceList = audienceList; + return this; + } + + public Builder claimsList(List claimsList) { + + this.claimsList = claimsList; + return this; + } + + public Builder grantTypes(List grantTypes) { + + this.grantTypes = grantTypes; + return this; + } + + public Builder skipConsent(boolean skipConsent) { + + this.skipConsent = skipConsent; + return this; + } + + public ApplicationConfig build() { + + return new ApplicationConfig(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizedAccessTokenContext.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizedAccessTokenContext.java new file mode 100644 index 00000000000..a89fe6f06bf --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizedAccessTokenContext.java @@ -0,0 +1,126 @@ +/* + * 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.oauth2.dataprovider.model; + +import com.nimbusds.jwt.JWTClaimsSet; + +public class AuthorizedAccessTokenContext { + + private String grantType; + private String clientId; + private String clientSecret; + private String refreshToken; + private String accessToken; + + private JWTClaimsSet accessTokenClaims; + + private AuthorizedAccessTokenContext(Builder builder) { + + this.grantType = builder.grantType; + this.refreshToken = builder.refreshToken; + this.accessToken = builder.accessToken; + this.accessTokenClaims = builder.accessTokenClaims; + this.clientId = builder.clientId; + this.clientSecret = builder.clientSecret; + + } + + public String getGrantType() { + + return grantType; + } + + public String getRefreshToken() { + + return refreshToken; + } + + public String getAccessToken() { + + return accessToken; + } + + public JWTClaimsSet getAccessTokenClaims() { + + return accessTokenClaims; + } + + public String getClientId() { + + return clientId; + } + + public String getClientSecret() { + + return clientSecret; + } + + public static class Builder { + + private String grantType; + private String clientId; + private String clientSecret; + private String refreshToken; + private String accessToken; + + private JWTClaimsSet accessTokenClaims; + + public Builder grantType(String grantType) { + + this.grantType = grantType; + return this; + } + + public Builder refreshToken(String refreshToken) { + + this.refreshToken = refreshToken; + return this; + } + + public Builder accessToken(String accessToken) { + + this.accessToken = accessToken; + return this; + } + + public Builder accessTokenClaims(JWTClaimsSet accessTokenClaims) { + + this.accessTokenClaims = accessTokenClaims; + return this; + } + + public Builder clientId(String clientId) { + + this.clientId = clientId; + return this; + } + + public Builder clientSecret(String clientSecret) { + + this.clientSecret = clientSecret; + return this; + } + + public AuthorizedAccessTokenContext build() { + + return new AuthorizedAccessTokenContext(this); + } + } + +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizingUser.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizingUser.java new file mode 100644 index 00000000000..6a8853f4c55 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/AuthorizingUser.java @@ -0,0 +1,94 @@ +/* + * 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.oauth2.dataprovider.model; + +import java.util.Map; + +public class AuthorizingUser { + + private String username; + private String password; + + private String userId; + + private Map userClaims; + + private AuthorizingUser(Builder builder) { + + this.username = builder.username; + this.password = builder.password; + this.userClaims = builder.userClaims; + } + + public String getUserId() { + + return userId; + } + + public void setUserId(String userId) { + + this.userId = userId; + } + + public String getUsername() { + + return username; + } + + public String getPassword() { + + return password; + } + + public Map getUserClaims() { + + return userClaims; + } + + public static class Builder { + + private String username; + private String password; + + private Map userClaims; + + public Builder username(String username) { + + this.username = username; + return this; + } + + public Builder password(String password) { + + this.password = password; + return this; + } + + public Builder userClaims(Map userClaims) { + + this.userClaims = userClaims; + return this; + } + + public AuthorizingUser build() { + + return new AuthorizingUser(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/TokenScopes.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/TokenScopes.java new file mode 100644 index 00000000000..7b3f384272a --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/TokenScopes.java @@ -0,0 +1,66 @@ +/* + * 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.oauth2.dataprovider.model; + +import java.util.List; + +public class TokenScopes { + + private List requestedScopes; + private List grantedScopes; + + private TokenScopes(Builder builder) { + + this.requestedScopes = builder.requestedScopes; + this.grantedScopes = builder.grantedScopes; + } + + public List getRequestedScopes() { + + return requestedScopes; + } + + public List getGrantedScopes() { + + return grantedScopes; + } + + public static class Builder { + + private List requestedScopes; + private List grantedScopes; + + public Builder requestedScopes(List requestedScopes) { + + this.requestedScopes = requestedScopes; + return this; + } + + public Builder grantedScopes(List grantedScopes) { + + this.grantedScopes = grantedScopes; + return this; + } + + public TokenScopes build() { + + return new TokenScopes(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/UserClaimConfig.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/UserClaimConfig.java new file mode 100644 index 00000000000..9896cb46239 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/dataprovider/model/UserClaimConfig.java @@ -0,0 +1,64 @@ +/* + * 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.oauth2.dataprovider.model; + +public class UserClaimConfig { + + private String localClaimUri; + private String oidcClaimUri; + + public UserClaimConfig(Builder builder) { + + this.localClaimUri = builder.localClaimUri; + this.oidcClaimUri = builder.oidcClaimUri; + } + + public String getLocalClaimUri() { + + return localClaimUri; + } + + public String getOidcClaimUri() { + + return oidcClaimUri; + } + + public static class Builder { + + private String localClaimUri; + private String oidcClaimUri; + + public Builder localClaimUri(String localClaimUri) { + + this.localClaimUri = localClaimUri; + return this; + } + + public Builder oidcClaimUri(String oidcClaimUri) { + + this.oidcClaimUri = oidcClaimUri; + return this; + } + + public UserClaimConfig build() { + + return new UserClaimConfig(this); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml index fd48b6b5889..e21b09dfad3 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml @@ -138,6 +138,7 @@ +