Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate multiOptionURI parameter #5502

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
<artifactId>org.wso2.carbon.identity.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.application.authentication.framework</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
Expand Down Expand Up @@ -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}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";

Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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();
Expand Down
Loading