From 835f7c3df9c170d816c558b0409881749c6f34f1 Mon Sep 17 00:00:00 2001 From: Thumimku Date: Tue, 22 Oct 2024 10:29:22 +0530 Subject: [PATCH 1/3] init --- ...OAuth2ServiceClientCredentialTestCase.java | 137 +++++++++++++++++- 1 file changed, 133 insertions(+), 4 deletions(-) diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java index 97bc2b75b0..26a0a96935 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java @@ -21,7 +21,9 @@ import com.nimbusds.oauth2.sdk.AccessTokenResponse; import com.nimbusds.oauth2.sdk.AuthorizationGrant; import com.nimbusds.oauth2.sdk.ClientCredentialsGrant; +import com.nimbusds.oauth2.sdk.ErrorObject; import com.nimbusds.oauth2.sdk.Scope; +import com.nimbusds.oauth2.sdk.TokenErrorResponse; import com.nimbusds.oauth2.sdk.TokenRequest; import com.nimbusds.oauth2.sdk.TokenResponse; import com.nimbusds.oauth2.sdk.auth.ClientAuthentication; @@ -30,8 +32,16 @@ import com.nimbusds.oauth2.sdk.http.HTTPResponse; import com.nimbusds.oauth2.sdk.id.ClientID; import com.nimbusds.openid.connect.sdk.OIDCTokenResponse; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +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.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -44,10 +54,19 @@ 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.restclients.OAuth2RestClient; +import org.wso2.identity.integration.test.utils.CarbonUtils; import org.wso2.identity.integration.test.utils.OAuth2Constant; import java.net.URI; - +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; import static org.wso2.identity.integration.test.utils.OAuth2Constant.OAUTH2_SCOPE_OPENID; /** @@ -55,6 +74,13 @@ */ public class OAuth2ServiceClientCredentialTestCase extends OAuth2ServiceAbstractIntegrationTest { + private static final String JWT = "JWT"; + private static final String API_USERS_V1_OFFLINE_INVITE_LINK = "/api/users/v1/offline-invite-link/"; + public static final String SCIM2_BULK = "/scim2/Bulk"; + public static final String OAUTH2_INTROSPECT = "/oauth2/introspect"; + private static final String INTERNAL_BULK_RESOURCE_CREATE = "internal_bulk_resource_create"; + private static final String INTERNAL_OFFLINE_INVITE = "internal_offline_invite"; + private static final String SCOPE = "scope"; private String accessToken; private String consumerKey; private String consumerSecret; @@ -110,6 +136,13 @@ public void atEnd() throws Exception { public void testRegisterApplication() throws Exception { ApplicationResponseModel application = addApplication(); + + String applicationId = application.getId(); + if (!CarbonUtils.isLegacyAuthzRuntimeEnabled()) { + // Authorize few system APIs. + authorizeSystemAPIs(applicationId, + new ArrayList<>(Arrays.asList(SCIM2_BULK, OAUTH2_INTROSPECT))); + } Assert.assertNotNull(application, "OAuth App creation failed."); OpenIDConnectConfiguration oidcConfig = getOIDCInboundDetailsOfApplication(application.getId()); @@ -119,8 +152,6 @@ public void testRegisterApplication() throws Exception { consumerSecret = oidcConfig.getClientSecret(); Assert.assertNotNull(consumerSecret, "Application creation failed."); - - applicationId = application.getId(); } @Test(groups = "wso2.is", description = "Send client credentials token request.", dependsOnMethods = "testRegisterApplication") @@ -130,7 +161,7 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { ClientID clientID = new ClientID(consumerKey); Secret clientSecret = new Secret(consumerSecret); ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret); - Scope scope = new Scope(OAUTH2_SCOPE_OPENID, "xyz", VALID_RANDOM_SCOPE); + Scope scope = new Scope(OAUTH2_SCOPE_OPENID, "xyz", VALID_RANDOM_SCOPE, INTERNAL_BULK_RESOURCE_CREATE); URI tokenEndpoint = new URI(getTenantQualifiedURL(OAuth2Constant.ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientCredentialsGrant, scope); @@ -150,8 +181,13 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { Scope scopesInResponse = accessTokenResponse.getTokens().getAccessToken().getScope(); Assert.assertFalse(scopesInResponse.contains("xyz"), "Not allowed random scope is issued for client credential " + "grant type."); + Assert.assertFalse(scopesInResponse.contains(INTERNAL_OFFLINE_INVITE), "Not allowed random scope is issued for client credential " + + "grant type."); + Assert.assertTrue(scopesInResponse.contains(VALID_RANDOM_SCOPE), "Allowed random scope is not issued for " + "client credential grant type."); + Assert.assertTrue(scopesInResponse.contains(INTERNAL_BULK_RESOURCE_CREATE), + "Allowed bulk resource create scope is not issued for client credential grant type."); // This ensures that openid scopes are not issued for client credential grant type. Assert.assertFalse(accessTokenResponse instanceof OIDCTokenResponse, "Client credential grant type cannot " + @@ -159,6 +195,99 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { Assert.assertFalse(scopesInResponse.contains(OAUTH2_SCOPE_OPENID), "Client credentials cannot get openid scope."); } + @Test(groups = "wso2.is", description = "Send client credentials token request with invalid client Id.", + dependsOnMethods = "testGetTokenUsingClientCredentialsGrant") + public void testGetTokenUsingCCGrantWithInvalidClientId() throws Exception { + + AuthorizationGrant clientCredentialsGrant = new ClientCredentialsGrant(); + ClientID clientID = new ClientID("invalidConsumerKey"); + Secret clientSecret = new Secret(consumerSecret); + ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret); + Scope scope = new Scope(OAUTH2_SCOPE_OPENID, "xyz", VALID_RANDOM_SCOPE, INTERNAL_BULK_RESOURCE_CREATE); + + URI tokenEndpoint = new URI(getTenantQualifiedURL(OAuth2Constant.ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientCredentialsGrant, scope); + HTTPResponse tokenHTTPResp = request.toHTTPRequest().send(); + Assert.assertNotNull(tokenHTTPResp, "Access token http response is null."); + + TokenResponse tokenResponse = TokenResponse.parse(tokenHTTPResp); + Assert.assertFalse(tokenResponse.indicatesSuccess(), + "Token response indicated success. Token request should fail with invalid client id."); + + TokenErrorResponse accessTokenResponse = (TokenErrorResponse) tokenResponse; + ErrorObject errorObject = accessTokenResponse.getErrorObject(); + Assert.assertEquals(errorObject.getHTTPStatusCode(), HttpStatus.SC_UNAUTHORIZED, + "Invalid access token response doesn't contain bad request status code."); + Assert.assertEquals(errorObject.getCode(), "invalid_client", + "Invalid access token response doesn't contain required error message."); + Assert.assertEquals(errorObject.getDescription(), + "A valid OAuth client could not be found for client_id: invalidConsumerKey", + "Invalid access token response doesn't contain required error description."); + } + + @Test(groups = "wso2.is", description = "Send client credentials token request with invalid client secret.", + dependsOnMethods = "testGetTokenUsingCCGrantWithInvalidClientId") + public void testGetTokenUsingCCGrantWithInvalidClientCredentials() throws Exception { + + AuthorizationGrant clientCredentialsGrant = new ClientCredentialsGrant(); + ClientID clientID = new ClientID(consumerKey); + Secret clientSecret = new Secret("invalidConsumerSecret"); + ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret); + Scope scope = new Scope(OAUTH2_SCOPE_OPENID, "xyz", VALID_RANDOM_SCOPE, INTERNAL_BULK_RESOURCE_CREATE); + + URI tokenEndpoint = new URI(getTenantQualifiedURL(OAuth2Constant.ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientCredentialsGrant, scope); + HTTPResponse tokenHTTPResp = request.toHTTPRequest().send(); + Assert.assertNotNull(tokenHTTPResp, "Access token http response is null."); + + TokenResponse tokenResponse = TokenResponse.parse(tokenHTTPResp); + Assert.assertFalse(tokenResponse.indicatesSuccess(), + "Token response indicated success. Token request should fail with invalid client id."); + + TokenErrorResponse accessTokenResponse = (TokenErrorResponse) tokenResponse; + ErrorObject errorObject = accessTokenResponse.getErrorObject(); + Assert.assertEquals(errorObject.getHTTPStatusCode(), HttpStatus.SC_UNAUTHORIZED, + "Invalid access token response doesn't contain bad request status code."); + Assert.assertEquals(errorObject.getCode(), "invalid_client", + "Invalid access token response doesn't contain required error message."); + Assert.assertEquals(errorObject.getDescription(), + "Client credentials are invalid.", + "Invalid access token response doesn't contain required error description."); + } + + @Test(groups = "wso2.is", description = "Send client credentials token request without client secret.", + dependsOnMethods = "testGetTokenUsingCCGrantWithInvalidClientCredentials") + public void testGetTokenUsingCCGrantWithoutCredentials() throws Exception { + + + List parameters = new ArrayList<>(); + parameters.add(new BasicNameValuePair("grant_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS)); + + String scopes = "xyz " + VALID_RANDOM_SCOPE + " " + INTERNAL_BULK_RESOURCE_CREATE; + parameters.add(new BasicNameValuePair("scope", scopes)); + + List
headers = new ArrayList<>(); + headers.add(new BasicHeader(AUTHORIZATION_HEADER, OAuth2Constant.BASIC_HEADER + " " + + getBase64EncodedString("", ""))); + 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("error"), "Invalid access token response doesn't contain" + + " error message."); + assertEquals(jsonResponse.getString("error"), "invalid_client", + "Invalid access token response doesn't contain required error message."); + + assertTrue(jsonResponse.has("error_description"), "Error not found in the token response."); + assertEquals(jsonResponse.getString("error_description"), "Client ID not found in the request.", + "Invalid access token response doesn't contain required error description."); + } + @Test(groups = "wso2.is", description = "Validate access token", dependsOnMethods = "testGetTokenUsingClientCredentialsGrant") public void testValidateAccessToken() throws Exception { From d0f7a238c80a4d46b113c17237a6d7e7db67286e Mon Sep 17 00:00:00 2001 From: Thumimku Date: Tue, 22 Oct 2024 11:32:29 +0530 Subject: [PATCH 2/3] add jwt tyoken type cases --- ...OAuth2ServiceClientCredentialTestCase.java | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java index 26a0a96935..2c315cf9de 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java @@ -51,6 +51,7 @@ import org.wso2.carbon.automation.engine.context.AutomationContext; import org.wso2.carbon.automation.engine.context.TestUserMode; import org.wso2.carbon.automation.engine.context.beans.Tenant; +import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.AccessTokenConfiguration; 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.restclients.OAuth2RestClient; @@ -63,7 +64,6 @@ 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; @@ -74,13 +74,10 @@ */ public class OAuth2ServiceClientCredentialTestCase extends OAuth2ServiceAbstractIntegrationTest { - private static final String JWT = "JWT"; - private static final String API_USERS_V1_OFFLINE_INVITE_LINK = "/api/users/v1/offline-invite-link/"; public static final String SCIM2_BULK = "/scim2/Bulk"; public static final String OAUTH2_INTROSPECT = "/oauth2/introspect"; private static final String INTERNAL_BULK_RESOURCE_CREATE = "internal_bulk_resource_create"; private static final String INTERNAL_OFFLINE_INVITE = "internal_offline_invite"; - private static final String SCOPE = "scope"; private String accessToken; private String consumerKey; private String consumerSecret; @@ -89,6 +86,7 @@ public class OAuth2ServiceClientCredentialTestCase extends OAuth2ServiceAbstract private final AutomationContext context; private Tenant tenantInfo; private String applicationId; + private OpenIDConnectConfiguration oidcConfig; private CloseableHttpClient client; @@ -137,7 +135,7 @@ public void testRegisterApplication() throws Exception { ApplicationResponseModel application = addApplication(); - String applicationId = application.getId(); + applicationId = application.getId(); if (!CarbonUtils.isLegacyAuthzRuntimeEnabled()) { // Authorize few system APIs. authorizeSystemAPIs(applicationId, @@ -145,7 +143,7 @@ public void testRegisterApplication() throws Exception { } Assert.assertNotNull(application, "OAuth App creation failed."); - OpenIDConnectConfiguration oidcConfig = getOIDCInboundDetailsOfApplication(application.getId()); + oidcConfig = getOIDCInboundDetailsOfApplication(application.getId()); consumerKey = oidcConfig.getClientId(); Assert.assertNotNull(consumerKey, "Application creation failed."); @@ -167,7 +165,8 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientCredentialsGrant, scope); HTTPResponse tokenHTTPResp = request.toHTTPRequest().send(); Assert.assertNotNull(tokenHTTPResp, "Access token http response is null."); - + Assert.assertEquals(tokenHTTPResp.getContentType().toString(), "application/json", + "Token response did not indicate correct token response"); TokenResponse tokenResponse = TokenResponse.parse(tokenHTTPResp); Assert.assertTrue(tokenResponse.indicatesSuccess(), "Token response did not indicate success. Token request has failed."); @@ -195,6 +194,18 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { Assert.assertFalse(scopesInResponse.contains(OAUTH2_SCOPE_OPENID), "Client credentials cannot get openid scope."); } + @Test(groups = "wso2.is", description = "Validate access token", + dependsOnMethods = "testGetTokenUsingClientCredentialsGrant") + public void testValidateAccessToken() throws Exception { + + String introspectionUrl = tenantInfo.getDomain().equalsIgnoreCase("carbon.super") ? + OAuth2Constant.INTRO_SPEC_ENDPOINT : OAuth2Constant.TENANT_INTRO_SPEC_ENDPOINT; + org.json.simple.JSONObject responseObj = introspectTokenWithTenant(client, accessToken, introspectionUrl, + username, userPassword); + Assert.assertNotNull(responseObj, "Validate access token failed. response is invalid."); + Assert.assertEquals(responseObj.get("active"), true, "Token Validation failed"); + } + @Test(groups = "wso2.is", description = "Send client credentials token request with invalid client Id.", dependsOnMethods = "testGetTokenUsingClientCredentialsGrant") public void testGetTokenUsingCCGrantWithInvalidClientId() throws Exception { @@ -215,7 +226,7 @@ public void testGetTokenUsingCCGrantWithInvalidClientId() throws Exception { "Token response indicated success. Token request should fail with invalid client id."); TokenErrorResponse accessTokenResponse = (TokenErrorResponse) tokenResponse; - ErrorObject errorObject = accessTokenResponse.getErrorObject(); + ErrorObject errorObject = accessTokenResponse.getErrorObject(); Assert.assertEquals(errorObject.getHTTPStatusCode(), HttpStatus.SC_UNAUTHORIZED, "Invalid access token response doesn't contain bad request status code."); Assert.assertEquals(errorObject.getCode(), "invalid_client", @@ -245,7 +256,7 @@ public void testGetTokenUsingCCGrantWithInvalidClientCredentials() throws Except "Token response indicated success. Token request should fail with invalid client id."); TokenErrorResponse accessTokenResponse = (TokenErrorResponse) tokenResponse; - ErrorObject errorObject = accessTokenResponse.getErrorObject(); + ErrorObject errorObject = accessTokenResponse.getErrorObject(); Assert.assertEquals(errorObject.getHTTPStatusCode(), HttpStatus.SC_UNAUTHORIZED, "Invalid access token response doesn't contain bad request status code."); Assert.assertEquals(errorObject.getCode(), "invalid_client", @@ -288,15 +299,20 @@ public void testGetTokenUsingCCGrantWithoutCredentials() throws Exception { "Invalid access token response doesn't contain required error description."); } - @Test(groups = "wso2.is", description = "Validate access token", - dependsOnMethods = "testGetTokenUsingClientCredentialsGrant") - public void testValidateAccessToken() throws Exception { - - String introspectionUrl = tenantInfo.getDomain().equalsIgnoreCase("carbon.super") ? - OAuth2Constant.INTRO_SPEC_ENDPOINT : OAuth2Constant.TENANT_INTRO_SPEC_ENDPOINT; - org.json.simple.JSONObject responseObj = introspectTokenWithTenant(client, accessToken, introspectionUrl, - username, userPassword); - Assert.assertNotNull(responseObj, "Validate access token failed. response is invalid."); - Assert.assertEquals(responseObj.get("active"), true, "Token Validation failed"); + @Test(groups = "wso2.is", description = "Perform client credentials token request tests for JWT token type.", + dependsOnMethods = "testGetTokenUsingCCGrantWithoutCredentials") + public void testGetTokenUsingCCGrantForJWTToken() throws Exception { + + AccessTokenConfiguration accessTokenConfig = new AccessTokenConfiguration().type("JWT"); + accessTokenConfig.setUserAccessTokenExpiryInSeconds(3600L); + accessTokenConfig.setApplicationAccessTokenExpiryInSeconds(3600L); + + oidcConfig.setAccessToken(accessTokenConfig); + updateApplicationInboundConfig(applicationId, oidcConfig, OIDC); + testGetTokenUsingClientCredentialsGrant(); + testValidateAccessToken(); + testGetTokenUsingCCGrantWithInvalidClientId(); + testGetTokenUsingCCGrantWithInvalidClientCredentials(); + testGetTokenUsingCCGrantWithoutCredentials(); } } From b171a8e17cd19f4b327da73e8192945bc0e79a78 Mon Sep 17 00:00:00 2001 From: Thumimku Date: Wed, 23 Oct 2024 11:06:26 +0530 Subject: [PATCH 3/3] fix comments --- .../test/oauth2/OAuth2ServiceClientCredentialTestCase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java index 2c315cf9de..932b390e7e 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2ServiceClientCredentialTestCase.java @@ -166,7 +166,7 @@ public void testGetTokenUsingClientCredentialsGrant() throws Exception { HTTPResponse tokenHTTPResp = request.toHTTPRequest().send(); Assert.assertNotNull(tokenHTTPResp, "Access token http response is null."); Assert.assertEquals(tokenHTTPResp.getContentType().toString(), "application/json", - "Token response did not indicate correct token response"); + "Token response did not indicate correct token response."); TokenResponse tokenResponse = TokenResponse.parse(tokenHTTPResp); Assert.assertTrue(tokenResponse.indicatesSuccess(), "Token response did not indicate success. Token request has failed."); @@ -270,7 +270,6 @@ public void testGetTokenUsingCCGrantWithInvalidClientCredentials() throws Except dependsOnMethods = "testGetTokenUsingCCGrantWithInvalidClientCredentials") public void testGetTokenUsingCCGrantWithoutCredentials() throws Exception { - List parameters = new ArrayList<>(); parameters.add(new BasicNameValuePair("grant_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS));