From ee30ffb15202598584355a54569a9e53911a3223 Mon Sep 17 00:00:00 2001 From: rmsamitha Date: Tue, 5 Nov 2024 21:08:33 +0530 Subject: [PATCH] Introduce proxy support for backend oauth security --- .../OAuthConfiguredHTTPEndpoint.java | 4 +- .../synapse/endpoints/ProxyConfigs.java | 81 ++++++++ .../synapse/endpoints/auth/AuthConstants.java | 8 + .../auth/oauth/AuthorizationCodeHandler.java | 12 +- .../auth/oauth/ClientCredentialsHandler.java | 7 +- .../endpoints/auth/oauth/OAuthClient.java | 173 +++++++++++++++--- .../endpoints/auth/oauth/OAuthHandler.java | 14 +- .../endpoints/auth/oauth/OAuthUtils.java | 100 +++++++++- .../oauth/PasswordCredentialsHandler.java | 8 +- .../endpoints/auth/oauth/OAuthClientTest.java | 5 +- .../endpoints/auth/oauth/OAuthUtilsTest.java | 4 +- 11 files changed, 365 insertions(+), 51 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/synapse/endpoints/ProxyConfigs.java diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/OAuthConfiguredHTTPEndpoint.java b/modules/core/src/main/java/org/apache/synapse/endpoints/OAuthConfiguredHTTPEndpoint.java index ad7a165661..070b417718 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/OAuthConfiguredHTTPEndpoint.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/OAuthConfiguredHTTPEndpoint.java @@ -64,10 +64,10 @@ public void send(MessageContext synCtx) { } catch (AuthException e) { handleError(synCtx, - "Could not generate access token for oauth configured http endpoint " + this.getName(), e); + "Could not generate access token for oauth configured http endpoint " + this.getName() + ".", e); } catch (AxisFault axisFault) { handleError(synCtx, - "Error cloning the message context for oauth configured http endpoint " + this.getName(), + "Error cloning the message context for oauth configured http endpoint " + this.getName() + ".", axisFault); } } diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/ProxyConfigs.java b/modules/core/src/main/java/org/apache/synapse/endpoints/ProxyConfigs.java new file mode 100644 index 0000000000..e9a107c8a1 --- /dev/null +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/ProxyConfigs.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://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.apache.synapse.endpoints; + +/** + * This class represents a model for proxy configurations which is used for the OAuth authentication of endpoints + */ +public class ProxyConfigs { + private String proxyHost; + private String proxyPort; + private String proxyUsername; + private String proxyPassword; + private String proxyProtocol; + private boolean proxyEnabled; + + public void setProxyEnabled(boolean proxyEnabled) { + this.proxyEnabled = proxyEnabled; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public void setProxyPort(String proxyPort) { + this.proxyPort = proxyPort; + } + + public void setProxyUsername(String proxyUsername) { + this.proxyUsername = proxyUsername; + } + + public void setProxyPassword(String proxyPassword) { + this.proxyPassword = proxyPassword; + } + + public void setProxyProtocol(String proxyProtocol) { + this.proxyProtocol = proxyProtocol; + } + + public boolean isProxyEnabled() { + return proxyEnabled; + } + + public String getProxyHost() { + return proxyHost; + } + + public String getProxyPort() { + return proxyPort; + } + + public String getProxyUsername() { + return proxyUsername; + } + + public String getProxyPassword() { + return proxyPassword; + } + + public String getProxyProtocol() { + return proxyProtocol; + } +} + + diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/AuthConstants.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/AuthConstants.java index ab96cbc33e..6c13dd5a8e 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/AuthConstants.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/AuthConstants.java @@ -87,4 +87,12 @@ public class AuthConstants { public static final String BASIC_AUTH_USERNAME = "username"; public static final String BASIC_AUTH_PASSWORD = "password"; + public static final String PROXY_CONFIGS = "proxyConfigs"; + public static final String PROXY_HOST = "proxyHost"; + public static final String PROXY_PORT = "proxyPort"; + public static final String PROXY_USERNAME = "proxyUsername"; + public static final String PROXY_PASSWORD = "proxyPassword"; + public static final String OAUTH_PROXY_PROTOCOL = "proxyProtocol"; + + public static final String HTTPS_PROTOCOL = "https"; } diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/AuthorizationCodeHandler.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/AuthorizationCodeHandler.java index 28576ba590..336d1c83ff 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/AuthorizationCodeHandler.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/AuthorizationCodeHandler.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; +import org.apache.synapse.endpoints.ProxyConfigs; import org.apache.synapse.endpoints.auth.AuthConstants; import org.apache.synapse.endpoints.auth.AuthException; @@ -35,13 +36,12 @@ public class AuthorizationCodeHandler extends OAuthHandler { private final String refreshToken; - public AuthorizationCodeHandler(String tokenApiUrl, String clientId, String clientSecret, - String refreshToken, String authMode, int connectionTimeout, - int connectionRequestTimeout, int socketTimeout, - TokenCacheProvider tokenCacheProvider) { + public AuthorizationCodeHandler(String tokenApiUrl, String clientId, String clientSecret, String refreshToken, + String authMode, int connectionTimeout, int connectionRequestTimeout, int socketTimeout, + TokenCacheProvider tokenCacheProvider, ProxyConfigs proxyConfigs) { - super(tokenApiUrl, clientId, clientSecret, authMode, connectionTimeout, connectionRequestTimeout, - socketTimeout, tokenCacheProvider); + super(tokenApiUrl, clientId, clientSecret, authMode, connectionTimeout, connectionRequestTimeout, socketTimeout, + tokenCacheProvider,proxyConfigs); this.refreshToken = refreshToken; } diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/ClientCredentialsHandler.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/ClientCredentialsHandler.java index 37dfef724e..61e6b5578e 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/ClientCredentialsHandler.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/ClientCredentialsHandler.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; +import org.apache.synapse.endpoints.ProxyConfigs; import org.apache.synapse.endpoints.auth.AuthConstants; import org.apache.synapse.endpoints.auth.AuthException; @@ -34,11 +35,11 @@ public class ClientCredentialsHandler extends OAuthHandler { public ClientCredentialsHandler(String tokenApiUrl, String clientId, String clientSecret, String authMode, - int connectionTimeout, int connectionRequestTimeout, int socketTimeout, - TokenCacheProvider tokenCacheProvider) { + int connectionTimeout, int connectionRequestTimeout, int socketTimeout, + TokenCacheProvider tokenCacheProvider, ProxyConfigs proxyConfigs) { super(tokenApiUrl, clientId, clientSecret, authMode, connectionTimeout, connectionRequestTimeout, socketTimeout, - tokenCacheProvider); + tokenCacheProvider, proxyConfigs); } @Override diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthClient.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthClient.java index e3c42ac9a8..22a7a2fbad 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthClient.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthClient.java @@ -26,9 +26,14 @@ import org.apache.axis2.description.Parameter; import org.apache.axis2.description.TransportOutDescription; import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; @@ -39,23 +44,32 @@ import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.NoConnectionReuseStrategy; +import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.impl.conn.DefaultProxyRoutePlanner; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.synapse.MessageContext; import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.endpoints.ProxyConfigs; import org.apache.synapse.endpoints.auth.AuthConstants; import org.apache.synapse.endpoints.auth.AuthException; import org.apache.synapse.transport.http.conn.SSLContextDetails; import org.apache.synapse.transport.nhttp.config.ClientConnFactoryBuilder; import org.apache.synapse.transport.nhttp.util.SecureVaultValueReader; +import org.apache.synapse.util.xpath.KeyStoreManager; import org.wso2.securevault.SecretResolver; import org.wso2.securevault.SecretResolverFactory; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; import javax.xml.namespace.QName; import java.io.BufferedReader; import java.io.FileInputStream; @@ -66,7 +80,11 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; +import java.security.KeyManagementException; import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.KeyStoreException; +import java.util.Arrays; import java.util.Map; /** @@ -84,28 +102,35 @@ public class OAuthClient { private static final String HTTP_CONNECTION = "http"; private static final String HTTPS_CONNECTION = "https"; private static final String ALL_HOSTS = "*"; + public static final String HOST_NAME_VERIFIER = "httpclient.hostnameVerifier"; + public static final String ALLOW_ALL = "AllowAll"; + public static final String STRICT = "Strict"; + public static final String DEFAULT_AND_LOCALHOST = "DefaultAndLocalhost"; + public static final int MAX_TOTAL_POOL_SIZE = 100; + public static final int DEFAULT_MAX_PER_ROUTE = 50; /** * Method to generate the access token from an OAuth server * - * @param tokenApiUrl The token url of the server - * @param payload The payload of the request - * @param credentials The encoded credentials + * @param tokenApiUrl The token url of the server + * @param payload The payload of the request + * @param credentials The encoded credentials + * @param proxyConfigs The proxy configurations * @return accessToken String - * @throws AuthException In the event of an unexpected HTTP status code return from the server or access_token - * key missing in the response payload - * @throws IOException In the event of a problem parsing the response from the server + * @throws AuthException In the event of an unexpected HTTP status code return from the server or access_token key + * missing in the response payload + * @throws IOException In the event of a problem parsing the response from the server */ public static String generateToken(String tokenApiUrl, String payload, String credentials, MessageContext messageContext, Map customHeaders, - int connectionTimeout, int connectionRequestTimeout, int socketTimeout) throws AuthException, IOException { + int connectionTimeout, int connectionRequestTimeout, int socketTimeout, ProxyConfigs proxyConfigs) throws AuthException, IOException { if (log.isDebugEnabled()) { log.debug("Initializing token generation request: [token-endpoint] " + tokenApiUrl); } try (CloseableHttpClient httpClient = getSecureClient(tokenApiUrl, messageContext, connectionTimeout, - connectionRequestTimeout, socketTimeout)) { + connectionRequestTimeout, socketTimeout, proxyConfigs)) { HttpPost httpPost = new HttpPost(tokenApiUrl); httpPost.setHeader(AuthConstants.CONTENT_TYPE_HEADER, AuthConstants.APPLICATION_X_WWW_FORM_URLENCODED); if (!(customHeaders == null || customHeaders.isEmpty())) { @@ -178,40 +203,134 @@ private static String extractToken(CloseableHttpResponse response) throws AuthEx * @throws AuthException */ private static CloseableHttpClient getSecureClient(String tokenUrl, MessageContext messageContext, - int connectionTimeout, int connectionRequestTimeout, int socketTimeout) + int connectionTimeout, int connectionRequestTimeout, int socketTimeout, ProxyConfigs proxyConfigs) throws AuthException { + + if (proxyConfigs.isProxyEnabled()) { + return getSecureClientWithProxy(connectionTimeout, connectionRequestTimeout, socketTimeout, proxyConfigs); + } else { + return getSecureClientWithoutProxy(tokenUrl, messageContext, connectionTimeout, connectionRequestTimeout, + socketTimeout); + } + } + private static CloseableHttpClient getSecureClientWithoutProxy(String tokenUrl, MessageContext messageContext, + int connectionTimeout, int connectionRequestTimeout, int socketTimeout) throws AuthException { SSLContext sslContext; - ConfigurationContext configurationContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext(). - getConfigurationContext(); + ConfigurationContext configurationContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext() + .getConfigurationContext(); TransportOutDescription transportOut = configurationContext.getAxisConfiguration().getTransportOut("https"); try { - ClientConnFactoryBuilder clientConnFactoryBuilder = - new ClientConnFactoryBuilder(transportOut, configurationContext).parseSSL(); - + ClientConnFactoryBuilder clientConnFactoryBuilder = new ClientConnFactoryBuilder(transportOut, + configurationContext).parseSSL(); sslContext = getSSLContextWithUrl(tokenUrl, clientConnFactoryBuilder.getSslByHostMap(), - clientConnFactoryBuilder.getSSLContextDetails()); + clientConnFactoryBuilder.getSSLContextDetails()); } catch (AxisFault e) { throw new AuthException("Error while reading SSL configs. Using default Keystore and Truststore", e); } - SSLConnectionSocketFactory sslConnectionFactory = - new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); - RequestConfig config = RequestConfig.custom() - .setConnectTimeout(connectionTimeout) - .setConnectionRequestTimeout(connectionRequestTimeout) - .setSocketTimeout(socketTimeout).build(); - Registry registry = RegistryBuilder.create(). - register(HTTPS_CONNECTION, sslConnectionFactory).register(HTTP_CONNECTION, new PlainConnectionSocketFactory()) - .build(); + SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslContext, + NoopHostnameVerifier.INSTANCE); + RequestConfig config = RequestConfig.custom().setConnectTimeout(connectionTimeout) + .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build(); + Registry registry = RegistryBuilder. create() + .register(HTTPS_CONNECTION, sslConnectionFactory) + .register(HTTP_CONNECTION, new PlainConnectionSocketFactory()).build(); BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(registry); - CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config) - .setConnectionManager(connManager) - .setSSLSocketFactory(sslConnectionFactory).build(); + .setConnectionManager(connManager).setSSLSocketFactory(sslConnectionFactory).build(); return client; } + private static CloseableHttpClient getSecureClientWithProxy(int connectionTimeout, int connectionRequestTimeout, + int socketTimeout, ProxyConfigs proxyConfigs) throws AuthException { + + PoolingHttpClientConnectionManager pool = getPoolingHttpClientConnectionManager( + proxyConfigs.getProxyProtocol()); + pool.setMaxTotal(MAX_TOTAL_POOL_SIZE); + pool.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); + + RequestConfig params = RequestConfig.custom().build(); + HttpClientBuilder clientBuilder = HttpClients.custom().setConnectionManager(pool) + .setDefaultRequestConfig(params); + + HttpHost host = new HttpHost(proxyConfigs.getProxyHost(), Integer.parseInt(proxyConfigs.getProxyPort()), + proxyConfigs.getProxyProtocol()); + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(host); + RequestConfig config = RequestConfig.custom().setConnectTimeout(connectionTimeout) + .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build(); + clientBuilder = clientBuilder.setRoutePlanner(routePlanner); + + if (StringUtils.isNotBlank(proxyConfigs.getProxyUsername()) && StringUtils.isNotBlank( + proxyConfigs.getProxyPassword())) { + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials( + new AuthScope(proxyConfigs.getProxyHost(), Integer.parseInt(proxyConfigs.getProxyPort())), + new UsernamePasswordCredentials(proxyConfigs.getProxyUsername(), proxyConfigs.getProxyPassword())); + clientBuilder = clientBuilder.setDefaultRequestConfig(config) + .setDefaultCredentialsProvider(credentialsProvider); + } + + return clientBuilder.build(); + } + + private static PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager(String protocol) + throws AuthException { + + PoolingHttpClientConnectionManager poolManager; + if (AuthConstants.HTTPS_PROTOCOL.equals(protocol)) { + SSLConnectionSocketFactory socketFactory = createSocketFactory(); + org.apache.http.config.Registry socketFactoryRegistry = + RegistryBuilder. create() + .register(AuthConstants.HTTPS_PROTOCOL, socketFactory).build(); + poolManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + } else { + poolManager = new PoolingHttpClientConnectionManager(); + } + return poolManager; + } + + private static SSLConnectionSocketFactory createSocketFactory() throws AuthException { + SSLContext sslContext; + + char[] trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); + String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); + try { + KeyStore trustStore = KeyStoreManager.getKeyStore(trustStoreLocation, Arrays.toString(trustStorePassword), + "JKS"); + sslContext = SSLContexts.custom().loadTrustMaterial(trustStore).build(); + + HostnameVerifier hostnameVerifier; + String hostnameVerifierOption = System.getProperty(HOST_NAME_VERIFIER); + + if (ALLOW_ALL.equalsIgnoreCase(hostnameVerifierOption)) { + hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + } else if (STRICT.equalsIgnoreCase(hostnameVerifierOption)) { + hostnameVerifier = SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; + } else if (DEFAULT_AND_LOCALHOST.equalsIgnoreCase(hostnameVerifierOption)) { + hostnameVerifier = new HostnameVerifier() { + final String[] localhosts = { "::1", "127.0.0.1", "localhost", "localhost.localdomain" }; + + @Override + public boolean verify(String urlHostName, SSLSession session) { + return SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER.verify(urlHostName, + session) || Arrays.asList(localhosts).contains(urlHostName); + } + }; + } else { + hostnameVerifier = SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; + } + + return new SSLConnectionSocketFactory(sslContext, hostnameVerifier); + } catch (NoSuchAlgorithmException e) { + throw new AuthException(e); + } catch (KeyStoreException e) { + throw new AuthException(e); + } catch (KeyManagementException e) { + throw new AuthException(e); + } + } + /** * Returns SSL Context for the token endpoint. * diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthHandler.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthHandler.java index a520b43000..4e11a71933 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthHandler.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthHandler.java @@ -25,6 +25,7 @@ import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.endpoints.ProxyConfigs; import org.apache.synapse.endpoints.auth.AuthConstants; import org.apache.synapse.endpoints.auth.AuthException; import org.apache.synapse.endpoints.auth.AuthHandler; @@ -55,9 +56,11 @@ public abstract class OAuthHandler implements AuthHandler { protected final int socketTimeout; private final TokenCacheProvider tokenCacheProvider; + private ProxyConfigs proxyConfigs; + protected OAuthHandler(String tokenApiUrl, String clientId, String clientSecret, String authMode, - int connectionTimeout, int connectionRequestTimeout, int socketTimeout, - TokenCacheProvider tokenCacheProvider) { + int connectionTimeout, int connectionRequestTimeout, int socketTimeout, + TokenCacheProvider tokenCacheProvider, ProxyConfigs proxyConfigs) { this.id = OAuthUtils.getRandomOAuthHandlerID(); this.tokenApiUrl = tokenApiUrl; @@ -68,6 +71,7 @@ protected OAuthHandler(String tokenApiUrl, String clientId, String clientSecret, this.connectionRequestTimeout = connectionRequestTimeout; this.socketTimeout = socketTimeout; this.tokenCacheProvider = tokenCacheProvider; + this.proxyConfigs = proxyConfigs; } @Override @@ -98,7 +102,7 @@ private String getToken(final MessageContext messageContext) throws AuthExceptio token = OAuthClient.generateToken(OAuthUtils.resolveExpression(tokenApiUrl, messageContext), buildTokenRequestPayload(messageContext), getEncodedCredentials(messageContext), messageContext, getResolvedCustomHeadersMap(customHeadersMap, messageContext), - connectionTimeout, connectionRequestTimeout, socketTimeout); + connectionTimeout, connectionRequestTimeout, socketTimeout, proxyConfigs); // Cache the newly generated token tokenCacheProvider.putToken(getId(messageContext), token); @@ -210,6 +214,10 @@ public OMElement serializeOAuthConfiguration(OMFactory omFactory) { clientSecret)); oauthCredentials.addChild(OAuthUtils.createOMElementWithValue(omFactory, AuthConstants.TOKEN_API_URL, tokenApiUrl)); + if (proxyConfigs.isProxyEnabled()) { + OMElement proxyElement = OAuthUtils.createOMProxyConfigs(omFactory, proxyConfigs); + oauthCredentials.addChild(proxyElement); + } if (requestParametersMap != null && !requestParametersMap.isEmpty()) { OMElement requestParameters = OAuthUtils.createOMRequestParams(omFactory, requestParametersMap); oauthCredentials.addChild(requestParameters); diff --git a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthUtils.java b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthUtils.java index 48bb5b4809..6b6ac5241b 100644 --- a/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthUtils.java +++ b/modules/core/src/main/java/org/apache/synapse/endpoints/auth/oauth/OAuthUtils.java @@ -31,6 +31,7 @@ import org.apache.synapse.config.xml.XMLConfigConstants; import org.apache.synapse.core.axis2.Axis2MessageContext; import org.apache.synapse.endpoints.OAuthConfiguredHTTPEndpoint; +import org.apache.synapse.endpoints.ProxyConfigs; import org.apache.synapse.endpoints.auth.AuthConstants; import org.apache.synapse.endpoints.auth.AuthException; import org.apache.synapse.mediators.Value; @@ -119,6 +120,12 @@ private static AuthorizationCodeHandler getAuthorizationCodeHandler(OMElement au String refreshToken = getChildValue(authCodeElement, AuthConstants.OAUTH_REFRESH_TOKEN); String tokenApiUrl = getChildValue(authCodeElement, AuthConstants.TOKEN_API_URL); String authMode = getChildValue(authCodeElement, AuthConstants.OAUTH_AUTHENTICATION_MODE); + + ProxyConfigs proxyConfigs = getProxyConfigs(authCodeElement); + if (proxyConfigs == null) { + return null; + } + int connectionTimeout = getOauthTimeouts(authCodeElement, AuthConstants.OAUTH_CONNECTION_TIMEOUT); int connectionRequestTimeout = getOauthTimeouts(authCodeElement, AuthConstants.OAUTH_CONNECTION_REQUEST_TIMEOUT); @@ -130,7 +137,7 @@ private static AuthorizationCodeHandler getAuthorizationCodeHandler(OMElement au } AuthorizationCodeHandler handler = new AuthorizationCodeHandler(tokenApiUrl, clientId, clientSecret, refreshToken, authMode, connectionTimeout, connectionRequestTimeout, socketTimeout, - TokenCacheFactory.getTokenCache()); + TokenCacheFactory.getTokenCache(), proxyConfigs); if (hasRequestParameters(authCodeElement)) { Map requestParameters = getRequestParameters(authCodeElement); if (requestParameters == null) { @@ -161,6 +168,12 @@ private static ClientCredentialsHandler getClientCredentialsHandler( String clientSecret = getChildValue(clientCredentialsElement, AuthConstants.OAUTH_CLIENT_SECRET); String tokenApiUrl = getChildValue(clientCredentialsElement, AuthConstants.TOKEN_API_URL); String authMode = getChildValue(clientCredentialsElement, AuthConstants.OAUTH_AUTHENTICATION_MODE); + + ProxyConfigs proxyConfigs = getProxyConfigs(clientCredentialsElement); + if (proxyConfigs == null) { + return null; + } + int connectionTimeout = getOauthTimeouts(clientCredentialsElement, AuthConstants.OAUTH_CONNECTION_TIMEOUT); int connectionRequestTimeout = getOauthTimeouts(clientCredentialsElement, AuthConstants.OAUTH_CONNECTION_REQUEST_TIMEOUT); @@ -171,7 +184,7 @@ private static ClientCredentialsHandler getClientCredentialsHandler( return null; } ClientCredentialsHandler handler = new ClientCredentialsHandler(tokenApiUrl, clientId, clientSecret, authMode, - connectionTimeout, connectionRequestTimeout, socketTimeout, TokenCacheFactory.getTokenCache()); + connectionTimeout, connectionRequestTimeout, socketTimeout, TokenCacheFactory.getTokenCache(), proxyConfigs); if (hasRequestParameters(clientCredentialsElement)) { Map requestParameters = getRequestParameters(clientCredentialsElement); if (requestParameters == null) { @@ -204,6 +217,12 @@ private static PasswordCredentialsHandler getPasswordCredentialsHandler( String password = getChildValue(passwordCredentialsElement, AuthConstants.OAUTH_PASSWORD); String tokenApiUrl = getChildValue(passwordCredentialsElement, AuthConstants.TOKEN_API_URL); String authMode = getChildValue(passwordCredentialsElement, AuthConstants.OAUTH_AUTHENTICATION_MODE); + + ProxyConfigs proxyConfigs = getProxyConfigs(passwordCredentialsElement); + if (proxyConfigs == null) { + return null; + } + int connectionTimeout = getOauthTimeouts(passwordCredentialsElement, AuthConstants.OAUTH_CONNECTION_TIMEOUT); int connectionRequestTimeout = getOauthTimeouts(passwordCredentialsElement, AuthConstants.OAUTH_CONNECTION_REQUEST_TIMEOUT); @@ -215,7 +234,7 @@ private static PasswordCredentialsHandler getPasswordCredentialsHandler( } PasswordCredentialsHandler handler = new PasswordCredentialsHandler(tokenApiUrl, clientId, clientSecret, username, password, authMode, connectionTimeout, connectionRequestTimeout, socketTimeout, - TokenCacheFactory.getTokenCache()); + TokenCacheFactory.getTokenCache(), proxyConfigs); if (hasRequestParameters(passwordCredentialsElement)) { Map requestParameters = getRequestParameters(passwordCredentialsElement); if (requestParameters == null) { @@ -233,6 +252,50 @@ private static PasswordCredentialsHandler getPasswordCredentialsHandler( return handler; } + /** + * Method to get the proxy configurations + * + * @param grantTypeOMElement OMElement containing the grant type related OMElement + * @return ProxyConfigs object. Return null if proxy configurations are invalid + */ + private static ProxyConfigs getProxyConfigs(OMElement grantTypeOMElement) { + + ProxyConfigs proxyConfigs = new ProxyConfigs(); + OMElement proxyConfigsOM = grantTypeOMElement.getFirstChildWithName( + new QName(SynapseConstants.SYNAPSE_NAMESPACE, AuthConstants.PROXY_CONFIGS)); + if (proxyConfigsOM == null || proxyConfigsOM.getFirstElement() == null) { + //proxyConfigs Element is not available or it has no child elements + proxyConfigs.setProxyEnabled(false); + } else { + proxyConfigs.setProxyEnabled(true); + proxyConfigs.setProxyHost(getChildValue(proxyConfigsOM, AuthConstants.PROXY_HOST)); + proxyConfigs.setProxyPort(getChildValue(proxyConfigsOM, AuthConstants.PROXY_PORT)); + proxyConfigs.setProxyUsername(getChildValue(proxyConfigsOM, AuthConstants.PROXY_USERNAME)); + proxyConfigs.setProxyPassword(getChildValue(proxyConfigsOM, AuthConstants.PROXY_PASSWORD)); + proxyConfigs.setProxyProtocol(getChildValue(proxyConfigsOM, AuthConstants.OAUTH_PROXY_PROTOCOL)); + + if (StringUtils.isEmpty(proxyConfigs.getProxyHost())) { + log.error( + "'proxyHost' is not set for the proxy configurations. So error occurred while getting the " + + "related Oauth handler."); + return null; + } + if (StringUtils.isEmpty(proxyConfigs.getProxyPort())) { + log.error( + "'proxyPort' is not set for the proxy configurations. So error occurred while getting the " + + "related Oauth handler."); + return null; + } + if (StringUtils.isEmpty(proxyConfigs.getProxyProtocol())) { + log.error( + "'proxyProtocol' is not set for the proxy configurations. So error occurred while getting the" + + " related Oauth handler."); + return null; + } + } + return proxyConfigs; + } + /** * Method to return the request parameters as a Map. * @@ -551,4 +614,35 @@ public static OMElement createOMRequestParams(OMFactory omFactory, Map