From 3f487b82a6955a2fa83bcf15dc771ed18c47e36a Mon Sep 17 00:00:00 2001
From: Thomas Lenz <thomas.lenz@egiz.gv.at>
Date: Wed, 1 Apr 2020 17:57:37 +0200
Subject: Revert "back-port of PVP IDP-module request post-processor"

This reverts commit bd6492ef3f4576d62b8f7cfe20dbaf425b22e2bb.
---
 .../pvp2/idp/impl/AbstractPVP2XProtocol.java       |  549 -----------
 .../pvp2/idp/impl/AbstractPvp2XProtocol.java       | 1041 ++++++++++----------
 2 files changed, 528 insertions(+), 1062 deletions(-)
 delete mode 100644 eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPVP2XProtocol.java

diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPVP2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPVP2XProtocol.java
deleted file mode 100644
index 597d3c22..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPVP2XProtocol.java
+++ /dev/null
@@ -1,549 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,  
- * A-SIT Plus, 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 "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *  
- * 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.gv.egiz.eaaf.modules.pvp2.idp.impl;
-
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameID;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.core.Status;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.core.StatusMessage;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.ws.security.SecurityPolicyException;
-import org.opensaml.xml.security.x509.X509Credential;
-import org.opensaml.xml.signature.SignableXMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import at.gv.egiz.components.eventlog.api.EventConstants;
-import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
-import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
-import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
-import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
-import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException;
-import at.gv.egiz.eaaf.core.exceptions.SLOException;
-import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
-import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration;
-import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor;
-import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPVPRequestException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding;
-import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
-import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EAAFURICompare;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SAMLVerificationEngine;
- 
-public abstract class AbstractPVP2XProtocol extends AbstractController implements IModulInfo {
-	private static final Logger log = LoggerFactory.getLogger(AbstractPVP2XProtocol.class);
-	
-	@Autowired(required=true) protected IPVP2BasicConfiguration pvpBasicConfiguration;
-	@Autowired(required=true) protected IPVPMetadataProvider metadataProvider;
-	@Autowired(required=true) protected SAMLVerificationEngine samlVerificationEngine;
-	@Autowired(required=false) protected List<IAuthnRequestPostProcessor> authRequestPostProcessors;
-	
-	private AbstractCredentialProvider pvpIDPCredentials;
-
-	
-		
-	/**
-	 * Sets a specific credential provider for PVP S-Profile IDP component.
-	 * @param pvpIDPCredentials credential provider
-	 */
-	public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) {
-		this.pvpIDPCredentials = pvpIDPCredentials;
-		
-	}
-	
-	public boolean generateErrorMessage(Throwable e,
-			HttpServletRequest request, HttpServletResponse response,
-			IRequest protocolRequest) throws Throwable {
-		
-		if(protocolRequest == null) {
-			throw e;
-		}
-		
-		if(!(protocolRequest instanceof PVPSProfilePendingRequest) ) {
-			throw e;
-		}
-		PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest)protocolRequest;
-		
-		Response samlResponse = 
-				SAML2Utils.createSAMLObject(Response.class);
-		Status status = SAML2Utils.createSAMLObject(Status.class);
-		StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
-		StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);
-		
-		String moaError = null;
-		
-		if(e instanceof NoPassivAuthenticationException) {
-			statusCode.setValue(StatusCode.NO_PASSIVE_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));	
-			
-		} else if (e instanceof NameIDFormatNotSupportedException) {
-			statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
- 
-		} else if (e instanceof SLOException) {
-			//SLOExecpetions only occurs if session information is lost
-			return false;
-			
-		} else if(e instanceof PVP2Exception) {
-			PVP2Exception ex = (PVP2Exception) e;
-			statusCode.setValue(ex.getStatusCodeValue());
-			String statusMessageValue = ex.getStatusMessageValue();
-			if(statusMessageValue != null) {
-				statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue));
-			}						
-			moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId());
-			
-		} else {
-			statusCode.setValue(StatusCode.RESPONDER_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
-			moaError = statusMessager.getResponseErrorCode(e);
-		}
-		
-		
-		if (StringUtils.isNotEmpty(moaError)) {
-			StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class);
-			moaStatusCode.setValue(moaError);
-			statusCode.setStatusCode(moaStatusCode);
-		}
-		
-		status.setStatusCode(statusCode);
-		if(statusMessage.getMessage() != null) {
-			status.setStatusMessage(statusMessage);
-		}
-		samlResponse.setStatus(status);
-		String remoteSessionID = SAML2Utils.getSecureIdentifier();
-		samlResponse.setID(remoteSessionID);
-
-		samlResponse.setIssueInstant(new DateTime());
-		Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
-		nissuer.setValue(pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL()));
-		nissuer.setFormat(NameID.ENTITY);
-		samlResponse.setIssuer(nissuer);
-		
-		IEncoder encoder = null;
-		
-		if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {			
-			encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class);
-						
-		} else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))  {
-			encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class);
-			
-		} else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI))  {
-			encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class);
-		}
-
-		if(encoder == null) {
-			// default to redirect binding
-			encoder = new RedirectBinding();
-		}
-
-		String relayState = null;
-		if (pvpRequest.getRequest() != null)
-			relayState = pvpRequest.getRequest().getRelayState();
-		
-		X509Credential signCred = pvpIDPCredentials.getIDPAssertionSigningCredential();
-		
-		encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), 
-				relayState, signCred, protocolRequest);
-		return true;
-	}
-
-	public boolean validate(HttpServletRequest request,
-			HttpServletResponse response, IRequest pending) {
-		
-		return true;
-	}
-		
-	protected void pvpMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {		
-		//create pendingRequest object
-		PVPSProfilePendingRequest pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-		pendingReq.initialize(req, authConfig);
-		pendingReq.setModule(getName());
-		
-		revisionsLogger.logEvent(
-				pendingReq.getUniqueSessionIdentifier(), 
-				pendingReq.getUniqueTransactionIdentifier(), 
-				EventConstants.TRANSACTION_IP, 
-				req.getRemoteAddr());
-				
-		MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class);
-		metadataAction.processRequest(pendingReq, 
-				req, resp, null);
-		
-	}
-	
-	protected void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {		
-		PVPSProfilePendingRequest pendingReq = null;
-		
-		try {
-			//create pendingRequest object
-			pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-			pendingReq.initialize(req, authConfig);
-			pendingReq.setModule(getName());
-			
-			revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
-			revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());						
-			revisionsLogger.logEvent(
-					pendingReq.getUniqueSessionIdentifier(), 
-					pendingReq.getUniqueTransactionIdentifier(), 
-					EventConstants.TRANSACTION_IP, 
-					req.getRemoteAddr());
-			
-			//get POST-Binding decoder implementation
-			InboundMessage msg = (InboundMessage) new PostBinding().decode(
-					req, resp, metadataProvider, false,
-					new EAAFURICompare(pvpBasicConfiguration.getIDPSSOPostService(pendingReq.getAuthURL())));
-			pendingReq.setRequest(msg);
-						
-			//preProcess Message
-			preProcess(req, resp, pendingReq);
-						
-		} catch (SecurityPolicyException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-			
-		} catch (SecurityException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-		
-		} catch (EAAFException e) {
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw e;
-			
-		} catch (Throwable e) {			
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
-		}					
-	}
-	
-	protected void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {
-		PVPSProfilePendingRequest pendingReq = null;
-		try {
-			//create pendingRequest object
-			pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-			pendingReq.initialize(req, authConfig);
-			pendingReq.setModule(getName());
-			
-			revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
-			revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());						
-			revisionsLogger.logEvent(
-					pendingReq.getUniqueSessionIdentifier(), 
-					pendingReq.getUniqueTransactionIdentifier(), 
-					EventConstants.TRANSACTION_IP, 
-					req.getRemoteAddr());
-			
-			//get POST-Binding decoder implementation
-			InboundMessage msg = (InboundMessage) new RedirectBinding().decode(
-					req, resp, metadataProvider, false,
-					new EAAFURICompare(pvpBasicConfiguration.getIDPSSORedirectService(pendingReq.getAuthURL())));
-			pendingReq.setRequest(msg);
-			
-			//preProcess Message
-			preProcess(req, resp, pendingReq);
-						
-		} catch (SecurityPolicyException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-			
-		} catch (SecurityException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-			
-		} catch (EAAFException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.info("Receive INVALID protocol request: " + samlRequest);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw e;
-						
-		} catch (Throwable e) {			
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-						
-			throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
-		}					
-	}
-	
-	
-	
-	/**
-	 * 
-	 * 
-	 * @param request
-	 * @param response
-	 * @param msg
-	 * @return true if preprocess can handle this request type, otherwise false
-	 * @throws Throwable
-	 */
-	abstract protected boolean childPreProcess(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable;
-	
-	protected void preProcess(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
-			
-			InboundMessage msg = pendingReq.getRequest();
-		
-			if (StringUtils.isEmpty(msg.getEntityID())) {
-				throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
-				
-			}
-			
-			if(!msg.isVerified()) {
-				samlVerificationEngine.verify(msg, 
-						TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
-				msg.setVerified(true);
-								
-			}
-			
-			revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE, getAuthProtocolIdentifier());
-			
-			if (msg instanceof PVPSProfileRequest && 
-					((PVPSProfileRequest)msg).getSamlRequest() instanceof AuthnRequest)
-				preProcessAuthRequest(request, response, pendingReq);
-
-			else if (childPreProcess(request, response, pendingReq))
-				log.debug("Find protocol handler in child implementation");
-				
-			else {
-				log.error("Receive unsupported PVP21 message of type: " + ((PVPSProfileRequest)msg).getSamlRequest().getClass().getName());
-				throw new InvalidPVPRequestException("pvp2.09", 
-						new Object[] {((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()});
-			}
-							
-			
-			
-			//switch to session authentication
-			protAuthService.performAuthentication(request, response, pendingReq);								
-	}
-
-	
-	/**
-	 * PreProcess Authn request
-	 * @param request
-	 * @param response
-	 * @param pendingReq
-	 * @throws Throwable
-	 */
-	private void preProcessAuthRequest(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
-
-		PVPSProfileRequest moaRequest = ((PVPSProfileRequest)pendingReq.getRequest());		
-		SignableXMLObject samlReq =  moaRequest.getSamlRequest();
-
-		if(!(samlReq instanceof AuthnRequest)) {
-			throw new InvalidPVPRequestException("Unsupported request", new Object[] {});
-		}
-				
-		EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider);
-		if(metadata == null) {
-			throw new NoMetadataInformationException();
-		}
-		SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
-		
-		AuthnRequest authnRequest = (AuthnRequest)samlReq;
-		
-		if (authnRequest.getIssueInstant() == null) {
-			log.warn("Unsupported request: No IssueInstant Attribute found.");
-			throw new AuthnRequestValidatorException("pvp2.22", 
-					new Object[] {"Unsupported request: No IssueInstant Attribute found"}, 
-					pendingReq);
-			
-		}
-		
-		if (authnRequest.getIssueInstant().minusMinutes(EAAFConstants.ALLOWED_TIME_JITTER).isAfterNow()) {
-			log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore.");
-			throw new AuthnRequestValidatorException("pvp2.22", 
-					new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."},
-					pendingReq);
-			
-		}
-			
-		//parse AssertionConsumerService
-		AssertionConsumerService consumerService = null;
-		if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) && 
-				StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) {
-			//use AssertionConsumerServiceURL from request
-
-			//check requested AssertionConsumingService URL against metadata
-			List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices();
-			for (AssertionConsumerService service : metadataAssertionServiceList) {
-				if (authnRequest.getProtocolBinding().equals(service.getBinding())
-						&& authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) {
-					consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
-					consumerService.setBinding(authnRequest.getProtocolBinding());
-					consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL());					
-					log.debug("Requested AssertionConsumerServiceURL is valid.");
-				}				
-			}
-			
-			if (consumerService == null) {				
-				throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL());
-				
-			}
-
-
-		} else {
-			//use AssertionConsumerServiceIndex and select consumerService from metadata
-			Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();
-			int assertionidx = 0;
-		
-			if(aIdx != null) {
-				assertionidx = aIdx.intValue();
-			
-			} else {				
-				assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor);
-				
-			}		
-			consumerService  = spSSODescriptor.getAssertionConsumerServices().get(assertionidx);
-			
-			if (consumerService == null) {			
-				throw new InvalidAssertionConsumerServiceException(aIdx);
-				
-			}			
-		}
-		
-				
-		//validate AuthnRequest
-		AuthnRequest authReq = (AuthnRequest) samlReq;
-		String oaURL = moaRequest.getEntityMetadata(metadataProvider).getEntityID();
-		log.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding());
-								
-		pendingReq.setSPEntityId(StringEscapeUtils.escapeHtml(oaURL));
-		pendingReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(pendingReq.getSPEntityId()));
-		pendingReq.setBinding(consumerService.getBinding());
-		pendingReq.setRequest(moaRequest);
-		pendingReq.setConsumerURL(consumerService.getLocation());
-		
-		//parse AuthRequest
-		pendingReq.setPassiv(authReq.isPassive());
-		pendingReq.setForce(authReq.isForceAuthn());
-
-		//AuthnRequest needs authentication
-		pendingReq.setNeedAuthentication(true);
-
-		//set protocol action, which should be executed after authentication
-		pendingReq.setAction(AuthenticationAction.class.getName());
-		
-		 // do post-processing if required
-    log.trace("Starting extended AuthnRequest validation and processing ... ");
-    if (authRequestPostProcessors != null) {
-      for (final IAuthnRequestPostProcessor processor : authRequestPostProcessors) {
-        log.trace("Post-process AuthnRequest with module: {}", processor.getClass().getSimpleName());
-        processor.process(request, pendingReq, authReq, spSSODescriptor);
-
-      }
-    }
-    
-		log.debug("Extended AuthnRequest validation and processing finished");
-				
-		//write revisionslog entry
-		revisionsLogger.logEvent(pendingReq, PVPEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST, authReq.getID());
-		
-	}
-	
-	@PostConstruct
-	private void verifyInitialization() {
-		if (pvpIDPCredentials == null) {
-			log.error("No SAML2 credentialProvider injected!");
-			throw new RuntimeException("No SAML2 credentialProvider injected!");
-			
-		}		
-	}
-	
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java
index 597d3c22..a56c8726 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java
@@ -1,29 +1,22 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,  
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, 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 "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
  * https://joinup.ec.europa.eu/news/understanding-eupl-v12
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *  
- * 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.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * 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.gv.egiz.eaaf.modules.pvp2.idp.impl;
 
 import java.util.List;
@@ -32,518 +25,540 @@ import javax.annotation.PostConstruct;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameID;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.core.Status;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.core.StatusMessage;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.ws.security.SecurityPolicyException;
-import org.opensaml.xml.security.x509.X509Credential;
-import org.opensaml.xml.signature.SignableXMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
 import at.gv.egiz.components.eventlog.api.EventConstants;
 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.EaafConstants;
 import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
 import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
 import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
 import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
 import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException;
-import at.gv.egiz.eaaf.core.exceptions.SLOException;
+import at.gv.egiz.eaaf.core.exceptions.SloException;
 import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
-import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.PvpEventConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration;
 import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider;
 import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor;
-import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPVPRequestException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.NameIdFormatNotSupportedException;
 import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
 import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException;
 import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding;
 import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
 import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding;
 import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EAAFURICompare;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
 import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SAMLVerificationEngine;
- 
-public abstract class AbstractPVP2XProtocol extends AbstractController implements IModulInfo {
-	private static final Logger log = LoggerFactory.getLogger(AbstractPVP2XProtocol.class);
-	
-	@Autowired(required=true) protected IPVP2BasicConfiguration pvpBasicConfiguration;
-	@Autowired(required=true) protected IPVPMetadataProvider metadataProvider;
-	@Autowired(required=true) protected SAMLVerificationEngine samlVerificationEngine;
-	@Autowired(required=false) protected List<IAuthnRequestPostProcessor> authRequestPostProcessors;
-	
-	private AbstractCredentialProvider pvpIDPCredentials;
-
-	
-		
-	/**
-	 * Sets a specific credential provider for PVP S-Profile IDP component.
-	 * @param pvpIDPCredentials credential provider
-	 */
-	public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) {
-		this.pvpIDPCredentials = pvpIDPCredentials;
-		
-	}
-	
-	public boolean generateErrorMessage(Throwable e,
-			HttpServletRequest request, HttpServletResponse response,
-			IRequest protocolRequest) throws Throwable {
-		
-		if(protocolRequest == null) {
-			throw e;
-		}
-		
-		if(!(protocolRequest instanceof PVPSProfilePendingRequest) ) {
-			throw e;
-		}
-		PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest)protocolRequest;
-		
-		Response samlResponse = 
-				SAML2Utils.createSAMLObject(Response.class);
-		Status status = SAML2Utils.createSAMLObject(Status.class);
-		StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
-		StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);
-		
-		String moaError = null;
-		
-		if(e instanceof NoPassivAuthenticationException) {
-			statusCode.setValue(StatusCode.NO_PASSIVE_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));	
-			
-		} else if (e instanceof NameIDFormatNotSupportedException) {
-			statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
- 
-		} else if (e instanceof SLOException) {
-			//SLOExecpetions only occurs if session information is lost
-			return false;
-			
-		} else if(e instanceof PVP2Exception) {
-			PVP2Exception ex = (PVP2Exception) e;
-			statusCode.setValue(ex.getStatusCodeValue());
-			String statusMessageValue = ex.getStatusMessageValue();
-			if(statusMessageValue != null) {
-				statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue));
-			}						
-			moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId());
-			
-		} else {
-			statusCode.setValue(StatusCode.RESPONDER_URI);
-			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
-			moaError = statusMessager.getResponseErrorCode(e);
-		}
-		
-		
-		if (StringUtils.isNotEmpty(moaError)) {
-			StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class);
-			moaStatusCode.setValue(moaError);
-			statusCode.setStatusCode(moaStatusCode);
-		}
-		
-		status.setStatusCode(statusCode);
-		if(statusMessage.getMessage() != null) {
-			status.setStatusMessage(statusMessage);
-		}
-		samlResponse.setStatus(status);
-		String remoteSessionID = SAML2Utils.getSecureIdentifier();
-		samlResponse.setID(remoteSessionID);
-
-		samlResponse.setIssueInstant(new DateTime());
-		Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
-		nissuer.setValue(pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL()));
-		nissuer.setFormat(NameID.ENTITY);
-		samlResponse.setIssuer(nissuer);
-		
-		IEncoder encoder = null;
-		
-		if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {			
-			encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class);
-						
-		} else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))  {
-			encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class);
-			
-		} else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI))  {
-			encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class);
-		}
-
-		if(encoder == null) {
-			// default to redirect binding
-			encoder = new RedirectBinding();
-		}
-
-		String relayState = null;
-		if (pvpRequest.getRequest() != null)
-			relayState = pvpRequest.getRequest().getRelayState();
-		
-		X509Credential signCred = pvpIDPCredentials.getIDPAssertionSigningCredential();
-		
-		encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), 
-				relayState, signCred, protocolRequest);
-		return true;
-	}
-
-	public boolean validate(HttpServletRequest request,
-			HttpServletResponse response, IRequest pending) {
-		
-		return true;
-	}
-		
-	protected void pvpMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {		
-		//create pendingRequest object
-		PVPSProfilePendingRequest pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-		pendingReq.initialize(req, authConfig);
-		pendingReq.setModule(getName());
-		
-		revisionsLogger.logEvent(
-				pendingReq.getUniqueSessionIdentifier(), 
-				pendingReq.getUniqueTransactionIdentifier(), 
-				EventConstants.TRANSACTION_IP, 
-				req.getRemoteAddr());
-				
-		MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class);
-		metadataAction.processRequest(pendingReq, 
-				req, resp, null);
-		
-	}
-	
-	protected void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {		
-		PVPSProfilePendingRequest pendingReq = null;
-		
-		try {
-			//create pendingRequest object
-			pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-			pendingReq.initialize(req, authConfig);
-			pendingReq.setModule(getName());
-			
-			revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
-			revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());						
-			revisionsLogger.logEvent(
-					pendingReq.getUniqueSessionIdentifier(), 
-					pendingReq.getUniqueTransactionIdentifier(), 
-					EventConstants.TRANSACTION_IP, 
-					req.getRemoteAddr());
-			
-			//get POST-Binding decoder implementation
-			InboundMessage msg = (InboundMessage) new PostBinding().decode(
-					req, resp, metadataProvider, false,
-					new EAAFURICompare(pvpBasicConfiguration.getIDPSSOPostService(pendingReq.getAuthURL())));
-			pendingReq.setRequest(msg);
-						
-			//preProcess Message
-			preProcess(req, resp, pendingReq);
-						
-		} catch (SecurityPolicyException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-			
-		} catch (SecurityException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-		
-		} catch (EAAFException e) {
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw e;
-			
-		} catch (Throwable e) {			
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
-		}					
-	}
-	
-	protected void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {
-		PVPSProfilePendingRequest pendingReq = null;
-		try {
-			//create pendingRequest object
-			pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
-			pendingReq.initialize(req, authConfig);
-			pendingReq.setModule(getName());
-			
-			revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
-			revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());						
-			revisionsLogger.logEvent(
-					pendingReq.getUniqueSessionIdentifier(), 
-					pendingReq.getUniqueTransactionIdentifier(), 
-					EventConstants.TRANSACTION_IP, 
-					req.getRemoteAddr());
-			
-			//get POST-Binding decoder implementation
-			InboundMessage msg = (InboundMessage) new RedirectBinding().decode(
-					req, resp, metadataProvider, false,
-					new EAAFURICompare(pvpBasicConfiguration.getIDPSSORedirectService(pendingReq.getAuthURL())));
-			pendingReq.setRequest(msg);
-			
-			//preProcess Message
-			preProcess(req, resp, pendingReq);
-						
-		} catch (SecurityPolicyException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-			
-		} catch (SecurityException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-			
-		} catch (EAAFException e) {
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.info("Receive INVALID protocol request: " + samlRequest);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-			
-			throw e;
-						
-		} catch (Throwable e) {			
-			String samlRequest = req.getParameter("SAMLRequest");			
-			log.warn("Receive INVALID protocol request: " + samlRequest, e);
-			
-			//write revision log entries
-			if (pendingReq != null)
-				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
-						
-			throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
-		}					
-	}
-	
-	
-	
-	/**
-	 * 
-	 * 
-	 * @param request
-	 * @param response
-	 * @param msg
-	 * @return true if preprocess can handle this request type, otherwise false
-	 * @throws Throwable
-	 */
-	abstract protected boolean childPreProcess(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable;
-	
-	protected void preProcess(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
-			
-			InboundMessage msg = pendingReq.getRequest();
-		
-			if (StringUtils.isEmpty(msg.getEntityID())) {
-				throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
-				
-			}
-			
-			if(!msg.isVerified()) {
-				samlVerificationEngine.verify(msg, 
-						TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
-				msg.setVerified(true);
-								
-			}
-			
-			revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE, getAuthProtocolIdentifier());
-			
-			if (msg instanceof PVPSProfileRequest && 
-					((PVPSProfileRequest)msg).getSamlRequest() instanceof AuthnRequest)
-				preProcessAuthRequest(request, response, pendingReq);
-
-			else if (childPreProcess(request, response, pendingReq))
-				log.debug("Find protocol handler in child implementation");
-				
-			else {
-				log.error("Receive unsupported PVP21 message of type: " + ((PVPSProfileRequest)msg).getSamlRequest().getClass().getName());
-				throw new InvalidPVPRequestException("pvp2.09", 
-						new Object[] {((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()});
-			}
-							
-			
-			
-			//switch to session authentication
-			protAuthService.performAuthentication(request, response, pendingReq);								
-	}
-
-	
-	/**
-	 * PreProcess Authn request
-	 * @param request
-	 * @param response
-	 * @param pendingReq
-	 * @throws Throwable
-	 */
-	private void preProcessAuthRequest(HttpServletRequest request,
-			HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
-
-		PVPSProfileRequest moaRequest = ((PVPSProfileRequest)pendingReq.getRequest());		
-		SignableXMLObject samlReq =  moaRequest.getSamlRequest();
-
-		if(!(samlReq instanceof AuthnRequest)) {
-			throw new InvalidPVPRequestException("Unsupported request", new Object[] {});
-		}
-				
-		EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider);
-		if(metadata == null) {
-			throw new NoMetadataInformationException();
-		}
-		SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
-		
-		AuthnRequest authnRequest = (AuthnRequest)samlReq;
-		
-		if (authnRequest.getIssueInstant() == null) {
-			log.warn("Unsupported request: No IssueInstant Attribute found.");
-			throw new AuthnRequestValidatorException("pvp2.22", 
-					new Object[] {"Unsupported request: No IssueInstant Attribute found"}, 
-					pendingReq);
-			
-		}
-		
-		if (authnRequest.getIssueInstant().minusMinutes(EAAFConstants.ALLOWED_TIME_JITTER).isAfterNow()) {
-			log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore.");
-			throw new AuthnRequestValidatorException("pvp2.22", 
-					new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."},
-					pendingReq);
-			
-		}
-			
-		//parse AssertionConsumerService
-		AssertionConsumerService consumerService = null;
-		if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) && 
-				StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) {
-			//use AssertionConsumerServiceURL from request
-
-			//check requested AssertionConsumingService URL against metadata
-			List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices();
-			for (AssertionConsumerService service : metadataAssertionServiceList) {
-				if (authnRequest.getProtocolBinding().equals(service.getBinding())
-						&& authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) {
-					consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
-					consumerService.setBinding(authnRequest.getProtocolBinding());
-					consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL());					
-					log.debug("Requested AssertionConsumerServiceURL is valid.");
-				}				
-			}
-			
-			if (consumerService == null) {				
-				throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL());
-				
-			}
-
-
-		} else {
-			//use AssertionConsumerServiceIndex and select consumerService from metadata
-			Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();
-			int assertionidx = 0;
-		
-			if(aIdx != null) {
-				assertionidx = aIdx.intValue();
-			
-			} else {				
-				assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor);
-				
-			}		
-			consumerService  = spSSODescriptor.getAssertionConsumerServices().get(assertionidx);
-			
-			if (consumerService == null) {			
-				throw new InvalidAssertionConsumerServiceException(aIdx);
-				
-			}			
-		}
-		
-				
-		//validate AuthnRequest
-		AuthnRequest authReq = (AuthnRequest) samlReq;
-		String oaURL = moaRequest.getEntityMetadata(metadataProvider).getEntityID();
-		log.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding());
-								
-		pendingReq.setSPEntityId(StringEscapeUtils.escapeHtml(oaURL));
-		pendingReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(pendingReq.getSPEntityId()));
-		pendingReq.setBinding(consumerService.getBinding());
-		pendingReq.setRequest(moaRequest);
-		pendingReq.setConsumerURL(consumerService.getLocation());
-		
-		//parse AuthRequest
-		pendingReq.setPassiv(authReq.isPassive());
-		pendingReq.setForce(authReq.isForceAuthn());
-
-		//AuthnRequest needs authentication
-		pendingReq.setNeedAuthentication(true);
-
-		//set protocol action, which should be executed after authentication
-		pendingReq.setAction(AuthenticationAction.class.getName());
-		
-		 // do post-processing if required
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.Status;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.StatusMessage;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.xmlsec.signature.SignableXMLObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public abstract class AbstractPvp2XProtocol extends AbstractController implements IModulInfo {
+  private static final Logger log = LoggerFactory.getLogger(AbstractPvp2XProtocol.class);
+
+  private static final String HTTP_PARAM_SAMLREQ = "SAMLRequest";
+  private static final String ERROR_INVALID_REQUEST = "Receive INVALID protocol request: {}";
+
+  @Autowired(required = true)
+  protected IPvp2BasicConfiguration pvpBasicConfiguration;
+  @Autowired(required = true)
+  protected IPvp2MetadataProvider metadataProvider;
+  @Autowired(required = true)
+  protected SamlVerificationEngine samlVerificationEngine;
+  @Autowired(required = false)
+  protected List<IAuthnRequestPostProcessor> authRequestPostProcessors;
+
+  private IPvp2CredentialProvider pvpIdpCredentials;
+
+  /**
+   * Sets a specific credential provider for PVP S-Profile IDP component.
+   *
+   * @param pvpIdpCredentials credential provider
+   */
+  public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) {
+    this.pvpIdpCredentials = pvpIdpCredentials;
+
+  }
+
+  @Override
+  public boolean generateErrorMessage(final Throwable e, final HttpServletRequest request,
+      final HttpServletResponse response, final IRequest protocolRequest) throws Throwable {
+
+    if (protocolRequest == null) {
+      throw e;
+    }
+
+    if (!(protocolRequest instanceof PvpSProfilePendingRequest)) {
+      throw e;
+    }
+    final PvpSProfilePendingRequest pvpRequest = (PvpSProfilePendingRequest) protocolRequest;
+
+    final Response samlResponse = Saml2Utils.createSamlObject(Response.class);
+    final Status status = Saml2Utils.createSamlObject(Status.class);
+    final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class);
+    final StatusMessage statusMessage = Saml2Utils.createSamlObject(StatusMessage.class);
+
+    String moaError = null;
+
+    if (e instanceof NoPassivAuthenticationException) {
+      statusCode.setValue(StatusCode.NO_PASSIVE);
+      statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+
+    } else if (e instanceof NameIdFormatNotSupportedException) {
+      statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY);
+      statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+
+    } else if (e instanceof SloException) {
+      // SLOExecpetions only occurs if session information is lost
+      return false;
+
+    } else if (e instanceof Pvp2Exception) {
+      final Pvp2Exception ex = (Pvp2Exception) e;
+      statusCode.setValue(ex.getStatusCodeValue());
+      final String statusMessageValue = ex.getStatusMessageValue();
+      if (statusMessageValue != null) {
+        statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue));
+      }
+      moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId());
+
+    } else {
+      statusCode.setValue(StatusCode.RESPONDER);
+      statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+      moaError = statusMessager.getResponseErrorCode(e);
+    }
+
+    if (StringUtils.isNotEmpty(moaError)) {
+      final StatusCode moaStatusCode = Saml2Utils.createSamlObject(StatusCode.class);
+      moaStatusCode.setValue(moaError);
+      statusCode.setStatusCode(moaStatusCode);
+    }
+
+    status.setStatusCode(statusCode);
+    if (statusMessage.getMessage() != null) {
+      status.setStatusMessage(statusMessage);
+    }
+    samlResponse.setStatus(status);
+    final String remoteSessionID = Saml2Utils.getSecureIdentifier();
+    samlResponse.setID(remoteSessionID);
+
+    samlResponse.setIssueInstant(new DateTime());
+    final Issuer nissuer = Saml2Utils.createSamlObject(Issuer.class);
+    nissuer.setValue(pvpBasicConfiguration.getIdpEntityId(pvpRequest.getAuthUrl()));
+    nissuer.setFormat(NameIDType.ENTITY);
+    samlResponse.setIssuer(nissuer);
+
+    IEncoder encoder = null;
+
+    if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+      encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class);
+
+    } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
+      encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class);
+
+    } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) {
+      encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class);
+    }
+
+    if (encoder == null) {
+      // default to redirect binding
+      encoder = new RedirectBinding();
+    }
+
+    String relayState = null;
+    if (pvpRequest.getRequest() != null) {
+      relayState = pvpRequest.getRequest().getRelayState();
+    }
+
+    final EaafX509Credential signCred = pvpIdpCredentials.getMessageSigningCredential();
+
+    encoder.encodeResponse(request, response, samlResponse, pvpRequest.getConsumerUrl(), relayState,
+        signCred, protocolRequest);
+    return true;
+  }
+
+  @Override
+  public boolean validate(final HttpServletRequest request, final HttpServletResponse response,
+      final IRequest pending) {
+
+    return true;
+  }
+
+  protected void pvpMetadataRequest(final HttpServletRequest req, final HttpServletResponse resp)
+      throws EaafException {
+    // create pendingRequest object
+    final PvpSProfilePendingRequest pendingReq =
+        applicationContext.getBean(PvpSProfilePendingRequest.class);
+    pendingReq.initialize(req, authConfig);
+    pendingReq.setModule(getName());
+
+    revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(),
+        pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP,
+        req.getRemoteAddr());
+
+    final MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class);
+    metadataAction.processRequest(pendingReq, req, resp, null);
+
+  }
+
+  protected void pvpIdpPostRequest(final HttpServletRequest req, final HttpServletResponse resp)
+      throws EaafException {
+    PvpSProfilePendingRequest pendingReq = null;
+
+    try {
+      // create pendingRequest object
+      pendingReq = applicationContext.getBean(PvpSProfilePendingRequest.class);
+      pendingReq.initialize(req, authConfig);
+      pendingReq.setModule(getName());
+
+      revisionsLogger.logEvent(EventConstants.SESSION_CREATED,
+          pendingReq.getUniqueSessionIdentifier());
+      revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED,
+          pendingReq.getUniqueTransactionIdentifier());
+      revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(),
+          pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP,
+          req.getRemoteAddr());
+
+      // get POST-Binding decoder implementation
+      final InboundMessage msg = (InboundMessage) new PostBinding().decode(req, resp,
+          metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+          new EaafUriCompare(pvpBasicConfiguration.getIdpSsoPostService(pendingReq.getAuthUrl())));
+      pendingReq.setRequest(msg);
+
+      // preProcess Message
+      preProcess(req, resp, pendingReq);
+
+    } catch (final SamlSigningException e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+    } catch (final Pvp2Exception e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() });
+
+    } catch (final EaafException e) {
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw e;
+
+    } catch (final Throwable e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new EaafException("pvp2.24", new Object[] { e.getMessage() }, e);
+    }
+  }
+
+  protected void pvpIdpRedirecttRequest(final HttpServletRequest req,
+      final HttpServletResponse resp) throws EaafException {
+    PvpSProfilePendingRequest pendingReq = null;
+    try {
+      // create pendingRequest object
+      pendingReq = applicationContext.getBean(PvpSProfilePendingRequest.class);
+      pendingReq.initialize(req, authConfig);
+      pendingReq.setModule(getName());
+
+      revisionsLogger.logEvent(EventConstants.SESSION_CREATED,
+          pendingReq.getUniqueSessionIdentifier());
+      revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED,
+          pendingReq.getUniqueTransactionIdentifier());
+      revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(),
+          pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP,
+          req.getRemoteAddr());
+
+      // get POST-Binding decoder implementation
+      final InboundMessage msg = (InboundMessage) new RedirectBinding().decode(req, resp,
+          metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, new EaafUriCompare(
+              pvpBasicConfiguration.getIdpSsoRedirectService(pendingReq.getAuthUrl())));
+      pendingReq.setRequest(msg);
+
+      // preProcess Message
+      preProcess(req, resp, pendingReq);
+
+    } catch (final SamlSigningException e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+    } catch (final Pvp2Exception e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() });
+
+    } catch (final EaafException e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.info(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw e;
+
+    } catch (final Throwable e) {
+      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ);
+      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);
+
+      // write revision log entries
+      if (pendingReq != null) {
+        revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+            pendingReq.getUniqueTransactionIdentifier());
+      }
+
+      throw new EaafException("pvp2.24", new Object[] { e.getMessage() }, e);
+    }
+  }
+
+  /**
+   * Authentication request pre-processor.
+   *
+   * @param request    http request
+   * @param response   http response
+   * @param pendingReq current pending request
+   * @return true if preprocess can handle this request type, otherwise false
+   * @throws Throwable In case of an error
+   */
+  protected abstract boolean childPreProcess(HttpServletRequest request,
+      HttpServletResponse response, PvpSProfilePendingRequest pendingReq) throws Throwable;
+
+  protected void preProcess(final HttpServletRequest request, final HttpServletResponse response,
+      final PvpSProfilePendingRequest pendingReq) throws Throwable {
+
+    final InboundMessage msg = pendingReq.getRequest();
+
+    if (StringUtils.isEmpty(msg.getEntityID())) {
+      throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
+
+    }
+
+    if (!msg.isVerified()) {
+      samlVerificationEngine.verify(msg,
+          TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+      msg.setVerified(true);
+
+    }
+
+    revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE,
+        getAuthProtocolIdentifier());
+
+    if (msg instanceof PvpSProfileRequest
+        && ((PvpSProfileRequest) msg).getSamlRequest() instanceof AuthnRequest) {
+      preProcessAuthRequest(request, pendingReq);
+    } else if (childPreProcess(request, response, pendingReq)) {
+      log.debug("Find protocol handler in child implementation");
+    } else {
+      log.error("Receive unsupported PVP21 message of type: "
+          + ((PvpSProfileRequest) msg).getSamlRequest().getClass().getName());
+      throw new InvalidPvpRequestException("pvp2.09",
+          new Object[] { ((PvpSProfileRequest) msg).getSamlRequest().getClass().getName() });
+    }
+
+    // switch to session authentication
+    protAuthService.performAuthentication(request, response, pendingReq);
+  }
+
+  /**
+   * PreProcess Authn request.
+   *
+   * @param request    http request
+   * @param pendingReq current pending request
+   * @throws Throwable in case of an error
+   */
+  protected void preProcessAuthRequest(final HttpServletRequest request,
+      final PvpSProfilePendingRequest pendingReq)
+      throws Throwable {
+
+    final PvpSProfileRequest moaRequest = (PvpSProfileRequest) pendingReq.getRequest();
+    final SignableXMLObject samlReq = moaRequest.getSamlRequest();
+
+    if (!(samlReq instanceof AuthnRequest)) {
+      throw new InvalidPvpRequestException("Unsupported request", new Object[] {});
+    }
+
+    final EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider);
+    if (metadata == null) {
+      throw new NoMetadataInformationException();
+    }
+    final SPSSODescriptor spSsoDescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+
+    final AuthnRequest authnRequest = (AuthnRequest) samlReq;
+
+    if (authnRequest.getIssueInstant() == null) {
+      log.warn("Unsupported request: No IssueInstant Attribute found.");
+      throw new AuthnRequestValidatorException("pvp2.22",
+          new Object[] { "Unsupported request: No IssueInstant Attribute found" }, pendingReq);
+
+    }
+
+    if (authnRequest.getIssueInstant().minusMinutes(EaafConstants.ALLOWED_TIME_JITTER)
+        .isAfterNow()) {
+      log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore.");
+      throw new AuthnRequestValidatorException("pvp2.22",
+          new Object[] { "Unsupported request: No IssueInstant DateTime is not valid anymore." },
+          pendingReq);
+
+    }
+
+    // parse AssertionConsumerService
+    AssertionConsumerService consumerService = null;
+    if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL())
+        && StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) {
+      // use AssertionConsumerServiceURL from request
+
+      // check requested AssertionConsumingService URL against metadata
+      final List<AssertionConsumerService> metadataAssertionServiceList =
+          spSsoDescriptor.getAssertionConsumerServices();
+      for (final AssertionConsumerService service : metadataAssertionServiceList) {
+        if (authnRequest.getProtocolBinding().equals(service.getBinding())
+            && authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) {
+          consumerService = Saml2Utils.createSamlObject(AssertionConsumerService.class);
+          consumerService.setBinding(authnRequest.getProtocolBinding());
+          consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL());
+          log.debug("Requested AssertionConsumerServiceURL is valid.");
+        }
+      }
+
+      if (consumerService == null) {
+        throw new InvalidAssertionConsumerServiceException(
+            authnRequest.getAssertionConsumerServiceURL());
+
+      }
+
+    } else {
+      // use AssertionConsumerServiceIndex and select consumerService from metadata
+      final Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();
+      int assertionidx = 0;
+
+      if (aIdx != null) {
+        assertionidx = aIdx;
+
+      } else {
+        assertionidx = Saml2Utils.getDefaultAssertionConsumerServiceIndex(spSsoDescriptor);
+
+      }
+      consumerService = spSsoDescriptor.getAssertionConsumerServices().get(assertionidx);
+
+      if (consumerService == null) {
+        throw new InvalidAssertionConsumerServiceException(aIdx);
+
+      }
+    }
+
+    // validate AuthnRequest
+    final AuthnRequest authReq = (AuthnRequest) samlReq;
+    final String oaUrl = moaRequest.getEntityMetadata(metadataProvider).getEntityID();
+    log.info(
+        "Dispatch PVP2 AuthnRequest: OAURL=" + oaUrl + " Binding=" + consumerService.getBinding());
+
+    pendingReq.setSpEntityId(StringEscapeUtils.escapeHtml(oaUrl));
+    pendingReq.setOnlineApplicationConfiguration(
+        authConfig.getServiceProviderConfiguration(pendingReq.getSpEntityId()));
+    pendingReq.setBinding(consumerService.getBinding());
+    pendingReq.setRequest(moaRequest);
+    pendingReq.setConsumerUrl(consumerService.getLocation());
+
+    // parse AuthRequest
+    pendingReq.setPassiv(authReq.isPassive());
+    pendingReq.setForce(authReq.isForceAuthn());
+
+    // AuthnRequest needs authentication
+    pendingReq.setNeedAuthentication(true);
+
+    // set protocol action, which should be executed after authentication
+    pendingReq.setAction(AuthenticationAction.class.getName());
+
+    // do post-processing if required
     log.trace("Starting extended AuthnRequest validation and processing ... ");
     if (authRequestPostProcessors != null) {
       for (final IAuthnRequestPostProcessor processor : authRequestPostProcessors) {
         log.trace("Post-process AuthnRequest with module: {}", processor.getClass().getSimpleName());
-        processor.process(request, pendingReq, authReq, spSSODescriptor);
+        processor.process(request, pendingReq, authReq, spSsoDescriptor);
 
       }
     }
-    
-		log.debug("Extended AuthnRequest validation and processing finished");
-				
-		//write revisionslog entry
-		revisionsLogger.logEvent(pendingReq, PVPEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST, authReq.getID());
-		
-	}
-	
-	@PostConstruct
-	private void verifyInitialization() {
-		if (pvpIDPCredentials == null) {
-			log.error("No SAML2 credentialProvider injected!");
-			throw new RuntimeException("No SAML2 credentialProvider injected!");
-			
-		}		
-	}
-	
+
+    log.debug("Extended AuthnRequest validation and processing finished");
+
+    // write revisionslog entry
+    revisionsLogger.logEvent(pendingReq, PvpEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST,
+        authReq.getID());
+
+  }
+
+  @PostConstruct
+  private void verifyInitialization() {
+    if (pvpIdpCredentials == null) {
+      log.error("No SAML2 credentialProvider injected!");
+      throw new RuntimeException("No SAML2 credentialProvider injected!");
+
+    }
+  }
+
 }
-- 
cgit v1.2.3