diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml index 95a93bf93321..a47d7ae4c83c 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml @@ -62,6 +62,11 @@ org.wso2.carbon.identity.core provided + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.authentication.framework + provided + org.wso2.carbon org.wso2.carbon.utils @@ -200,6 +205,7 @@ org.wso2.carbon.identity.user.registration.stub.*;version="${carbon.identity.package.import.version.range}", org.apache.axis2.*;version="${axis2.osgi.version.range}", org.wso2.carbon.identity.core.util;resolution:=optional;version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.authentication.framework.config;version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.core.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.base;resolution:=optional;version="${carbon.identity.package.import.version.range}", org.wso2.carbon.user.core.*; version="${carbon.kernel.package.import.version.range}", diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/src/main/java/org/wso2/carbon/identity/application/authentication/endpoint/util/AuthenticationEndpointUtil.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/src/main/java/org/wso2/carbon/identity/application/authentication/endpoint/util/AuthenticationEndpointUtil.java index 2c1ea4622448..7b32aa4d8100 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/src/main/java/org/wso2/carbon/identity/application/authentication/endpoint/util/AuthenticationEndpointUtil.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/src/main/java/org/wso2/carbon/identity/application/authentication/endpoint/util/AuthenticationEndpointUtil.java @@ -35,6 +35,7 @@ import org.owasp.encoder.Encode; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.endpoint.util.bean.UserDTO; +import org.wso2.carbon.identity.application.authentication.framework.config.ConfigurationFacade; import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; @@ -74,6 +75,7 @@ public class AuthenticationEndpointUtil { private static final String QUERY_STRING_INITIATOR = "?"; private static final String PADDING_CHAR = "="; private static final String UNDERSCORE = "_"; + private static String serverHostAndPort; private static final String TENANT_DOMAIN_PLACEHOLDER = "${tenantDomain}"; private static final String SUPER_TENANT = "carbon.super"; @@ -254,6 +256,25 @@ public static String getErrorCodeToi18nMapping(String errorCode, String subError */ public static boolean isValidURL(String urlString) { + return validateURL(urlString); + } + + /** + * This method is to validate a multiOptionURI. This method validate absolute URLs. + * default value of multiOptionURL is /authenticationendpoint/ + * @param urlString URL String. + * @return true if valid URL, false otherwise. + */ + public static boolean isValidMultiOptionURI(String urlString) { + + if (validateURL(urlString)) { + return validateCallbackURL(urlString); + } + return false; + } + + private static boolean validateURL(String urlString) { + if (StringUtils.isBlank(urlString)) { String errorMsg = "Invalid URL."; if (log.isDebugEnabled()) { @@ -281,6 +302,68 @@ public static boolean isValidURL(String urlString) { return true; } + private static boolean validateCallbackURL(String callbackURL) { + + String authenticationEndpointURL = ConfigurationFacade.getInstance().getAuthenticationEndpointURL(); + try { + if (isURLRelative(callbackURL)) { + return !callbackURL.startsWith("//"); // Check for protocol-relative URLs. + } else { + String multiOptionURIHostAndPort = getHostAndPort(callbackURL); + /* + If the multiOptionURI is an absolute URL, then the host of the multiOptionURI should be + either host of the server or host of the externalized authenticationEndpointURL. + */ + if (multiOptionURIHostAndPort.equals(getServerHostAndPort()) || + (!isURLRelative(authenticationEndpointURL) && multiOptionURIHostAndPort + .equals(getHostAndPort(authenticationEndpointURL)))) { + return true; + } else { + log.error("No valid host found for the multiOptionURI. URL: " + multiOptionURIHostAndPort + + " is not allowed."); + return false; + } + } + } catch (MalformedURLException | URISyntaxException e) { + if (log.isDebugEnabled()) { + log.debug(e.getMessage(), e); + } + return false; + } + } + + private static String getServerHostAndPort() { + + try { + if (StringUtils.isEmpty(serverHostAndPort)) { + serverHostAndPort = getHostAndPort(buildAbsoluteURL("/")); + } + } catch (MalformedURLException | URLBuilderException e) { + if (log.isDebugEnabled()) { + log.debug(e.getMessage(), e); + } + } + + return serverHostAndPort; + } + + /** + * Extracts the host and port from a given URL string. + * If the URL does not specify a port, only the host is returned. + * + * @param urlString The URL from which to extract the host and port. + * @return A string containing the host and, if specified, the port. + * @throws MalformedURLException If the given string does not represent a valid URL. + */ + private static String getHostAndPort(String urlString) throws MalformedURLException { + + URL url = new URL(urlString); + String host = url.getHost(); + int port = url.getPort(); // Returns -1 if the port is not explicitly specified in the URL + + return port == -1 ? host : host + ":" + port; + } + private static boolean isURLRelative(String uriString) throws URISyntaxException { return !new URI(uriString).isAbsolute();