Details
diff --git a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
index be7de79..da55815 100644
--- a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
+++ b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
@@ -84,6 +84,7 @@ import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
+import org.keycloak.saml.validators.DestinationValidator;
/**
*
@@ -97,6 +98,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
protected final SamlSessionStore sessionStore;
protected final SamlDeployment deployment;
protected AuthChallenge challenge;
+ private final DestinationValidator destinationValidator = DestinationValidator.forProtocolMap(null);
public AbstractSamlAuthenticationHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
this.facade = facade;
@@ -145,7 +147,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
holder = SAMLRequestParser.parseRequestPostBinding(samlRequest);
}
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
- if (!requestUri.equals(requestAbstractType.getDestination().toString())) {
+ if (! destinationValidator.validate(requestUri, requestAbstractType.getDestination())) {
log.error("expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'");
return AuthOutcome.FAILED;
}
@@ -186,7 +188,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
}
final StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
// validate destination
- if (!requestUri.equals(statusResponse.getDestination())) {
+ if (! destinationValidator.validate(requestUri, statusResponse.getDestination())) {
log.error("Request URI '" + requestUri + "' does not match SAML request destination '" + statusResponse.getDestination() + "'");
return AuthOutcome.FAILED;
}
diff --git a/saml-core/src/main/java/org/keycloak/saml/validators/DestinationValidator.java b/saml-core/src/main/java/org/keycloak/saml/validators/DestinationValidator.java
new file mode 100644
index 0000000..a160790
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/validators/DestinationValidator.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2018 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed 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.keycloak.saml.validators;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Check that Destination field in SAML request/response is either unset or matches the expected one.
+ * @author hmlnarik
+ */
+public class DestinationValidator {
+
+ private static final Pattern PROTOCOL_MAP_PATTERN = Pattern.compile("\\s*([a-zA-Z][a-zA-Z\\d+-.]*)\\s*=\\s*(\\d+)\\s*");
+ private static final String[] DEFAULT_PROTOCOL_TO_PORT_MAP = new String[] { "http=80", "https=443" };
+
+ private final Map<String, Integer> knownPorts;
+ private final Map<Integer, String> knownProtocols;
+
+ private DestinationValidator(Map<String, Integer> knownPorts, Map<Integer, String> knownProtocols) {
+ this.knownPorts = knownPorts;
+ this.knownProtocols = knownProtocols;
+ }
+
+ public static DestinationValidator forProtocolMap(String[] protocolMappings) {
+ if (protocolMappings == null) {
+ protocolMappings = DEFAULT_PROTOCOL_TO_PORT_MAP;
+ }
+
+ Map<String, Integer> knownPorts = new HashMap<>();
+ Map<Integer, String> knownProtocols = new HashMap<>();
+
+ for (String protocolMapping : protocolMappings) {
+ Matcher m = PROTOCOL_MAP_PATTERN.matcher(protocolMapping);
+ if (m.matches()) {
+ Integer port = Integer.valueOf(m.group(2));
+ String proto = m.group(1);
+
+ knownPorts.put(proto, port);
+ knownProtocols.put(port, proto);
+ }
+ }
+
+ return new DestinationValidator(knownPorts, knownProtocols);
+ }
+
+ public boolean validate(String expectedDestination, String actualDestination) {
+ try {
+ return validate(expectedDestination == null ? null : URI.create(expectedDestination), actualDestination);
+ } catch (IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
+ public boolean validate(String expectedDestination, URI actualDestination) {
+ try {
+ return validate(expectedDestination == null ? null : URI.create(expectedDestination), actualDestination);
+ } catch (IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
+ public boolean validate(URI expectedDestination, String actualDestination) {
+ try {
+ return validate(expectedDestination, actualDestination == null ? null : URI.create(actualDestination));
+ } catch (IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
+ public boolean validate(URI expectedDestination, URI actualDestination) {
+ if (actualDestination == null) {
+ return true; // destination is optional
+ }
+
+ if (expectedDestination == null) {
+ return false; // expected destination is mandatory
+ }
+
+ if (Objects.equals(expectedDestination, actualDestination)) {
+ return true;
+ }
+
+ Integer portByScheme = knownPorts.get(expectedDestination.getScheme());
+ String protocolByPort = knownProtocols.get(expectedDestination.getPort());
+
+ URI updatedUri = null;
+ try {
+ if (expectedDestination.getPort() < 0 && portByScheme != null) {
+ updatedUri = new URI(
+ expectedDestination.getScheme(),
+ expectedDestination.getUserInfo(),
+ expectedDestination.getHost(),
+ portByScheme,
+ expectedDestination.getPath(),
+ expectedDestination.getQuery(),
+ expectedDestination.getFragment()
+ );
+ } else if (expectedDestination.getPort() >= 0 && Objects.equals(protocolByPort, expectedDestination.getScheme())) {
+ updatedUri = new URI(
+ expectedDestination.getScheme(),
+ expectedDestination.getUserInfo(),
+ expectedDestination.getHost(),
+ -1,
+ expectedDestination.getPath(),
+ expectedDestination.getQuery(),
+ expectedDestination.getFragment()
+ );
+ }
+ } catch (URISyntaxException ex) {
+ return false;
+ }
+
+ return Objects.equals(updatedUri, actualDestination);
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java b/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
index f6cb9f1..a65f86a 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
@@ -87,6 +87,7 @@ import java.util.List;
import org.keycloak.rotation.HardcodedKeyLocator;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
+import org.keycloak.saml.validators.DestinationValidator;
import org.w3c.dom.Element;
import java.util.*;
@@ -111,6 +112,7 @@ public class SAMLEndpoint {
protected SAMLIdentityProviderConfig config;
protected IdentityProvider.AuthenticationCallback callback;
protected SAMLIdentityProvider provider;
+ private final DestinationValidator destinationValidator;
@Context
private KeycloakSession session;
@@ -122,11 +124,12 @@ public class SAMLEndpoint {
private HttpHeaders headers;
- public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
+ public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback, DestinationValidator destinationValidator) {
this.realm = realm;
this.config = config;
this.callback = callback;
this.provider = provider;
+ this.destinationValidator = destinationValidator;
}
@GET
@@ -238,7 +241,7 @@ public class SAMLEndpoint {
SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
// validate destination
- if (requestAbstractType.getDestination() != null && !session.getContext().getUri().getAbsolutePath().equals(requestAbstractType.getDestination())) {
+ if (! destinationValidator.validate(session.getContext().getUri().getAbsolutePath(), requestAbstractType.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
@@ -456,7 +459,7 @@ public class SAMLEndpoint {
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
// validate destination
- if (statusResponse.getDestination() != null && !session.getContext().getUri().getAbsolutePath().toString().equals(statusResponse.getDestination())) {
+ if (! destinationValidator.validate(session.getContext().getUri().getAbsolutePath(), statusResponse.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
index 5a9a4c7..4069ead 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
@@ -35,6 +35,7 @@ import org.keycloak.saml.*;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
+import org.keycloak.saml.validators.DestinationValidator;
import org.keycloak.sessions.AuthenticationSessionModel;
import javax.ws.rs.core.MediaType;
@@ -50,13 +51,15 @@ import java.util.TreeSet;
*/
public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityProviderConfig> {
protected static final Logger logger = Logger.getLogger(SAMLIdentityProvider.class);
- public SAMLIdentityProvider(KeycloakSession session, SAMLIdentityProviderConfig config) {
+ private final DestinationValidator destinationValidator;
+ public SAMLIdentityProvider(KeycloakSession session, SAMLIdentityProviderConfig config, DestinationValidator destinationValidator) {
super(session, config);
+ this.destinationValidator = destinationValidator;
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
- return new SAMLEndpoint(realm, this, getConfig(), callback);
+ return new SAMLEndpoint(realm, this, getConfig(), callback, destinationValidator);
}
@Override
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
index 0170424..a0eb471 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
@@ -16,6 +16,7 @@
*/
package org.keycloak.broker.saml;
+import org.keycloak.Config.Scope;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
@@ -29,6 +30,7 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
+import org.keycloak.saml.validators.DestinationValidator;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
@@ -44,6 +46,8 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
public static final String PROVIDER_ID = "saml";
+ private DestinationValidator destinationValidator;
+
@Override
public String getName() {
return "SAML v2.0";
@@ -51,7 +55,7 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
@Override
public SAMLIdentityProvider create(KeycloakSession session, IdentityProviderModel model) {
- return new SAMLIdentityProvider(session, new SAMLIdentityProviderConfig(model));
+ return new SAMLIdentityProvider(session, new SAMLIdentityProviderConfig(model), destinationValidator);
}
@Override
@@ -159,4 +163,10 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
return PROVIDER_ID;
}
+ @Override
+ public void init(Scope config) {
+ super.init(config);
+
+ this.destinationValidator = DestinationValidator.forProtocolMap(config.getArray("knownProtocols"));
+ }
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
index 3a1ae98..eac5d98 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
@@ -35,6 +35,7 @@ import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.validators.DestinationValidator;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.w3c.dom.Document;
@@ -54,8 +55,8 @@ public class SamlEcpProfileService extends SamlService {
private static final String NS_PREFIX_SAML_PROTOCOL = "samlp";
private static final String NS_PREFIX_SAML_ASSERTION = "saml";
- public SamlEcpProfileService(RealmModel realm, EventBuilder event, Map<String, Integer> knownPorts, Map<Integer, String> knownProtocols) {
- super(realm, event, knownPorts, knownProtocols);
+ public SamlEcpProfileService(RealmModel realm, EventBuilder event, DestinationValidator destinationValidator) {
+ super(realm, event, destinationValidator);
}
public Response authenticate(InputStream inputStream) {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
index 32212a3..1951404 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
@@ -18,7 +18,6 @@
package org.keycloak.protocol.saml;
import org.keycloak.Config;
-import org.keycloak.OAuth2Constants;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
@@ -33,18 +32,16 @@ import org.keycloak.protocol.saml.mappers.RoleListMapper;
import org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
+import org.keycloak.saml.validators.DestinationValidator;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -52,29 +49,14 @@ import java.util.regex.Pattern;
*/
public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
- private static final Pattern PROTOCOL_MAP_PATTERN = Pattern.compile("\\s*([a-zA-Z][a-zA-Z\\d+-.]*)\\s*=\\s*(\\d+)\\s*");
- private static final String[] DEFAULT_PROTOCOL_TO_PORT_MAP = new String[] { "http=80", "https=443" };
-
public static final String SCOPE_ROLE_LIST = "role_list";
private static final String ROLE_LIST_CONSENT_TEXT = "${samlRoleListScopeConsentText}";
- private final Map<Integer, String> knownPorts = new HashMap<>();
- private final Map<String, Integer> knownProtocols = new HashMap<>();
-
- private void addToProtocolPortMaps(String protocolMapping) {
- Matcher m = PROTOCOL_MAP_PATTERN.matcher(protocolMapping);
- if (m.matches()) {
- Integer port = Integer.valueOf(m.group(2));
- String proto = m.group(1);
-
- knownPorts.put(port, proto);
- knownProtocols.put(proto, port);
- }
- }
+ private DestinationValidator destinationValidator;
@Override
public Object createProtocolEndpoint(RealmModel realm, EventBuilder event) {
- return new SamlService(realm, event, knownProtocols, knownPorts);
+ return new SamlService(realm, event, destinationValidator);
}
@Override
@@ -87,14 +69,7 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
//PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
//sts.installDefaultConfiguration();
- String[] protocolMappings = config.getArray("knownProtocols");
- if (protocolMappings == null) {
- protocolMappings = DEFAULT_PROTOCOL_TO_PORT_MAP;
- }
-
- for (String protocolMapping : protocolMappings) {
- addToProtocolPortMaps(protocolMapping);
- }
+ this.destinationValidator = DestinationValidator.forProtocolMap(config.getArray("knownProtocols"));
}
@Override
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index d3da176..b8a32f5 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -85,8 +85,8 @@ import org.keycloak.rotation.HardcodedKeyLocator;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.SPMetadataDescriptor;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
+import org.keycloak.saml.validators.DestinationValidator;
import org.keycloak.sessions.AuthenticationSessionModel;
-import java.util.Map;
/**
* Resource class for the saml connect token service
@@ -98,13 +98,11 @@ public class SamlService extends AuthorizationEndpointBase {
protected static final Logger logger = Logger.getLogger(SamlService.class);
- private final Map<String, Integer> knownPorts;
- private final Map<Integer, String> knownProtocols;
+ private final DestinationValidator destinationValidator;
- public SamlService(RealmModel realm, EventBuilder event, Map<String, Integer> knownPorts, Map<Integer, String> knownProtocols) {
+ public SamlService(RealmModel realm, EventBuilder event, DestinationValidator destinationValidator) {
super(realm, event);
- this.knownPorts = knownPorts;
- this.knownProtocols = knownProtocols;
+ this.destinationValidator = destinationValidator;
}
public abstract class BindingProtocol {
@@ -147,7 +145,7 @@ public class SamlService extends AuthorizationEndpointBase {
StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
// validate destination
- if (statusResponse.getDestination() != null && !session.getContext().getUri().getAbsolutePath().toString().equals(statusResponse.getDestination())) {
+ if (! destinationValidator.validate(session.getContext().getUri().getAbsolutePath(), statusResponse.getDestination())) {
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
@@ -272,7 +270,7 @@ public class SamlService extends AuthorizationEndpointBase {
event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
}
- if (! isValidDestination(requestAbstractType.getDestination())) {
+ if (! destinationValidator.validate(session.getContext().getUri().getAbsolutePath(), requestAbstractType.getDestination())) {
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
@@ -376,7 +374,7 @@ public class SamlService extends AuthorizationEndpointBase {
event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
}
- if (! isValidDestination(logoutRequest.getDestination())) {
+ if (! destinationValidator.validate(logoutRequest.getDestination(), session.getContext().getUri().getAbsolutePath())) {
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
@@ -696,35 +694,10 @@ public class SamlService extends AuthorizationEndpointBase {
@NoCache
@Consumes({"application/soap+xml",MediaType.TEXT_XML})
public Response soapBinding(InputStream inputStream) {
- SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event, knownPorts, knownProtocols);
+ SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event, destinationValidator);
ResteasyProviderFactory.getInstance().injectProperties(bindingService);
return bindingService.authenticate(inputStream);
}
-
- private boolean isValidDestination(URI destination) {
- if (destination == null) {
- return true; // destination is optional
- }
-
- URI expected = session.getContext().getUri().getAbsolutePath();
-
- if (Objects.equals(expected, destination)) {
- return true;
- }
-
- Integer portByScheme = knownPorts.get(expected.getScheme());
- if (expected.getPort() < 0 && portByScheme != null) {
- return Objects.equals(session.getContext().getUri().getRequestUriBuilder().port(portByScheme).build(), destination);
- }
-
- String protocolByPort = knownProtocols.get(expected.getPort());
- if (expected.getPort() >= 0 && Objects.equals(protocolByPort, expected.getScheme())) {
- return Objects.equals(session.getContext().getUri().getRequestUriBuilder().port(-1).build(), destination);
- }
-
- return false;
- }
-
}