diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/user-context.xml b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/user-context.xml index ae14ce655..aa48f9395 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/user-context.xml +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/user-context.xml @@ -133,6 +133,7 @@ https://login.cesnet.cz/proxy/ urn:cesnet: false + eppn jdbc:mariadb://localhost:3306/STATS user @@ -197,6 +198,7 @@ + diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/PerunSamlUserDetailsService.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/PerunSamlUserDetailsService.java index 612b23f2c..922a7f202 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/PerunSamlUserDetailsService.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/PerunSamlUserDetailsService.java @@ -15,16 +15,18 @@ public class PerunSamlUserDetailsService implements SAMLUserDetailsService { private static final Logger log = LoggerFactory.getLogger(PerunSamlUserDetailsService.class); private final PerunAdapter perunAdapter; + private final SamlProperties samlProperties; @Autowired - public PerunSamlUserDetailsService(PerunAdapter perunAdapter) { + public PerunSamlUserDetailsService(PerunAdapter perunAdapter, SamlProperties samlProperties) { this.perunAdapter = perunAdapter; + this.samlProperties = samlProperties; } @Override public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException { log.debug("Loading user for SAML credential"); - PerunPrincipal p = FiltersUtils.getPerunPrincipal(credential); + PerunPrincipal p = FiltersUtils.getPerunPrincipal(credential, samlProperties.getUserIdentifierAttribute()); log.debug("Fetching user from perun ({})", p); return perunAdapter.getPreauthenticatedUserId(p); } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/SamlProperties.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/SamlProperties.java index 6ccbcfed4..c38cf1962 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/SamlProperties.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/saml/SamlProperties.java @@ -23,6 +23,7 @@ public class SamlProperties implements InitializingBean { private String idpMetadataFile; private String idpMetadataUrl; private String[] acrReservedPrefixes; + private String userIdentifierAttribute; public String getEntityID() { return entityID; @@ -125,4 +126,12 @@ public class SamlProperties implements InitializingBean { this.acrReservedPrefixes = nonNull.toArray(new String[0]); } } + + public String getUserIdentifierAttribute() { + return userIdentifierAttribute; + } + + public void setUserIdentifierAttribute(String userIdentifierAttribute) { + this.userIdentifierAttribute = userIdentifierAttribute; + } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/CallPerunFiltersFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/CallPerunFiltersFilter.java index c4a37f603..d2423b353 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/CallPerunFiltersFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/CallPerunFiltersFilter.java @@ -3,6 +3,7 @@ package cz.muni.ics.oidc.server.filters; import cz.muni.ics.oidc.BeanUtil; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.PerunUser; +import cz.muni.ics.oidc.saml.SamlProperties; import cz.muni.ics.oidc.server.adapters.PerunAdapter; import java.io.IOException; import java.util.List; @@ -47,6 +48,9 @@ public class CallPerunFiltersFilter extends GenericFilterBean { @Autowired private PerunAdapter perunAdapter; + @Autowired + private SamlProperties samlProperties; + private PerunFiltersContext perunFiltersContext; @PostConstruct @@ -72,7 +76,7 @@ public class CallPerunFiltersFilter extends GenericFilterBean { CallPerunFiltersFilter.class.getSimpleName(), client.getClientId(), e); } } - PerunUser user = FiltersUtils.getPerunUser(request, perunAdapter); + PerunUser user = FiltersUtils.getPerunUser(request, perunAdapter, samlProperties.getUserIdentifierAttribute()); FilterParams params = new FilterParams(client, facility, user); for (PerunRequestFilter filter : filters) { if (!filter.doFilter(servletRequest, servletResponse, params)) { diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java index 156b53aaf..b773627e2 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java @@ -2,7 +2,6 @@ package cz.muni.ics.oidc.server.filters; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.PARAM_FORCE_AUTHN; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.SAML_EPUID; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; import com.google.common.base.Strings; import cz.muni.ics.oidc.models.Facility; @@ -31,6 +30,7 @@ import org.springframework.security.providers.ExpiringUsernameAuthenticationToke import org.springframework.security.saml.SAMLCredential; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.util.StringUtils; /** * Utility class for filters. Contains common methods used by most of filter classes. @@ -102,12 +102,12 @@ public class FiltersUtils { * @param perunAdapter Adapter of Perun interface * @return Found PerunUser */ - public static PerunUser getPerunUser(HttpServletRequest request, PerunAdapter perunAdapter) { + public static PerunUser getPerunUser(HttpServletRequest request, PerunAdapter perunAdapter, String samlIdAttribute) { SAMLCredential samlCredential = getSamlCredential(request); if (samlCredential == null) { return null; } - PerunPrincipal principal = getPerunPrincipal(samlCredential); + PerunPrincipal principal = getPerunPrincipal(samlCredential, samlIdAttribute); log.debug("fetching Perun user with extLogin '{}' and extSourceName '{}'", principal.getExtLogin(), principal.getExtSourceName()); return perunAdapter.getPreauthenticatedUserId(principal); @@ -121,8 +121,17 @@ public class FiltersUtils { return (SAMLCredential) p.getCredentials(); } - public static PerunPrincipal getPerunPrincipal(SAMLCredential credential) { - String extLogin = credential.getAttributeAsString(SAML_EPUID); + public static PerunPrincipal getPerunPrincipal(SAMLCredential credential, String idAttribute) { + if (credential == null) { + throw new IllegalArgumentException("No SAML credential passed"); + } else if (!StringUtils.hasText(idAttribute)) { + throw new IllegalArgumentException("No identifier from SAML configured"); + } + String identifierAttrOid = PerunFilterConstants.SAML_IDS.getOrDefault(idAttribute, null); + if (identifierAttrOid == null) { + throw new IllegalStateException("SAML credentials has no value for attribute: " + idAttribute); + } + String extLogin = credential.getAttributeAsString(identifierAttrOid); String extSourceName = credential.getRemoteEntityID(); return new PerunPrincipal(extLogin, extSourceName); } @@ -136,7 +145,7 @@ public class FiltersUtils { public static PerunPrincipal extractPerunPrincipal(HttpServletRequest req, String proxyExtSourceName) { String extLogin = null; String remoteUser = req.getRemoteUser(); - if (isNotEmpty(remoteUser)) { + if (StringUtils.hasText(remoteUser)) { extLogin = remoteUser; } else if (req.getUserPrincipal() != null) { extLogin = ((User)req.getUserPrincipal()).getUsername(); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/PerunFilterConstants.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/PerunFilterConstants.java index 12401bb48..8469ed180 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/PerunFilterConstants.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/PerunFilterConstants.java @@ -1,5 +1,8 @@ package cz.muni.ics.oidc.server.filters; +import java.util.HashMap; +import java.util.Map; + /** * Class containing common constants used by Perun request filters. * @@ -33,8 +36,22 @@ public class PerunFilterConstants { public static final String EFILTER_PREFIX = "urn:cesnet:proxyidp:efilter:"; public static final String SAML_EPUID = "urn:oid:1.3.6.1.4.1.5923.1.1.1.13"; + public static final String SAML_EPPN = "urn:oid:1.3.6.1.4.1.5923.1.1.1.6"; + public static final String SAML_EPTID = "urn:oid:1.3.6.1.4.1.5923.1.1.1.10"; + public static final String SAML_UID = "urn:oid:0.9.2342.19200300.100.1.1"; + public static final String SAML_UNIQUE_IDENTIFIER = "urn:oid:0.9.2342.19200300.100.1.44"; + public static final String REFEDS_MFA = "https://refeds.org/profile/mfa"; public static final String PROMPT_LOGIN = "login"; public static final String PROMPT_SELECT_ACCOUNT = "select_account"; + public static final Map SAML_IDS = new HashMap<>(); + static { + SAML_IDS.put("eppn", SAML_EPPN); + SAML_IDS.put("epuid", SAML_EPUID); + SAML_IDS.put("eptid", SAML_EPTID); + SAML_IDS.put("uid", SAML_UID); + SAML_IDS.put("uniqueIdentifier", SAML_UNIQUE_IDENTIFIER); + } + } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunForceAupFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunForceAupFilter.java index ab62c0b85..f3366a67c 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunForceAupFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunForceAupFilter.java @@ -9,6 +9,7 @@ import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.PerunAttribute; import cz.muni.ics.oidc.models.PerunAttributeValue; import cz.muni.ics.oidc.models.PerunUser; +import cz.muni.ics.oidc.saml.SamlProperties; import cz.muni.ics.oidc.server.adapters.PerunAdapter; import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; import cz.muni.ics.oidc.server.filters.FilterParams; @@ -74,6 +75,7 @@ public class PerunForceAupFilter extends PerunRequestFilter { private final PerunAdapter perunAdapter; private final PerunOidcConfig perunOidcConfig; + private final SamlProperties samlProperties; private final String filterName; public PerunForceAupFilter(PerunRequestFilterParams params) { @@ -81,6 +83,7 @@ public class PerunForceAupFilter extends PerunRequestFilter { BeanUtil beanUtil = params.getBeanUtil(); this.perunAdapter = beanUtil.getBean(PerunAdapter.class); this.perunOidcConfig = beanUtil.getBean(PerunOidcConfig.class); + this.samlProperties = beanUtil.getBean(SamlProperties.class); this.perunOrgAupsAttrName = params.getProperty(ORG_AUPS_ATTR_NAME); this.perunUserAupsAttrName = params.getProperty(USER_AUPS_ATTR_NAME); @@ -102,7 +105,7 @@ public class PerunForceAupFilter extends PerunRequestFilter { return true; } - PerunUser user = FiltersUtils.getPerunUser(request, perunAdapter); + PerunUser user = FiltersUtils.getPerunUser(request, perunAdapter, samlProperties.getUserIdentifierAttribute()); if (user == null || user.getId() == null) { log.debug("{} - skip filter execution: no user provider", filterName); return true;