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();