feat: 🎸 Extended list of internal referrers for sess. invalider
Via property _saml.internalReferrers_ it can be configured which referrers are considered as internal and in such a cases session will not be invalidated. The property has to be list of URLs, separated by a comma, and the matching is done as a prefix of the current referrerpull/1580/head
parent
39498573c3
commit
9aa16ffe5c
|
@ -126,11 +126,11 @@
|
||||||
<prop key="saml.keystore.password">pass</prop>
|
<prop key="saml.keystore.password">pass</prop>
|
||||||
<prop key="saml.keystore.defaultKey">pass</prop>
|
<prop key="saml.keystore.defaultKey">pass</prop>
|
||||||
<prop key="saml.keystore.defaultKeyPass">pass</prop>
|
<prop key="saml.keystore.defaultKeyPass">pass</prop>
|
||||||
<prop key="saml.idp.defaultIdpEntityId">https://login.cesnet.cz/idp/</prop>
|
<prop key="saml.idp.defaultIdpEntityId"/>
|
||||||
<prop key="saml.idp.metadataLocation"/> <!-- i.e. /etc/perun/login-cesnet-metadata.xml -->
|
<prop key="saml.idp.metadataLocation"/> <!-- i.e. /etc/perun/login-cesnet-metadata.xml -->
|
||||||
<prop key="saml.idp.metadataUrl"/> <!-- i.e. https://login.cesnet.cz/proxy/module.php/metadata -->
|
<prop key="saml.idp.metadataUrl"/> <!-- i.e. https://login.cesnet.cz/proxy/module.php/metadata -->
|
||||||
<prop key="saml.proxy.enabled">true</prop>
|
<prop key="saml.proxy.spEntityId"/>
|
||||||
<prop key="saml.proxy.spEntityId">https://login.cesnet.cz/proxy/</prop>
|
<prop key="saml.internalReferrers"/> <!-- comma separated list of URLs (which are matched as prefixes) -->
|
||||||
<prop key="saml.acrs.reserverdPrefixes">urn:cesnet:</prop>
|
<prop key="saml.acrs.reserverdPrefixes">urn:cesnet:</prop>
|
||||||
<prop key="saml.acrs.enableComparison">false</prop>
|
<prop key="saml.acrs.enableComparison">false</prop>
|
||||||
<prop key="saml.user.attrIdentifier">eppn</prop><!-- eppn|epuid|eptid|uid|uniqueIdentifier -->
|
<prop key="saml.user.attrIdentifier">eppn</prop><!-- eppn|epuid|eptid|uid|uniqueIdentifier -->
|
||||||
|
@ -487,8 +487,8 @@
|
||||||
<constructor-arg name="pattern" value="/authorize**"/>
|
<constructor-arg name="pattern" value="/authorize**"/>
|
||||||
<constructor-arg name="oidcIssuer" value="${main.oidc.issuer.url}"/>
|
<constructor-arg name="oidcIssuer" value="${main.oidc.issuer.url}"/>
|
||||||
<constructor-arg name="idpEntityId" value="${saml.idp.defaultIdpEntityId}"/>
|
<constructor-arg name="idpEntityId" value="${saml.idp.defaultIdpEntityId}"/>
|
||||||
<constructor-arg name="proxyEnabled" value="${saml.proxy.enabled}"/>
|
|
||||||
<constructor-arg name="proxySpEntityId" value="${saml.proxy.spEntityId}"/>
|
<constructor-arg name="proxySpEntityId" value="${saml.proxy.spEntityId}"/>
|
||||||
|
<constructor-arg name="internalReferrers" value="#{'${saml.internalReferrers}'.split('\s*,\s*')}"/>
|
||||||
<constructor-arg name="contextLogoutHandler" ref="logoutHandler"/>
|
<constructor-arg name="contextLogoutHandler" ref="logoutHandler"/>
|
||||||
</bean>
|
</bean>
|
||||||
<bean id="samlDiscovery" class="org.springframework.security.saml.SAMLDiscovery">
|
<bean id="samlDiscovery" class="org.springframework.security.saml.SAMLDiscovery">
|
||||||
|
|
|
@ -3,6 +3,10 @@ package cz.muni.ics.oidc.saml;
|
||||||
import static org.springframework.http.HttpHeaders.REFERER;
|
import static org.springframework.http.HttpHeaders.REFERER;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
|
@ -21,25 +25,34 @@ public class SamlInvalidateSessionFilter extends GenericFilterBean {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SamlInvalidateSessionFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(SamlInvalidateSessionFilter.class);
|
||||||
private final AntPathRequestMatcher matcher;
|
private final AntPathRequestMatcher matcher;
|
||||||
|
|
||||||
private final String idpEntityId;
|
|
||||||
private final String proxySpEntityId;
|
|
||||||
private final boolean proxyEnabled;
|
|
||||||
private final String oidcIssuer;
|
|
||||||
private final SecurityContextLogoutHandler contextLogoutHandler;
|
private final SecurityContextLogoutHandler contextLogoutHandler;
|
||||||
|
private final List<String> internalReferrers = new ArrayList<>();
|
||||||
|
|
||||||
public SamlInvalidateSessionFilter(String pattern,
|
public SamlInvalidateSessionFilter(String pattern,
|
||||||
String idpEntityId,
|
String idpEntityId,
|
||||||
String oidcIssuer,
|
String oidcIssuer,
|
||||||
boolean proxyEnabled,
|
|
||||||
String proxySpEntityId,
|
String proxySpEntityId,
|
||||||
SecurityContextLogoutHandler contextLogoutHandler)
|
SecurityContextLogoutHandler contextLogoutHandler,
|
||||||
|
String[] internalReferrers)
|
||||||
{
|
{
|
||||||
this.matcher = new AntPathRequestMatcher(pattern);
|
this.matcher = new AntPathRequestMatcher(pattern);
|
||||||
this.idpEntityId = idpEntityId;
|
if (StringUtils.hasText(idpEntityId)) {
|
||||||
this.oidcIssuer = oidcIssuer;
|
this.internalReferrers.add(idpEntityId);
|
||||||
this.proxyEnabled = proxyEnabled;
|
}
|
||||||
this.proxySpEntityId = proxySpEntityId;
|
if (StringUtils.hasText(oidcIssuer)) {
|
||||||
|
this.internalReferrers.add(oidcIssuer);
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(proxySpEntityId)) {
|
||||||
|
this.internalReferrers.add(proxySpEntityId);
|
||||||
|
}
|
||||||
this.contextLogoutHandler = contextLogoutHandler;
|
this.contextLogoutHandler = contextLogoutHandler;
|
||||||
|
if (internalReferrers != null && internalReferrers.length > 0) {
|
||||||
|
List<String> referrers = Arrays.asList(internalReferrers);
|
||||||
|
referrers = referrers.stream().filter(StringUtils::hasText).collect(Collectors.toList());
|
||||||
|
if (!referrers.isEmpty()) {
|
||||||
|
this.internalReferrers.addAll(referrers);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -59,23 +72,15 @@ public class SamlInvalidateSessionFilter extends GenericFilterBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInternalReferer(String referer) {
|
private boolean isInternalReferer(String referer) {
|
||||||
if (!StringUtils.hasText(referer)) {
|
if (!StringUtils.hasText(referer)) { // no referer, consider as internal
|
||||||
// no referer, consider as internal
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
for (String internal : internalReferrers) {
|
||||||
boolean isInternal = referer.startsWith(oidcIssuer);
|
if (referer.startsWith(internal)) {
|
||||||
if (!isInternal) {
|
return true;
|
||||||
if (proxyEnabled) {
|
|
||||||
// check if referer is PROXY (SP part)
|
|
||||||
isInternal = referer.startsWith(proxySpEntityId);
|
|
||||||
} else {
|
|
||||||
// check if referer is IDP
|
|
||||||
isInternal = referer.startsWith(idpEntityId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
log.debug("Referer {} is internal: {}", referer, isInternal);
|
|
||||||
return isInternal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue