diff options
author | tzefferer <tzefferer@gmail.com> | 2018-07-27 13:14:35 +0200 |
---|---|---|
committer | tzefferer <tzefferer@gmail.com> | 2018-07-27 13:14:35 +0200 |
commit | 84f5ffce2e66e52a07ef6bdcb802e268566168e0 (patch) | |
tree | 2c996d4d61511886804c83a9133b9d75ed635e48 /connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java | |
parent | a3e019e87d78e17f24c170f7ef6a08d40ebfb232 (diff) | |
parent | 6d09f43225ba2e0f6d7b0583f843c858a1015807 (diff) | |
download | National_eIDAS_Gateway-84f5ffce2e66e52a07ef6bdcb802e268566168e0.tar.gz National_eIDAS_Gateway-84f5ffce2e66e52a07ef6bdcb802e268566168e0.tar.bz2 National_eIDAS_Gateway-84f5ffce2e66e52a07ef6bdcb802e268566168e0.zip |
Merge branch 'master' of gitlab.iaik.tugraz.at:egiz/eidas_at_proxy
# Conflicts:
# eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/test/eidas/specific/modules/authmodule_eIDASv2/SZRClientTest.java
Diffstat (limited to 'connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java')
-rw-r--r-- | connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java new file mode 100644 index 00000000..607f42df --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java @@ -0,0 +1,203 @@ +package at.asitplus.eidas.specific.connector.verification; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.opensaml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.core.Scoping; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.xml.XMLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asitplus.eidas.specific.connector.MSeIDASNodeConstants; +import at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestValidator; +import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException; + +public class AuthnRequestValidator implements IAuthnRequestValidator { + + private static final Logger log = LoggerFactory.getLogger(AuthnRequestValidator.class); + + @Override + public void validate(HttpServletRequest httpReq, IRequest pendingReq, AuthnRequest authnReq, + SPSSODescriptor spSSODescriptor) throws AuthnRequestValidatorException { + try { + //validate NameIDPolicy + NameIDPolicy nameIDPolicy = authnReq.getNameIDPolicy(); + if (nameIDPolicy != null) { + String nameIDFormat = nameIDPolicy.getFormat(); + if (nameIDFormat != null) { + if ( !(NameID.TRANSIENT.equals(nameIDFormat) || + NameID.PERSISTENT.equals(nameIDFormat)) ) { + + throw new NameIDFormatNotSupportedException(nameIDFormat); + + } + + } else + log.trace("Find NameIDPolicy, but NameIDFormat is 'null'"); + } else + log.trace("AuthnRequest includes no 'NameIDPolicy'"); + + + //post-process RequesterId + String spEntityId = extractScopeRequsterId(authnReq); + if (StringUtils.isEmpty(spEntityId)) { + log.info("NO service-provider entityID in Authn. request. Stop authn. process ... "); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"NO relaying-party entityID in Authn. request"}, pendingReq); + + } else + pendingReq.setRawDataToTransaction(MSeIDASNodeConstants.DATA_REQUESTERID, spEntityId); + + + //post-process ProviderName + String providerName = authnReq.getProviderName(); + if (StringUtils.isEmpty(providerName)) + log.info("Authn. request contains NO SP friendlyName"); + else + pendingReq.setRawDataToTransaction(MSeIDASNodeConstants.DATA_PROVIDERNAME, spEntityId); + + //post-process requested LoA + List<String> reqLoA = extractLoA(authnReq); + pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setRequiredLoA(reqLoA); + + //post-process requested LoA comparison-level + String reqLoAComperison = extractComparisonLevel(authnReq); + pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setLoAMachtingMode(reqLoAComperison); + + //validate and process requested attributes + boolean sectorDetected = false; + List<XMLObject> requestedAttributes = authnReq.getExtensions().getUnknownXMLObjects(); + for (XMLObject reqAttrObj : requestedAttributes) { + if (reqAttrObj instanceof EAAFRequestedAttributes) { + EAAFRequestedAttributes reqAttr = (EAAFRequestedAttributes)reqAttrObj; + if (reqAttr.getAttributes() != null && reqAttr.getAttributes().size() != 0 ) { + for (EAAFRequestedAttribute el : reqAttr.getAttributes()) { + log.trace("Processing req. attribute '" + el.getName() + "' ... "); + if (el.getName().equals(PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME)) { + if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) { + String sectorId = el.getAttributeValues().get(0).getDOM().getTextContent(); + ServiceProviderConfiguration spConfig = pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class); + + try { + spConfig.setbPKTargetIdentifier(sectorId); + sectorDetected = true; + + } catch (EAAFException e) { + log.info("Requested sector: " + sectorId + " DOES NOT match to allowed sectors for SP: " + spConfig.getUniqueIdentifier()); + } + + } else + log.info("Req. attribute '" + el.getName() + "' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute"); + + } else + log.debug("Ignore req. attribute: " + el.getName()); + + } + + } else + log.debug("No requested Attributes in Authn. Request"); + + } else + log.info("Ignore unknown requested attribute: " + reqAttrObj.getElementQName().toString()); + + } + + if (!sectorDetected) { + log.info("Authn.Req validation FAILED. Reason: Contains NO or NO VALID target-sector information."); + throw new AuthnRequestValidatorException("pvp2.22", new Object[] {"NO or NO VALID target-sector information"}); + + } + + } catch (EAAFStorageException e) { + log.info("Can NOT store Authn. Req. data into pendingRequest." , e); + throw new AuthnRequestValidatorException("internal.02", null, e); + + } + + } + + private String extractComparisonLevel(AuthnRequest authnReq) { + if (authnReq.getRequestedAuthnContext() != null) { + RequestedAuthnContext authContext = authnReq.getRequestedAuthnContext(); + return authContext.getComparison().toString(); + + } + + return null; + } + + private List<String> extractLoA(AuthnRequest authnReq) throws AuthnRequestValidatorException { + List<String> result = new ArrayList<String>(); + if (authnReq.getRequestedAuthnContext() != null) { + RequestedAuthnContext authContext = authnReq.getRequestedAuthnContext(); + if (authContext.getComparison().equals(AuthnContextComparisonTypeEnumeration.MINIMUM)) { + if (authContext.getAuthnContextClassRefs().isEmpty()) { + log.debug("Authn. Req. contains no requested LoA"); + + } else if (authContext.getAuthnContextClassRefs().size() > 1) { + log.info("Authn. Req. contains MORE THAN ONE requested LoA, but " + + AuthnContextComparisonTypeEnumeration.MINIMUM + " allows only one" ); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Authn. Req. contains MORE THAN ONE requested LoA, but " + + AuthnContextComparisonTypeEnumeration.MINIMUM + " allows only one"}); + + } else + result.add(authContext.getAuthnContextClassRefs().get(0).getAuthnContextClassRef()); + + } else if (authContext.getComparison().equals(AuthnContextComparisonTypeEnumeration.EXACT)) { + for (AuthnContextClassRef el : authContext.getAuthnContextClassRefs()) + result.add(el.getAuthnContextClassRef()); + + } else { + log.info("Currently only '" + AuthnContextComparisonTypeEnumeration.MINIMUM + "' and '" + + AuthnContextComparisonTypeEnumeration.EXACT + "' are supported"); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Currently only '" + AuthnContextComparisonTypeEnumeration.MINIMUM + "' and '" + + AuthnContextComparisonTypeEnumeration.EXACT + "' are supported"}); + + } + + } + + return result; + } + + private String extractScopeRequsterId(AuthnRequest authnReq) { + if (authnReq.getScoping() != null) { + Scoping scoping = authnReq.getScoping(); + if (scoping.getRequesterIDs() != null && + scoping.getRequesterIDs().size() > 0) { + if (scoping.getRequesterIDs().size() == 1) + return scoping.getRequesterIDs().get(0).getRequesterID(); + + else { + log.info("Authn. request contains more than on RequesterIDs! Only use first one"); + return scoping.getRequesterIDs().get(0).getRequesterID(); + + } + } + } + + return null; + } + + +} |