aboutsummaryrefslogtreecommitdiff
path: root/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java
diff options
context:
space:
mode:
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.java382
1 files changed, 0 insertions, 382 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
deleted file mode 100644
index 23702264..00000000
--- a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright 2018 A-SIT Plus GmbH
- * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ,
- * A-SIT Plus GmbH, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "License");
- * You may not use this work except in compliance with the License.
- * You may obtain a copy of the License at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * 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.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
-*/
-
-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.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.saml2.core.NameIDPolicy;
-import org.opensaml.saml.saml2.core.NameIDType;
-import org.opensaml.saml.saml2.core.RequestedAuthnContext;
-import org.opensaml.saml.saml2.core.Scoping;
-import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
-import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
-import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.core.api.data.EaafConstants;
-import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
-import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
-import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-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.core.impl.idp.controller.protocols.RequestImpl;
-import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
-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.IAuthnRequestPostProcessor;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NameIdFormatNotSupportedException;
-import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
-
-public class AuthnRequestValidator implements IAuthnRequestPostProcessor {
-
- private static final Logger log = LoggerFactory.getLogger(AuthnRequestValidator.class);
-
- @Autowired(required = true)
- private IConfiguration basicConfig;
-
- @Override
- public void process(HttpServletRequest httpReq, IRequest pendingReq, AuthnRequest authnReq,
- SPSSODescriptor spSsoDescriptor) throws AuthnRequestValidatorException {
- try {
- // validate NameIDPolicy
- final NameIDPolicy nameIdPolicy = authnReq.getNameIDPolicy();
- if (nameIdPolicy != null) {
- final String nameIdFormat = nameIdPolicy.getFormat();
- if (nameIdFormat != null) {
- if (!(NameIDType.TRANSIENT.equals(nameIdFormat)
- || NameIDType.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
- final 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
- final String providerName = authnReq.getProviderName();
- if (StringUtils.isEmpty(providerName)) {
- log.info("Authn. request contains NO SP friendlyName");
- } else {
- pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_PROVIDERNAME, providerName);
- }
-
- // post-process requested LoA
- postprocessLoaLevel(pendingReq, authnReq);
-
- // post-process requested LoA comparison-level
- pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setLoAMachtingMode(
- extractComparisonLevel(authnReq));
-
- // extract information from requested attributes
- extractFromRequestedAttriutes(pendingReq, authnReq);
-
- } catch (final EaafStorageException e) {
- log.info("Can NOT store Authn. Req. data into pendingRequest.", e);
- throw new AuthnRequestValidatorException("internal.02", null, e);
-
- }
-
- }
-
- private void extractFromRequestedAttriutes(IRequest pendingReq, AuthnRequest authnReq)
- throws AuthnRequestValidatorException, EaafStorageException {
- // validate and process requested attributes
- boolean sectorDetected = false;
-
- final ServiceProviderConfiguration spConfig = pendingReq.getServiceProviderConfiguration(
- ServiceProviderConfiguration.class);
-
- if (authnReq.getExtensions() != null) {
- final List<XMLObject> requestedAttributes = authnReq.getExtensions().getUnknownXMLObjects();
- for (final XMLObject reqAttrObj : requestedAttributes) {
- if (reqAttrObj instanceof EaafRequestedAttributes) {
- final EaafRequestedAttributes reqAttr = (EaafRequestedAttributes) reqAttrObj;
- if (reqAttr.getAttributes() != null && reqAttr.getAttributes().size() != 0) {
- for (final EaafRequestedAttribute el : reqAttr.getAttributes()) {
- log.trace("Processing req. attribute '" + el.getName() + "' ... ");
- if (el.getName().equals(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME)) {
- sectorDetected = extractBpkTargetIdentifier(el, spConfig);
-
- } else if (el.getName().equals(ExtendedPvpAttributeDefinitions.EID_TRANSACTION_ID_NAME)) {
- extractUniqueTransactionId(el, pendingReq);
-
- } else if (el.getName().equals(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME)) {
- extractBindingPublicKey(el, pendingReq);
-
- } 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.warn("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" });
-
- }
-
- }
-
- private void extractBindingPublicKey(EaafRequestedAttribute el, IRequest pendingReq)
- throws EaafStorageException {
- if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) {
- final String bindingPubKey = el.getAttributeValues().get(0).getDOM().getTextContent();
- pendingReq.setRawDataToTransaction(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME, bindingPubKey);
- log.info("Find Binding Public-Key. eIDAS authentication will be used to create an ID Austria Binding");
-
- } else {
- log.warn(
- "Req. attribute '{}' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute",
- el.getName());
-
- }
- }
-
- /**
- * Extract unique transactionId from AuthnRequest.
- *
- * @param el Requested attribute from AuthnRequest
- * @param pendingReq Current pendingRequest object (has to be of type
- * {@link RequestImpl})
- * @return <code>true</code> if transactionId extraction was successful,
- * otherwise <code>false</code>
- */
- private boolean extractUniqueTransactionId(EaafRequestedAttribute el, IRequest pendingReq) {
- if (!(pendingReq instanceof RequestImpl)) {
- log.warn(
- "Can NOT set unique transactionId from AuthnRequest,because 'PendingRequest' is NOT from Type: {}",
- RequestImpl.class.getName());
-
- } else {
- if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) {
- final String transactionId = el.getAttributeValues().get(0).getDOM().getTextContent();
- ((RequestImpl) pendingReq).setUniqueTransactionIdentifier(transactionId);
- log.info("Find transactionId: {} from requesting service. Replace old id: {} ",
- transactionId, TransactionIdUtils.getTransactionId());
- TransactionIdUtils.setTransactionId(transactionId);
-
- return true;
-
- } else {
- log.warn(
- "Req. attribute '{}' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute",
- el.getName());
-
- }
-
- }
-
- return false;
- }
-
- /**
- * Extract the bPK target from requested attribute.
- *
- * @param el Requested attribute from AuthnRequest
- * @param spConfig Service-Provider configuration for current process
- * @return <code>true</code> if bPK target extraction was successful, otherwise
- * <code>false</code>
- */
- private boolean extractBpkTargetIdentifier(EaafRequestedAttribute el,
- ServiceProviderConfiguration spConfig) {
- if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) {
- final String sectorId = el.getAttributeValues().get(0).getDOM().getTextContent();
- try {
- spConfig.setBpkTargetIdentifier(sectorId);
- return true;
-
- } catch (final EaafException e) {
- log.warn("Requested sector: " + sectorId + " DOES NOT match to allowed sectors for SP: "
- + spConfig.getUniqueIdentifier());
- }
-
- } else {
- log.warn("Req. attribute '" + el.getName()
- + "' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute");
- }
-
- return false;
-
- }
-
- private void postprocessLoaLevel(IRequest pendingReq, AuthnRequest authnReq)
- throws AuthnRequestValidatorException {
- final List<String> reqLoA = extractLoA(authnReq);
- log.trace("SP requests LoA with: {}", String.join(", ", reqLoA));
-
- LevelOfAssurance minimumLoAFromConfig = LevelOfAssurance.fromString(basicConfig.getBasicConfiguration(
- MsEidasNodeConstants.PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL,
- EaafConstants.EIDAS_LOA_HIGH));
- if (minimumLoAFromConfig == null) {
- log.warn("Can not load minimum LoA from configuration. Use LoA: {} as default",
- EaafConstants.EIDAS_LOA_HIGH);
- minimumLoAFromConfig = LevelOfAssurance.HIGH;
-
- }
-
- log.trace("Validate requested LoA to connector configuration minimum LoA: {} ...",
- minimumLoAFromConfig);
- final List<String> allowedLoA = new ArrayList<>();
- for (final String loa : reqLoA) {
- try {
- final LevelOfAssurance intLoa = LevelOfAssurance.fromString(loa);
- String selectedLoA = EaafConstants.EIDAS_LOA_HIGH;
- if (intLoa != null
- && intLoa.numericValue() <= minimumLoAFromConfig.numericValue()) {
- log.info("Client: {} requested LoA: {} will be upgraded to: {}",
- pendingReq.getServiceProviderConfiguration().getUniqueIdentifier(),
- loa,
- minimumLoAFromConfig);
- selectedLoA = minimumLoAFromConfig.getValue();
-
- }
-
- if (!allowedLoA.contains(selectedLoA)) {
- log.debug("Allow LoA: {} for Client: {}",
- selectedLoA,
- pendingReq.getServiceProviderConfiguration().getUniqueIdentifier());
- allowedLoA.add(selectedLoA);
-
- }
-
- } catch (final IllegalArgumentException e) {
- log.warn("LoA: {} is currently NOT supported and it will be ignored.", loa);
-
- }
-
- }
-
- pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setRequiredLoA(
- allowedLoA);
-
- }
-
- private String extractComparisonLevel(AuthnRequest authnReq) {
- if (authnReq.getRequestedAuthnContext() != null) {
- final RequestedAuthnContext authContext = authnReq.getRequestedAuthnContext();
- return authContext.getComparison().toString();
-
- }
-
- return null;
- }
-
- private List<String> extractLoA(AuthnRequest authnReq) throws AuthnRequestValidatorException {
- final List<String> result = new ArrayList<>();
- if (authnReq.getRequestedAuthnContext() != null) {
- final 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 (final 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) {
- final 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;
- }
-
-}