Merge pull request #36 from dBucik/acr_client_id

feat: 🎸 Forward client_id in AuthenticationContextClass
pull/1580/head
Dominik František Bučík 2021-11-12 13:31:54 +01:00 committed by GitHub
commit e6f91dcbed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 3 deletions

View File

@ -133,6 +133,7 @@
<prop key="saml.internalReferrers"/> <!-- comma separated list of URLs (which are matched as prefixes) --> <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.acrs.onlyreserved.append">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</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 -->
<!-- STATS JDBC --> <!-- STATS JDBC -->
<prop key="stats.jdbc.url">jdbc:mariadb://localhost:3306/STATS</prop> <prop key="stats.jdbc.url">jdbc:mariadb://localhost:3306/STATS</prop>
@ -198,6 +199,7 @@
<property name="idpMetadataFile" value="${saml.idp.metadataLocation}"/> <property name="idpMetadataFile" value="${saml.idp.metadataLocation}"/>
<property name="idpMetadataUrl" value="${saml.idp.metadataUrl}"/> <property name="idpMetadataUrl" value="${saml.idp.metadataUrl}"/>
<property name="acrReservedPrefixes" value="#{'${saml.acrs.reserverdPrefixes}'.split('\s*,\s*')}"/> <property name="acrReservedPrefixes" value="#{'${saml.acrs.reserverdPrefixes}'.split('\s*,\s*')}"/>
<property name="acrsToBeAdded" value="#{'${saml.acrs.onlyreserved.append}'.split('\s*,\s*')}"/>
<property name="userIdentifierAttribute" value="${saml.user.attrIdentifier}"/> <property name="userIdentifierAttribute" value="${saml.user.attrIdentifier}"/>
</bean> </bean>

View File

@ -1,8 +1,10 @@
package cz.muni.ics.oidc.saml; package cz.muni.ics.oidc.saml;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.CLIENT_ID_PREFIX;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.EFILTER_PREFIX; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.EFILTER_PREFIX;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.FILTER_PREFIX; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.FILTER_PREFIX;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.IDP_ENTITY_ID_PREFIX; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.IDP_ENTITY_ID_PREFIX;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.PARAM_CLIENT_ID;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.PARAM_PROMPT; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.PARAM_PROMPT;
import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.REFEDS_MFA; import static cz.muni.ics.oidc.server.filters.PerunFilterConstants.REFEDS_MFA;
@ -14,9 +16,13 @@ import cz.muni.ics.oidc.server.configurations.PerunOidcConfig;
import cz.muni.ics.oidc.server.filters.PerunFilterConstants; import cz.muni.ics.oidc.server.filters.PerunFilterConstants;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -43,14 +49,18 @@ public class PerunSamlEntryPoint extends SAMLEntryPoint {
private final PerunAdapter perunAdapter; private final PerunAdapter perunAdapter;
private final PerunOidcConfig config; private final PerunOidcConfig config;
private final FacilityAttrsConfig facilityAttrsConfig; private final FacilityAttrsConfig facilityAttrsConfig;
private final SamlProperties samlProperties;
@Autowired @Autowired
public PerunSamlEntryPoint(PerunAdapter perunAdapter, PerunOidcConfig config, public PerunSamlEntryPoint(PerunAdapter perunAdapter,
FacilityAttrsConfig facilityAttrsConfig) PerunOidcConfig config,
FacilityAttrsConfig facilityAttrsConfig,
SamlProperties samlProperties)
{ {
this.perunAdapter = perunAdapter; this.perunAdapter = perunAdapter;
this.config = config; this.config = config;
this.facilityAttrsConfig = facilityAttrsConfig; this.facilityAttrsConfig = facilityAttrsConfig;
this.samlProperties = samlProperties;
} }
@Override @Override
@ -163,15 +173,57 @@ public class PerunSamlEntryPoint extends SAMLEntryPoint {
options.setForceAuthN(true); options.setForceAuthN(true);
} }
if (StringUtils.hasText(request.getParameter(PARAM_CLIENT_ID)) && config.isAddClientIdToAcrs()) {
String clientIdAcr = CLIENT_ID_PREFIX + request.getParameter(PARAM_CLIENT_ID);
log.debug("Adding client_id ACR ({}) to list of AuthnContextClassRefs for purposes" +
" of displaying service name on the wayf", clientIdAcr);
acrs.add(clientIdAcr);
}
if (acrs.size() > 0) { if (acrs.size() > 0) {
options.setAuthnContexts(acrs); options.setAuthnContexts(acrs);
log.debug("Transformed acr_values ({}) to SAML AuthnContextClassRef ({})", log.debug("Transformed acr_values ({}) to SAML AuthnContextClassRef ({})",
acrValues, options.getAuthnContexts()); acrValues, options.getAuthnContexts());
} }
} }
private void processAcrs(List<String> acrs) {
if (acrs == null || acrs.isEmpty()) {
return;
}
String[] reservedAcrsPrefixes = samlProperties.getAcrReservedPrefixes();
Set<String> reservedPrefixes = (reservedAcrsPrefixes != null) ?
new HashSet<>(Arrays.asList(reservedAcrsPrefixes)) : new HashSet<>();
if (reservedPrefixes.isEmpty()) {
return;
}
boolean hasNonReserved = false;
for (String prefix: reservedPrefixes) {
for (String acr: acrs) {
if (!acr.startsWith(prefix)) {
log.debug("ACR with non reserved prefix found: {}", acr);
hasNonReserved = true;
break;
}
}
if (hasNonReserved) {
break;
}
}
if (!hasNonReserved) {
List<String> toBeAdded = new LinkedList<>(Arrays.asList(samlProperties.getAcrsToBeAdded()));
log.debug("NO ACR with non reserved prefix found, adding following: {}", toBeAdded);
acrs.addAll(toBeAdded);
}
}
private List<String> convertAcrValuesToList(String acrValues) { private List<String> convertAcrValuesToList(String acrValues) {
List<String> acrs = new ArrayList<>(); List<String> acrs = new LinkedList<>();
if (StringUtils.hasText(acrValues)) { if (StringUtils.hasText(acrValues)) {
String[] parts = acrValues.split(" "); String[] parts = acrValues.split(" ");
if (parts.length > 0) { if (parts.length > 0) {

View File

@ -23,6 +23,7 @@ public class SamlProperties implements InitializingBean {
private String idpMetadataFile; private String idpMetadataFile;
private String idpMetadataUrl; private String idpMetadataUrl;
private String[] acrReservedPrefixes; private String[] acrReservedPrefixes;
private String[] acrsToBeAdded;
private String userIdentifierAttribute; private String userIdentifierAttribute;
public String getEntityID() { public String getEntityID() {
@ -127,6 +128,14 @@ public class SamlProperties implements InitializingBean {
} }
} }
public String[] getAcrsToBeAdded() {
return acrsToBeAdded;
}
public void setAcrsToBeAdded(String[] acrsToBeAdded) {
this.acrsToBeAdded = acrsToBeAdded;
}
public String getUserIdentifierAttribute() { public String getUserIdentifierAttribute() {
return userIdentifierAttribute; return userIdentifierAttribute;
} }