Skip to content

Commit

Permalink
Merge pull request #21705 from madurangasiriwardena/sms
Browse files Browse the repository at this point in the history
Enable auto redirect for the http client
  • Loading branch information
madurangasiriwardena authored Nov 27, 2024
2 parents 3a6167e + 0cac5a3 commit d7923df
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
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.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.cookie.RFC6265CookieSpecProvider;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
Expand All @@ -41,6 +39,7 @@
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
import org.wso2.carbon.automation.engine.context.TestUserMode;
import org.wso2.identity.integration.test.base.MockClientCallback;
import org.wso2.identity.integration.test.base.MockSMSProvider;
import org.wso2.identity.integration.test.oidc.OIDCAbstractIntegrationTest;
import org.wso2.identity.integration.test.oidc.OIDCUtilTest;
Expand All @@ -59,8 +58,6 @@
import org.wso2.identity.integration.test.utils.OAuth2Constant;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -93,6 +90,8 @@ public class PasswordlessSMSOTPAuthTestCase extends OIDCAbstractIntegrationTest
private String authorizationCode;

private MockSMSProvider mockSMSProvider;
private MockClientCallback mockClientCallback;

private TestUserMode userMode;

@Factory(dataProvider = "testExecutionContextProvider")
Expand All @@ -116,6 +115,10 @@ public void testInit() throws Exception {
super.init(userMode);
mockSMSProvider = new MockSMSProvider();
mockSMSProvider.start();

mockClientCallback = new MockClientCallback();
mockClientCallback.start();

super.init();

Lookup<CookieSpecProvider> cookieSpecRegistry = RegistryBuilder.<CookieSpecProvider>create()
Expand All @@ -127,13 +130,8 @@ public void testInit() throws Exception {
client = HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setDefaultCookieSpecRegistry(cookieSpecRegistry)
.setRedirectStrategy(new DefaultRedirectStrategy() {
@Override
protected boolean isRedirectable(String method) {

return false;
}
}).build();
.setRedirectStrategy(new LaxRedirectStrategy())
.build();

backendURL = backendURL.replace("services/", "");

Expand Down Expand Up @@ -172,6 +170,7 @@ public void atEnd() throws Exception {
scim2RestClient.closeHttpClient();

mockSMSProvider.stop();
mockClientCallback.stop();
}

@Test(groups = "wso2.is", description = "Test passwordless authentication with SMS OTP")
Expand All @@ -190,19 +189,13 @@ private void sendAuthorizeRequest() throws Exception {
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE));
urlParameters.add(new BasicNameValuePair("client_id", oidcApplication.getClientId()));
urlParameters.add(new BasicNameValuePair("redirect_uri", OAuth2Constant.CALLBACK_URL));
urlParameters.add(new BasicNameValuePair("redirect_uri", MockClientCallback.CALLBACK_URL));

urlParameters.add(new BasicNameValuePair("scope", "openid"));

HttpResponse response = sendPostRequestWithParameters(client, urlParameters,
getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain()));

Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION);
assertNotNull(locationHeader, "Location header for authorize request");
EntityUtils.consume(response.getEntity());

response = sendGetRequest(client, locationHeader.getValue());

Map<String, Integer> keyPositionMap = new HashMap<>(1);
keyPositionMap.put("name=\"sessionDataKey\"", 1);
List<DataExtractUtil.KeyValue> keyValues = DataExtractUtil.extractDataFromResponse(response, keyPositionMap);
Expand All @@ -217,17 +210,9 @@ private void performUserLogin() throws Exception {

sendLoginPostForIdentifier(client, sessionDataKey, userObject.getUserName());
HttpResponse response = sendLoginPostForOtp(client, sessionDataKey, mockSMSProvider.getOTP());

Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION);
assertNotNull(locationHeader, "Location header");
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");
EntityUtils.consume(response.getEntity());

authorizationCode = getAuthorizationCodeFromURL(locationHeader.getValue());
authorizationCode = mockClientCallback.getAuthorizationCode();
assertNotNull(authorizationCode);
}

Expand Down Expand Up @@ -256,7 +241,7 @@ private HttpResponse sendTokenRequestForCodeGrant() throws Exception {
List<NameValuePair> 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("redirect_uri", MockClientCallback.CALLBACK_URL));
urlParameters.add(new BasicNameValuePair("client_id", oidcApplication.getClientSecret()));

urlParameters.add(new BasicNameValuePair("scope", "openid"));
Expand All @@ -272,21 +257,11 @@ private HttpResponse sendTokenRequestForCodeGrant() throws Exception {
getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain()));
}

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 OIDCApplication initOIDCApplication() {

OIDCApplication playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName,
OIDCUtilTest.playgroundAppOneAppContext,
OAuth2Constant.CALLBACK_URL);
MockClientCallback.CALLBACK_URL);
return playgroundApp;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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.base;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.extension.ResponseTransformerV2;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import com.github.tomakehurst.wiremock.http.Response;
import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
import org.wso2.identity.integration.common.utils.ISIntegrationTest;
import org.wso2.identity.integration.test.util.Utils;

import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;

/**
* Mock client callback endpoint to test OIDC related flows.
*/
public class MockClientCallback {

public static final String CALLBACK_URL = "https://localhost:8091/dummyApp/oauth2client";

private final AtomicReference<String> authorizationCode = new AtomicReference<>();

private WireMockServer wireMockServer;

public void start() {

wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig()
.httpsPort(8091)
.httpDisabled(true)
.keystorePath(Paths.get(Utils.getResidentCarbonHome(), "repository", "resources", "security",
ISIntegrationTest.KEYSTORE_NAME).toAbsolutePath().toString())
.keystorePassword("wso2carbon")
.keyManagerPassword("wso2carbon")
.extensions(new ResponseTemplateTransformer(null, true, null, null),
new ResponseTransformerV2() {

@Override
public Response transform(Response response, ServeEvent serveEvent) {

authorizationCode.set(serveEvent.getRequest().getQueryParams().get("code").firstValue());
return response;
}

@Override
public boolean applyGlobally() {
return false;
}

@Override
public String getName() {
return "authz-code-transformer";
}
}));

wireMockServer.start();

// Configure the mock client endpoints.
configureMockEndpoints();
}

public void stop() {

if (wireMockServer != null) {
wireMockServer.stop();
}
}

private void configureMockEndpoints() {

try {
wireMockServer.stubFor(get(urlPathEqualTo("/dummyApp/oauth2client"))
.withQueryParam("code", matching(".*"))
.willReturn(aResponse()
.withTransformers("response-template", "authz-code-transformer")
.withStatus(200)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public String getAuthorizationCode() {

return authorizationCode.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public void start() {

wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig()
.httpsPort(8089)
.httpDisabled(true)
.keystorePath(Paths.get(Utils.getResidentCarbonHome(), "repository", "resources", "security",
ISIntegrationTest.KEYSTORE_NAME).toAbsolutePath().toString())
.keystorePassword("wso2carbon")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void start() {

wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig()
.httpsPort(8090)
.httpDisabled(true)
.keystorePath(Paths.get(Utils.getResidentCarbonHome(), "repository", "resources", "security",
ISIntegrationTest.KEYSTORE_NAME).toAbsolutePath().toString())
.keystorePassword("wso2carbon")
Expand Down Expand Up @@ -93,7 +94,7 @@ public String getName() {

wireMockServer.start();

// Configure the mock OIDC endpoints.
// Configure the mock SMS endpoints.
configureMockEndpoints();
}

Expand Down

0 comments on commit d7923df

Please sign in to comment.