diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-04-11 09:44:11 +0200 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-04-11 09:44:11 +0200 | 
| commit | 61d276832ebcf1901183dab323126f8ecb6a7370 (patch) | |
| tree | ec9df86e1eb3cfb74f1fb68a371cb21d04e40d6b /eaaf_core/src/main/java | |
| parent | 13952dddd85fc08115f963b259885b5c9b7f2b57 (diff) | |
| download | EAAF-Components-61d276832ebcf1901183dab323126f8ecb6a7370.tar.gz EAAF-Components-61d276832ebcf1901183dab323126f8ecb6a7370.tar.bz2 EAAF-Components-61d276832ebcf1901183dab323126f8ecb6a7370.zip | |
refactor protocol finalization to support protocol response without final redirect
Diffstat (limited to 'eaaf_core/src/main/java')
13 files changed, 630 insertions, 519 deletions
| diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/data/EAAFConstants.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/data/EAAFConstants.java index b60d39e1..0a457825 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/data/EAAFConstants.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/data/EAAFConstants.java @@ -66,8 +66,12 @@ public class EAAFConstants {  	public static final String PROCESS_ENGINE_SERVICE_PROVIDER_ENTITYID = PROCESS_ENGINE_PREFIX + "uniqueSPId";  	public static final String PROCESS_ENGINE_SSL_CLIENT_CERTIFICATE = PROCESS_ENGINE_PREFIX + "holderofkey_cert";  	public static final String PROCESSCONTEXT_SP_CONFIG = PROCESS_ENGINE_PREFIX +  "spConfig"; +	public static final String PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT  +														= PROCESS_ENGINE_PREFIX + "requireNoPostAuthRedirect";  	public static final int ALLOWED_TIME_JITTER = 5; //minutes  	public static final String COUNTRYCODE_AUSTRIA = "AT"; + +	public static final String TESTCREDENTIALROOTOID = "1.2.40.0.10.2.4.1";  } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/IAuthData.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/IAuthData.java index e8e41999..7dcd643d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/IAuthData.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/IAuthData.java @@ -119,6 +119,7 @@ public interface IAuthData {  	 *   	 * @return  	 */ +	@Deprecated  	String getBPK();  	/** @@ -127,6 +128,7 @@ public interface IAuthData {  	 *   	 * @return Sector identifier with prefix  	 */ +	@Deprecated  	String getBPKType(); @@ -134,6 +136,7 @@ public interface IAuthData {  	 * Get List of bPK/bPKType tuples for this service provider    	 * @return List of Pairs<bPK, bPKType>  	 */ +	@Deprecated  	List<Pair<String, String>> getAdditionalbPKs();  	/** @@ -141,6 +144,7 @@ public interface IAuthData {  	 *   	 * @return  	 */ +	@Deprecated  	String getIdentificationValue();  	/** @@ -149,6 +153,7 @@ public interface IAuthData {  	 *   	 * @return  	 */ +	@Deprecated  	String getIdentificationType(); @@ -157,6 +162,7 @@ public interface IAuthData {  	 *   	 * @return IDL, or NULL if no IDL is available  	 */ +	@Deprecated  	IIdentityLink getIdentityLink();  	 /** diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/ISSOManager.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/ISSOManager.java index cba8fde7..5481fd52 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/ISSOManager.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/ISSOManager.java @@ -60,11 +60,11 @@ public interface ISSOManager {  	/**  	 * Populate service provider specific SSO settings  	 *  -	 * Check if Single Sign-On is allowed for the current pending request and the requested service provider  +	 * Check if Single Sign-On is allowed for the current pending request and the requested service provider +	 * Set IRequest.needSingleSignOnFunctionality() to true if SSO is allowed    	 *   	 * @param pendingReq Current incoming pending request  	 * @param httpReq http Servlet request -	 * @return true if SSO is allowed for this service provider, otherwise false  	 */  	public void isSSOAllowedForSP(IRequest pendingReq, HttpServletRequest httpReq); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/data/IAuthProcessDataContainer.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/data/IAuthProcessDataContainer.java index 76e071c6..46dd3850 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/data/IAuthProcessDataContainer.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/data/IAuthProcessDataContainer.java @@ -67,6 +67,7 @@ public interface IAuthProcessDataContainer {  	 *   	 * @return IdentityLink  	 */ +	@Deprecated  	IIdentityLink getIdentityLink();  	/** @@ -75,9 +76,9 @@ public interface IAuthProcessDataContainer {  	 * @param identityLink  	 *            The identityLink to set  	 */ +	@Deprecated  	void setIdentityLink(IIdentityLink identityLink); -  	/**  	 * Indicate that mandates was used in this auth. process  	 *  diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java new file mode 100644 index 00000000..f6f8e576 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * 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.core.api.idp.auth.services; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; + +public interface IProtocolAuthenticationService { + +	/** +	 * Initialize an authentication process for this protocol request +	 *  +	 * @param httpReq HttpServletRequest	 +	 * @param httpResp HttpServletResponse +	 * @param protocolRequest Authentication request which is actually in process +	 * @throws IOException  +	 * @throws EAAFException  +	 */ +	void performAuthentication(HttpServletRequest req, HttpServletResponse resp, IRequest pendingReq) +			throws IOException, EAAFException; + +	/** +	 * Finalize the requested protocol operation +	 *  +	 * @param httpReq HttpServletRequest	 +	 * @param httpResp HttpServletResponse +	 * @param protocolRequest Authentication request which is actually in process +	 * @throws IOException If response can not be written into {@link HttpServletResponse} +	 * @throws EAAFException If an internal error occur  +	 */ +	void finalizeAuthentication(HttpServletRequest req, HttpServletResponse resp, IRequest pendingReq) throws EAAFException, IOException; + +	/** +	 * @param throwable Exception that should be handled +	 * @param req Current open http request as {@link HttpServletRequest} +	 * @param resp Current open http response as {@link HttpServletResponse} +	 * @param pendingReq Authentication request which is actually in process +	 * @throws IOException If response can not be written into {@link HttpServletResponse} +	 * @throws EAAFException If an internal error occur +	 */ +	void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, +			IRequest pendingReq) throws IOException, EAAFException; + +	/** +	 * Handles all exceptions with no pending request. +	 * Therefore, the error is written to the users browser +	 *  +	 * @param throwable Exception that should be handled +	 * @param req Current open http request as {@link HttpServletRequest} +	 * @param resp Current open http response as {@link HttpServletResponse} +	 * @param writeExceptionToStatisticLog if <code>true</code>, the exception get logged into {@link IStatisticLogger} +	 * @throws IOException If response can not be written into {@link HttpServletResponse} +	 * @throws EAAFException If an internal error occure +	 */ +	void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException, EAAFException; + +}
\ No newline at end of file diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java index 23763cde..0d3eaf18 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java @@ -134,8 +134,10 @@ public abstract class AbstractAuthenticationManager implements IAuthenticationMa  			ssoManager.isSSOAllowedForSP(pendingReq, httpReq);  			//check if SSO session is active and valid -			isValidSSOSession = ssoManager.checkAndValidateSSOSession(pendingReq, httpReq, httpResp); -						 +			isValidSSOSession = ssoManager.checkAndValidateSSOSession(pendingReq, httpReq, httpResp) && +					pendingReq.needSingleSignOnFunctionality(); + +			  		}  		//check if session is already authenticated diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java index 0b334126..eb87e893 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java @@ -55,7 +55,7 @@ import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractAuthProtocolModulController; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController;  import at.gv.egiz.eaaf.core.impl.idp.process.springweb.AbstractTask;  import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder; @@ -101,7 +101,7 @@ public abstract class AbstractAuthServletTask extends AbstractTask {  	 * @param httpResp  	 */  	protected void performRedirectToProtocolFinialization(IRequest pendingReq, HttpServletResponse httpResp) { -		performRedirectToItself(pendingReq, httpResp, AbstractAuthProtocolModulController.ENDPOINT_FINALIZEPROTOCOL); +		performRedirectToItself(pendingReq, httpResp, ProtocolFinalizationController.ENDPOINT_FINALIZEPROTOCOL);  	} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java new file mode 100644 index 00000000..85c609e0 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java @@ -0,0 +1,458 @@ +/******************************************************************************* + * Copyright 2019 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.core.impl.idp.auth.services; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.naming.ConfigurationException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IRequestStorage; +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IAction; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IAuthenticationDataBuilder; +import at.gv.egiz.eaaf.core.api.idp.IModulInfo; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; +import at.gv.egiz.eaaf.core.api.idp.auth.ISSOManager; +import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; +import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFSSOException; +import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; +import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; +import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; + +@Service +public class ProtocolAuthenticationService implements IProtocolAuthenticationService { +	private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class); +	 +	@Autowired(required=true) private ApplicationContext applicationContext;	 +	@Autowired(required=true) private ITransactionStorage transactionStorage; +	@Autowired(required=true) private IAuthenticationManager authmanager;			 +	@Autowired(required=true) private IAuthenticationDataBuilder authDataBuilder;	 +	@Autowired(required=true) private IGUIFormBuilder guiBuilder; +	@Autowired(required=true) private IGUIBuilderConfigurationFactory guiConfigFactory; +	@Autowired(required=true) private IStatusMessenger statusMessager; +	@Autowired(required=true) private IRequestStorage requestStorage; +	 +	@Autowired private ISSOManager ssoManager; +	@Autowired private IStatisticLogger statisticLogger; +	@Autowired private IRevisionLogger revisionsLogger; +	 +	/* (non-Javadoc) +	 * @see at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService#performAuthentication(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) +	 */ +	@Override +	public void performAuthentication(final HttpServletRequest req, final HttpServletResponse resp,  +			final IRequest pendingReq) throws IOException, EAAFException { +		try { +			if (pendingReq.isNeedAuthentication()) { +				//request needs authentication --> start authentication process ... +			 +				//load Parameters from OnlineApplicationConfiguration +				final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); +				 +				if (oaParam == null) +					throw new EAAFAuthenticationException( +							IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG,  +							new Object[] { pendingReq.getSPEntityId() }); +									 +				if (authmanager.doAuthentication(req, resp, pendingReq)) {					 +					//pending request is already authenticated --> protocol-specific postProcessing can start directly 					 +					finalizeAuthentication(req, resp, pendingReq); +					 +					//transaction is finished, log transaction finished event +					revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); +					 +				} +							 +			} else {			 +				executeProtocolSpecificAction(req, resp, pendingReq, null); +			 +			} +			 +		} catch (final Exception e) { +			buildProtocolSpecificErrorResponse(e, req, resp, pendingReq);			 +			authmanager.performOnlyIDPLogOut(req, resp, pendingReq); +						 +		}		 +	} +	 +	/* (non-Javadoc) +	 * @see at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService#finalizeAuthentication(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) +	 */ +	@Override +	public void finalizeAuthentication(final HttpServletRequest req, final HttpServletResponse resp, final IRequest pendingReq) throws EAAFException, IOException{ +		log.debug("Finalize PendingRequest with ID " + pendingReq.getPendingRequestId()); +		try { +			 +			//check if pending-request has 'abortedByUser' flag set +			if (pendingReq.isAbortedByUser()) { +				//send authentication aborted error to Service Provider +				buildProtocolSpecificErrorResponse( +						new EAAFAuthenticationException( +								IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP,  +								new Object[] {}),  +						req, resp, pendingReq); +			 +				//do not remove the full active SSO-Session  +				//	in case of only one Service-Provider authentication request is aborted    +				if ( !pendingReq.needSingleSignOnFunctionality())  { +					transactionStorage.remove(pendingReq.getPendingRequestId()); +				 +				}							 + +				//check if pending-request are authenticated					 +			} else if (pendingReq.isAuthenticated()) {				 +				internalFinalizeAuthenticationProcess(req, resp, pendingReq); + +			} else { +				//suspect state: pending-request is not aborted but also are not authenticated  +				log.error("PendingRequest is NOT authenticated --> Abort authentication process!");		 +				handleErrorNoRedirect( +						new EAAFException( +								"auth.20", +								null), req, resp, true);							 +							 +			}		 +		 +		} catch (Exception e) { +			log.error("Finalize authentication protocol FAILED." , e); +			buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); +			 +			if (pendingReq != null) +				transactionStorage.remove(pendingReq.getPendingRequestId()); +			 +		}		 +	 +		//remove pending-request +		if (pendingReq != null) { +			requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); +			revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); +		 +		} +	} + +	 +	@Override +	public void buildProtocolSpecificErrorResponse(final Throwable throwable, final HttpServletRequest req,  +			final HttpServletResponse resp, final IRequest protocolRequest) throws EAAFException, IOException { +		try { +			 +			final Class<?> clazz = Class.forName(protocolRequest.requestedModule()); +			 +			if (clazz == null ||  +					!IModulInfo.class.isAssignableFrom(clazz)) { +				log.error("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +				throw new Exception("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +				 +			} +							 +			final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); +												 +			if (handlingModule.generateErrorMessage( +					throwable, req, resp, protocolRequest)) { +		 +				//log Error to technical log +				logExceptionToTechnicalLog(throwable); +				 +				//log Error Message +				statisticLogger.logErrorOperation(throwable, protocolRequest); +				 +				//write revision log entries +				revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, protocolRequest.getUniqueTransactionIdentifier()); +				 +				return; +				 +			} else { +				handleErrorNoRedirect(throwable, req, resp, true); +				 +			} +			 +		} catch (final Throwable e) { +			handleErrorNoRedirect(throwable, req, resp, true); +			 +		} +		 +	} +	 +	@Override +	public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req,  +			final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws IOException, EAAFException { +		 +		//log Exception into statistic database +		if (writeExceptionToStatisticLog) +			statisticLogger.logErrorOperation(throwable); +		 +		//write errror to console +		logExceptionToTechnicalLog(throwable); +		 +		//return error to Web browser +		if (throwable instanceof EAAFException || throwable instanceof ProcessExecutionException) +			internalMOAIDExceptionHandler(req, resp, (Exception)throwable, false); +		 +		else { +			//write generic message for general exceptions +			final String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null);			 +			writeHTMLErrorResponse(req, resp, msg, "9199", (Exception) throwable); +			 +		} +			 +	} +	 +	/** +	 * Finalize the requested protocol operation +	 *  +	 * @param httpReq HttpServletRequest	 +	 * @param httpResp HttpServletResponse +	 * @param protocolRequest Authentication request which is actually in process +	 * @param moaSession MOASession object, which is used to generate the protocol specific authentication information +	 * @throws Exception  +	 */ +	protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, final HttpServletResponse resp,  +			final IRequest pendingReq) throws Exception { +		 +		String newSSOSessionId = null; +		 +		//if Single Sign-On functionality is enabled for this request +		if (pendingReq.needSingleSignOnFunctionality()) { +			if (ssoManager != null) { +				newSSOSessionId = ssoManager.createNewSSOSessionCookie(req, resp, pendingReq); +				if (StringUtils.isEmpty(pendingReq.getInternalSSOSessionIdentifier())) +					ssoManager.createNewSSOSession(pendingReq, newSSOSessionId);	 +			 +			} else +				log.warn("SSO is requested but there is not SSO Session-Manager available"); +			 +		} +		 +		//build authenticationdata from session information and OA configuration +		final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq);	 +			 +		//execute the protocol-specific action +		final SLOInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); +				 +		//Store OA specific SSO session information if an SSO cookie is set +		if (StringUtils.isNotEmpty(newSSOSessionId)) { 		 +			try { +				ssoManager.updateSSOSession(pendingReq, newSSOSessionId, sloInformation); +																 +			} catch (final EAAFSSOException e) { +				log.warn("SSO Session information can not be stored  -> SSO is not enabled!");				 +				authmanager.performOnlyIDPLogOut(req, resp, pendingReq); +				 +			} +		 +		} else { +			//remove MOASession from database +			authmanager.performOnlyIDPLogOut(req, resp, pendingReq); +			 +		} +	 +		//Advanced statistic logging +		statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSSOSessionId)); +				 +	} +	 +	/** +	 * Executes the requested protocol action +	 *  +	 * @param httpReq HttpServletRequest	 +	 * @param httpResp HttpServletResponse +	 * @param protocolRequest Authentication request which is actually in process +	 * @param authData Service-provider specific authentication data +	 *  +	 * @return Return Single LogOut information or null if protocol supports no SSO +	 *  +	 * @throws Exception  +	 */ +	private SLOInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq, final HttpServletResponse httpResp,  +			final IRequest pendingReq, final IAuthData authData) throws Exception { +		try { +		//	request needs no authentication --> start request processing +			final Class<?> clazz = Class.forName(pendingReq.requestedAction()); +			if (clazz == null ||  +					!IAction.class.isAssignableFrom(clazz)) { +				log.error("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); +				throw new Exception("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); +				 +			} +			 +			final IAction protocolAction = (IAction) applicationContext.getBean(clazz);			  +			return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); +			 +		} catch (final ClassNotFoundException e) { +			log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); +			throw new Exception("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); +		} +		 +	} +	 +	/** +	 * Write a Exception to the MOA-ID-Auth internal technical log +	 *  +	 * @param loggedException Exception to log +	 */	 +	protected void logExceptionToTechnicalLog(final Throwable loggedException) { +		if (!( loggedException instanceof EAAFException  +				 || loggedException instanceof ProcessExecutionException )) { +			log.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); +	 +		} else { +			if (log.isDebugEnabled() || log.isTraceEnabled()) { +				log.warn(loggedException.getMessage(), loggedException); +	 +			} else { +				log.warn(loggedException.getMessage()); +	 +			}			 +		}		 +	} +	 +	private void writeBadRequestErrorResponse(final HttpServletRequest req, final HttpServletResponse resp, final EAAFException e) throws IOException { +		final String code = statusMessager.mapInternalErrorToExternalError(((InvalidProtocolRequestException)e).getErrorId()); +		final String descr = StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage())); +		resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); +		resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + +				"(Errorcode=" + code + +				" | Description=" + descr + ")"); +		 +	} +	 +	private void writeHTMLErrorResponse(final HttpServletRequest req, final HttpServletResponse httpResp, final String msg, final String errorCode, final Exception error) throws IOException, EAAFException { + +		try { +			final IGUIBuilderConfiguration config  +				= guiConfigFactory.getDefaultErrorGUI(HTTPUtils.extractAuthURLFromRequest(req)); + +//				HTTPUtils.extractAuthURLFromRequest(req),  +//					DefaultGUIFormBuilderConfiguration.VIEW_ERRORMESSAGE,  +//					null); +				 +			//add errorcode and errormessage +			if (config instanceof ModifyableGuiBuilderConfiguration) { +				((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorMsg", msg); +				((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorCode", errorCode); +				 +				//add stacktrace if debug is enabled +				if (log.isTraceEnabled()) { +					((ModifyableGuiBuilderConfiguration)config).putCustomParameter("stacktrace", getStacktraceFromException(error)); +				 +				} +				 +			} else  +				log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); +		 +			 +			 +			guiBuilder.build(httpResp, config, "Error-Message"); +			 +		} catch (final GUIBuildException e) { +			log.warn("Can not build error-message GUI.", e); +			throw new EAAFException("9199", null, e); + +			 +		} +		 +	} +	 +	private void writeHTMLErrorResponse(final HttpServletRequest req, final HttpServletResponse httpResp, final Exception error) throws IOException, EAAFException {				 +		writeHTMLErrorResponse(req, httpResp,  +				error.getMessage(),  +				statusMessager.getResponseErrorCode(error),  +				error);		 +	} +	 +	 +	private String getStacktraceFromException(final Exception ex) { +		final StringWriter errors = new StringWriter(); +	    ex.printStackTrace(new PrintWriter(errors)); +	    return errors.toString(); +	     +	} +	 +	private void internalMOAIDExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog) throws IOException, EAAFException {				 +		if (e instanceof ProtocolNotActiveException) { +			resp.getWriter().write(e.getMessage()); +			resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); +			resp.sendError(HttpServletResponse.SC_FORBIDDEN,  +					StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); +		 +		} else if (e instanceof AuthnRequestValidatorException) { +			final AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; +			//log Error Message +			if (writeExceptionToStatisicLog) +				statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); +			 +			//write error message +			writeBadRequestErrorResponse(req, resp, (EAAFException) e);			 +		 +		} else if (e instanceof InvalidProtocolRequestException) {		 +			//send error response +			writeBadRequestErrorResponse(req, resp, (EAAFException) e); +			 +		} else if (e instanceof ConfigurationException) { +			//send HTML formated error message +			writeHTMLErrorResponse(req, resp, e); +		 +		} else if (e instanceof EAAFException) { +			//send HTML formated error message +			writeHTMLErrorResponse(req, resp, e); +					 +		} else if (e instanceof ProcessExecutionException) { +			//send HTML formated error message +			writeHTMLErrorResponse(req, resp, e); +					 +		} +		 +	} +	 +	 +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java deleted file mode 100644 index 2f1cc6b4..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java +++ /dev/null @@ -1,242 +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.core.impl.idp.controller; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -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.IStatusMessenger; -import at.gv.egiz.eaaf.core.api.idp.IAction; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IAuthenticationDataBuilder; -import at.gv.egiz.eaaf.core.api.idp.IModulInfo; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; -import at.gv.egiz.eaaf.core.api.idp.auth.ISSOManager; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFSSOException; - -/** - * @author tlenz - * - */ - -public abstract class AbstractAuthProtocolModulController extends AbstractController { -	private static final Logger log = LoggerFactory.getLogger(AbstractAuthProtocolModulController.class); -	 -	public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol";	 -	public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; -		 -	  -	@Autowired(required=true) private IAuthenticationManager authmanager;			 -	@Autowired(required=true) private IAuthenticationDataBuilder authDataBuilder; -	@Autowired(required=false) private ISSOManager ssoManager; -	 -	/** -	 * Initialize an authentication process for this protocol request -	 *  -	 * @param httpReq HttpServletRequest	 -	 * @param httpResp HttpServletResponse -	 * @param protocolRequest Authentication request which is actually in process -	 * @throws IOException  -	 */ -	protected void performAuthentication(HttpServletRequest req, HttpServletResponse resp,  -			IRequest pendingReq) throws IOException { -		try { -			if (pendingReq.isNeedAuthentication()) { -				//request needs authentication --> start authentication process ... -			 -				//load Parameters from OnlineApplicationConfiguration -				ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); -				 -				if (oaParam == null) -					throw new EAAFAuthenticationException( -							IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG,  -							new Object[] { pendingReq.getSPEntityId() }); -									 -				if (authmanager.doAuthentication(req, resp, pendingReq)) {					 -					//pending request is already authenticated --> protocol-specific postProcessing can start directly 					 -					finalizeAuthenticationProcess(req, resp, pendingReq); -					 -					//transaction is finished, log transaction finished event -					revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); -					 -				} -							 -			} else {			 -				executeProtocolSpecificAction(req, resp, pendingReq, null); -			 -			} -			 -		} catch (Exception e) { -			buildProtocolSpecificErrorResponse(e, req, resp, pendingReq);			 -			authmanager.performOnlyIDPLogOut(req, resp, pendingReq); -						 -		}		 -	} -	 -	 -	/** -	 * Finalize the requested protocol operation -	 *  -	 * @param httpReq HttpServletRequest	 -	 * @param httpResp HttpServletResponse -	 * @param protocolRequest Authentication request which is actually in process -	 * @param moaSession MOASession object, which is used to generate the protocol specific authentication information -	 * @throws Exception  -	 */ -	protected void finalizeAuthenticationProcess(HttpServletRequest req, HttpServletResponse resp,  -			IRequest pendingReq) throws Exception { -		 -		String newSSOSessionId = null; -		 -		//if Single Sign-On functionality is enabled for this request -		if (pendingReq.needSingleSignOnFunctionality()) { -			if (ssoManager != null) { -				newSSOSessionId = ssoManager.createNewSSOSessionCookie(req, resp, pendingReq); -				if (StringUtils.isEmpty(pendingReq.getInternalSSOSessionIdentifier())) -					ssoManager.createNewSSOSession(pendingReq, newSSOSessionId);	 -			 -			} else -				log.warn("SSO is requested but there is not SSO Session-Manager available"); -			 -		} -		 -		//build authenticationdata from session information and OA configuration -		IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq);	 -			 -		//execute the protocol-specific action -		SLOInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); -				 -		//Store OA specific SSO session information if an SSO cookie is set -		if (StringUtils.isNotEmpty(newSSOSessionId)) { 		 -			try { -				ssoManager.updateSSOSession(pendingReq, newSSOSessionId, sloInformation); -																 -			} catch (EAAFSSOException e) { -				log.warn("SSO Session information can not be stored  -> SSO is not enabled!");				 -				authmanager.performOnlyIDPLogOut(req, resp, pendingReq); -				 -			} -		 -		} else { -			//remove MOASession from database -			authmanager.performOnlyIDPLogOut(req, resp, pendingReq); -			 -		} -	 -		//Advanced statistic logging -		statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSSOSessionId)); -				 -	} -	 -	/** -	 * Executes the requested protocol action -	 *  -	 * @param httpReq HttpServletRequest	 -	 * @param httpResp HttpServletResponse -	 * @param protocolRequest Authentication request which is actually in process -	 * @param authData Service-provider specific authentication data -	 *  -	 * @return Return Single LogOut information or null if protocol supports no SSO -	 *  -	 * @throws Exception  -	 */ -	private SLOInformationInterface executeProtocolSpecificAction(HttpServletRequest httpReq, HttpServletResponse httpResp,  -			IRequest pendingReq, IAuthData authData) throws Exception { -		try { -		//	request needs no authentication --> start request processing -			Class<?> clazz = Class.forName(pendingReq.requestedAction()); -			if (clazz == null ||  -					!IAction.class.isAssignableFrom(clazz)) { -				log.error("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); -				throw new Exception("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); -				 -			} -			 -			IAction protocolAction = (IAction) applicationContext.getBean(clazz);			  -			return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); -			 -		} catch (ClassNotFoundException e) { -			log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); -			throw new Exception("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); -		} -		 -	} -		 -	protected void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req,  -			HttpServletResponse resp, IRequest protocolRequest) throws IOException { -		try { -			 -			Class<?> clazz = Class.forName(protocolRequest.requestedModule()); -			 -			if (clazz == null ||  -					!IModulInfo.class.isAssignableFrom(clazz)) { -				log.error("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); -				throw new Exception("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); -				 -			} -							 -			IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); -												 -			if (handlingModule.generateErrorMessage( -					throwable, req, resp, protocolRequest)) { -		 -				//log Error to technical log -				logExceptionToTechnicalLog(throwable); -				 -				//log Error Message -				statisticLogger.logErrorOperation(throwable, protocolRequest); -				 -				//write revision log entries -				revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, protocolRequest.getUniqueTransactionIdentifier()); -				 -				return; -				 -			} else { -				handleErrorNoRedirect(throwable, req, resp, true); -				 -			} -			 -		} catch (Throwable e) { -			handleErrorNoRedirect(throwable, req, resp, true); -			 -		} -		 -	} -	 -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java index e7f2fe62..4e58868b 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -27,14 +27,9 @@  package at.gv.egiz.eaaf.core.impl.idp.controller;  import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.naming.ConfigurationException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils;  import org.apache.commons.text.StringEscapeUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -44,26 +39,16 @@ import org.springframework.web.bind.annotation.ExceptionHandler;  import at.gv.egiz.components.eventlog.api.EventConstants;  import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  import at.gv.egiz.eaaf.core.api.data.EAAFConstants;  import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; -import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; -import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService;  import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger;  import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;  import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; -import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;  import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; -import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils;  import at.gv.egiz.eaaf.core.impl.utils.Random;  import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; @@ -76,30 +61,29 @@ public abstract class AbstractController {  	private static final Logger log = LoggerFactory.getLogger(AbstractController.class); +	@Autowired(required=true) protected IProtocolAuthenticationService protAuthService;	  	@Autowired(required=true) protected ApplicationContext applicationContext;	  	@Autowired(required=true) protected IConfiguration authConfig;  	@Autowired(required=true) protected ITransactionStorage transactionStorage; -	@Autowired(required=true) protected IRequestStorage requestStorage; -	@Autowired(required=true) protected IGUIFormBuilder guiBuilder; -	@Autowired(required=true) protected IGUIBuilderConfigurationFactory guiConfigFactory;  	@Autowired(required=true) protected IStatusMessenger statusMessager; -	 -	@Autowired protected IStatisticLogger statisticLogger; +  	@Autowired protected IRevisionLogger revisionsLogger; -	 -	 -	 -	 -	 +		  	@ExceptionHandler({EAAFException.class}) -	public void MOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws IOException {				 -		log.error(e.getMessage() , e); -		internalMOAIDExceptionHandler(req, resp, e, true); +	public void MOAIDExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp, final Exception e) throws IOException {				 +		try { +			protAuthService.handleErrorNoRedirect(e, req, resp, true); +			 +		} catch (final EAAFException e1) { +			log.warn("Can NOT handle an 'EAAFException'. Forwarding to generic error ... ", e); +			IOExceptionHandler(resp, e); +			 +		}  	}  	@ExceptionHandler({Exception.class}) -	public void GenericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { +	public void GenericExceptionHandler(final HttpServletResponse resp, final Exception exception) throws IOException {  		log.error("Internel Server Error." , exception);  		resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8);		  		resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + @@ -112,7 +96,7 @@ public abstract class AbstractController {  	}  	@ExceptionHandler({IOException.class}) -	public void IOExceptionHandler(HttpServletResponse resp, Throwable exception) { +	public void IOExceptionHandler(final HttpServletResponse resp, final Throwable exception) {  		log.error("Internel Server Error." , exception);  		resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8);  		resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); @@ -120,15 +104,11 @@ public abstract class AbstractController {  	} -	protected void handleError(String errorMessage, Throwable exceptionThrown, -			HttpServletRequest req, HttpServletResponse resp, IRequest pendingReq) throws IOException { - -		String pendingRequestID = null; -		if (pendingReq != null) -			pendingRequestID = pendingReq.getPendingRequestId(); +	protected void handleError(final String errorMessage, final Throwable exceptionThrown, +			final HttpServletRequest req, final HttpServletResponse resp, final IRequest pendingReq) throws IOException, EAAFException {  		Throwable loggedException = null; -		Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown); +		final Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown);  		//extract pendingRequestID and originalException if it was a TaskExecutionException  		if (extractedException instanceof TaskExecutionException) { @@ -138,12 +118,7 @@ public abstract class AbstractController {  			//use TaskExecutionException directly, if no Original Exeception is included  			if (loggedException == null)  				loggedException = exceptionThrown; -			 -			//set pending-request ID if it is set -			String reqID = ((TaskExecutionException) extractedException).getPendingRequestID(); -			if (StringUtils.isNotEmpty(reqID)) -				pendingRequestID = reqID;  -						 +									  		} else  			loggedException = exceptionThrown; @@ -156,7 +131,7 @@ public abstract class AbstractController {  			//put exception into transaction store for redirect -			String key = Random.nextLongRandom(); +			final String key = Random.nextLongRandom();  			if (pendingReq != null) {  				revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR);  				transactionStorage.put(key,  @@ -171,13 +146,9 @@ public abstract class AbstractController {  			//build up redirect URL  			String redirectURL = null;  			redirectURL = ServletUtils.getBaseUrl(req);	 -			redirectURL += "/"+AbstractAuthProtocolModulController.ENDPOINT_ERRORHANDLING  +			redirectURL += "/"+ProtocolFinalizationController.ENDPOINT_ERRORHANDLING   					+ "?" + EAAFConstants.PARAM_HTTP_ERROR_CODE + "=" + key; -									 -//			//only add pending-request Id if it exists  -//			if (StringUtils.isNotEmpty(pendingRequestID))							 -//				redirectURL += "&" + EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; - +								  			resp.setContentType("text/html");  			resp.setStatus(302); @@ -186,128 +157,18 @@ public abstract class AbstractController {  			return; -		} catch (Exception e) { +		} catch (final Exception e) {  			log.warn("Default error-handling FAILED. Exception can not be stored ....", e);  			log.info("Switch to generic generic backup error-handling ... "); -			handleErrorNoRedirect(loggedException, req, resp, true); +			protAuthService.handleErrorNoRedirect(loggedException, req, resp, true);  		}  	} -	/** -	 * Handles all exceptions with no pending request. -	 * Therefore, the error is written to the users browser -	 *  -	 * @param throwable -	 * @param req -	 * @param resp -	 * @throws IOException  -	 */ -	protected void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req,  -			HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException { -		 -		//log Exception into statistic database -		if (writeExceptionToStatisticLog) -			statisticLogger.logErrorOperation(throwable); -		 -		//write errror to console -		logExceptionToTechnicalLog(throwable); -		 -		//return error to Web browser -		if (throwable instanceof EAAFException || throwable instanceof ProcessExecutionException) -			internalMOAIDExceptionHandler(req, resp, (Exception)throwable, false); -		 -		else { -			//write generic message for general exceptions -			String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null);			 -			writeHTMLErrorResponse(req, resp, msg, "9199", (Exception) throwable); -			 -		} -			 -	} -	 -	/** -	 * Write a Exception to the MOA-ID-Auth internal technical log -	 *  -	 * @param loggedException Exception to log -	 */	 -	protected void logExceptionToTechnicalLog(Throwable loggedException) { -		if (!( loggedException instanceof EAAFException  -				 || loggedException instanceof ProcessExecutionException )) { -			log.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); -	 -		} else { -			if (log.isDebugEnabled() || log.isTraceEnabled()) { -				log.warn(loggedException.getMessage(), loggedException); -	 -			} else { -				log.warn(loggedException.getMessage()); -	 -			}			 -		}		 -	} -		 -	private void writeBadRequestErrorResponse(HttpServletRequest req, HttpServletResponse resp, EAAFException e) throws IOException { -		String code = statusMessager.mapInternalErrorToExternalError(((InvalidProtocolRequestException)e).getErrorId()); -		String descr = StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage())); -		resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); -		resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + -				"(Errorcode=" + code + -				" | Description=" + descr + ")"); -		 -	} -	 -	private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, String msg, String errorCode, Exception error) throws IOException { - -		try { -			IGUIBuilderConfiguration config  -				= guiConfigFactory.getDefaultErrorGUI(HTTPUtils.extractAuthURLFromRequest(req)); -//				HTTPUtils.extractAuthURLFromRequest(req),  -//					DefaultGUIFormBuilderConfiguration.VIEW_ERRORMESSAGE,  -//					null); -				 -			//add errorcode and errormessage -			if (config instanceof ModifyableGuiBuilderConfiguration) { -				((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorMsg", msg); -				((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorCode", errorCode); -				 -				//add stacktrace if debug is enabled -				if (log.isTraceEnabled()) { -					((ModifyableGuiBuilderConfiguration)config).putCustomParameter("stacktrace", getStacktraceFromException(error)); -				 -				} -				 -			} else  -				log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); -			 -			 -			guiBuilder.build(httpResp, config, "Error-Message"); -			 -		} catch (GUIBuildException e) { -			log.warn("Can not build error-message GUI.", e); -			GenericExceptionHandler(httpResp, e); -			 -		} -		 -	} -	 -	private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, Exception error) throws IOException {				 -		writeHTMLErrorResponse(req, httpResp,  -				error.getMessage(),  -				statusMessager.getResponseErrorCode(error),  -				error);		 -	} -	 -	private String getStacktraceFromException(Exception ex) { -		StringWriter errors = new StringWriter(); -	    ex.printStackTrace(new PrintWriter(errors)); -	    return errors.toString(); -	     -	}  	/**  	 * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. @@ -315,13 +176,13 @@ public abstract class AbstractController {  	 * @param exception   	 * @return Return the latest TaskExecutionExecption if exists, otherwise the latest ProcessExecutionException  	 */ -	private Throwable extractOriginalExceptionFromProcessException(Throwable exception) { +	private Throwable extractOriginalExceptionFromProcessException(final Throwable exception) {  		Throwable exholder = exception;  		TaskExecutionException taskExc = null;  		while(exholder != null   				&& exholder instanceof ProcessExecutionException) { -			ProcessExecutionException procExc = (ProcessExecutionException) exholder; +			final ProcessExecutionException procExc = (ProcessExecutionException) exholder;  			if (procExc.getCause() != null &&   					procExc.getCause() instanceof TaskExecutionException) {  				taskExc = (TaskExecutionException) procExc.getCause(); @@ -339,40 +200,6 @@ public abstract class AbstractController {  			return taskExc;  	} -	private void internalMOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e, boolean writeExceptionToStatisicLog) throws IOException {				 -		if (e instanceof ProtocolNotActiveException) { -			resp.getWriter().write(e.getMessage()); -			resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); -			resp.sendError(HttpServletResponse.SC_FORBIDDEN,  -					StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); -		 -		} else if (e instanceof AuthnRequestValidatorException) { -			AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; -			//log Error Message -			if (writeExceptionToStatisicLog) -				statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); -			 -			//write error message -			writeBadRequestErrorResponse(req, resp, (EAAFException) e);			 -		 -		} else if (e instanceof InvalidProtocolRequestException) {		 -			//send error response -			writeBadRequestErrorResponse(req, resp, (EAAFException) e); -			 -		} else if (e instanceof ConfigurationException) { -			//send HTML formated error message -			writeHTMLErrorResponse(req, resp, (EAAFException) e); -		 -		} else if (e instanceof EAAFException) { -			//send HTML formated error message -			writeHTMLErrorResponse(req, resp, e); -					 -		} else if (e instanceof ProcessExecutionException) { -			//send HTML formated error message -			writeHTMLErrorResponse(req, resp, e); -					 -		} -		 -	} +	  } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java index d6448c95..6afa4fee 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java @@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired;  import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  import at.gv.egiz.eaaf.core.api.data.EAAFConstants;  import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; @@ -53,9 +54,10 @@ import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils;  public abstract class AbstractProcessEngineSignalController extends AbstractController {  	private static final Logger log = LoggerFactory.getLogger(AbstractProcessEngineSignalController.class);	 -	@Autowired protected ProcessEngine processEngine; +	@Autowired(required=true) protected ProcessEngine processEngine; +	@Autowired(required=true) IRequestStorage requestStorage; -	protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException { +	protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException, EAAFException {  		String pendingRequestID = StringEscapeUtils.escapeHtml4(getPendingRequestId(req));  		IRequest pendingReq = null;  		try {	 diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java index e96ea138..b830e240 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java @@ -20,10 +20,6 @@   * 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.core.impl.idp.controller;  import java.io.IOException; @@ -34,16 +30,18 @@ import javax.servlet.http.HttpServletResponse;  import org.apache.commons.text.StringEscapeUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Controller;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import at.gv.egiz.components.eventlog.api.EventConstants;  import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  import at.gv.egiz.eaaf.core.api.data.EAAFConstants;  import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService;  import at.gv.egiz.eaaf.core.exceptions.EAAFException;  /** @@ -51,8 +49,12 @@ import at.gv.egiz.eaaf.core.exceptions.EAAFException;   *   */  @Controller -public class ProtocolFinalizationController extends AbstractAuthProtocolModulController { +public class ProtocolFinalizationController extends AbstractController {  	private static final Logger log = LoggerFactory.getLogger(ProtocolFinalizationController.class); +	public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol";	 +	public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; +	 +	@Autowired(required=true) IRequestStorage requestStorage;  	@RequestMapping(value = ENDPOINT_ERRORHANDLING, method = {RequestMethod.GET})  	public void errorHandling(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { @@ -72,7 +74,7 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon  					if (pendingReq != null) {													  						//build protocol-specific error message if possible -						buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); +						protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq);  						//remove active user-session  						transactionStorage.remove(pendingReq.getPendingRequestId()); @@ -80,11 +82,11 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon  						return;  					} else { -						handleErrorNoRedirect(throwable, req, resp, true); +						protAuthService.handleErrorNoRedirect(throwable, req, resp, true);  					}  				} else { -					handleErrorNoRedirect( +					protAuthService.handleErrorNoRedirect(  							new EAAFException(  									IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID,   									null), req, resp, false); @@ -93,7 +95,7 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon  			} catch (Throwable e) {  				log.error(e.getMessage(), e);				 -				handleErrorNoRedirect(e, req, resp, false); +				protAuthService.handleErrorNoRedirect(e, req, resp, false);  			} finally {  				//remove pending-request @@ -107,7 +109,7 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon  		} else {  			log.debug("Request contains NO ErrorId"); -			handleErrorNoRedirect( +			protAuthService.handleErrorNoRedirect(  					new EAAFException(  							IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID,   							null), req, resp, false); @@ -132,62 +134,14 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon  		if (pendingReq == null) {  			log.error("No PendingRequest with ID " + pendingRequestID + " found.!");		 -			handleErrorNoRedirect( +			protAuthService.handleErrorNoRedirect(  					new EAAFException(  							IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT,   							new Object[]{pendingRequestID,  							}), req, resp, false);							 -		} else { -			try { -				log.debug("Finalize PendingRequest with ID " + pendingRequestID); -							 -				//check if pending-request has 'abortedByUser' flag set -				if (pendingReq.isAbortedByUser()) { -					//send authentication aborted error to Service Provider -					buildProtocolSpecificErrorResponse( -							new EAAFAuthenticationException( -									IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP,  -									new Object[] {}),  -							req, resp, pendingReq); -					 -					//do not remove the full active SSO-Session  -					// in case of only one Service-Provider authentication request is aborted    -					if ( !pendingReq.needSingleSignOnFunctionality())  { -						transactionStorage.remove(pendingReq.getPendingRequestId()); -						 -					}							 - -					//check if pending-request are authenticated					 -				} else if (pendingReq.isAuthenticated()) {				 -					finalizeAuthenticationProcess(req, resp, pendingReq); - -				} else { -					//suspect state: pending-request is not aborted but also are not authenticated  -					log.error("PendingRequest is NOT authenticated --> Abort authentication process!");		 -					handleErrorNoRedirect( -							new EAAFException( -									"auth.20", -									null), req, resp, true);							 -									 -				} -							 -			} catch (Exception e) { -				log.error("Finalize authentication protocol FAILED." , e); -				buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); -				 -				if (pendingReq != null) -					transactionStorage.remove(pendingReq.getPendingRequestId()); -				 -			}		 -		} -		 -		//remove pending-request -		if (pendingReq != null) { -			requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); -			revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); -			 -		} +		} else +			protAuthService.finalizeAuthentication(req, resp, pendingReq);  	} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java index 0370c14d..eff6b631 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java @@ -26,15 +26,20 @@   *******************************************************************************/  package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; +import java.io.Serializable; +  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cglib.proxy.Dispatcher;  import org.springframework.stereotype.Component;  import at.gv.egiz.eaaf.core.api.data.EAAFConstants;  import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; +import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.exceptions.EAAFException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; @@ -47,7 +52,9 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;  @Component("FinalizeAuthenticationTask")  public class FinalizeAuthenticationTask extends AbstractAuthServletTask { -		private static final Logger log = LoggerFactory.getLogger(FinalizeAuthenticationTask.class); +	private static final Logger log = LoggerFactory.getLogger(FinalizeAuthenticationTask.class); +	 +	@Autowired(required=true) IProtocolAuthenticationService protAuchService;  	/* (non-Javadoc)  	 * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @@ -60,13 +67,22 @@ public class FinalizeAuthenticationTask extends AbstractAuthServletTask {  		try {							  			//set pending request to authenticated   			pendingReq.setAuthenticated(true); -			requestStoreage.storePendingRequest(pendingReq); -		 -			log.info("AuthProcess finished. Redirect to Protocol Dispatcher.");			 -			performRedirectToProtocolFinialization(pendingReq, response); -  			revisionsLogger.logEvent(pendingReq, IAuthenticationManager.EVENT_AUTHENTICATION_PROCESS_FINISHED); +			 +			Object frontChannelRedirectFlagObj = executionContext.get(EAAFConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT); +			if (frontChannelRedirectFlagObj != null && frontChannelRedirectFlagObj instanceof Boolean && +					(Boolean)frontChannelRedirectFlagObj) { +				log.info("AuthProcess finished. Forward to Protocol finalization."); +				protAuchService.finalizeAuthentication(request, response, pendingReq); +				 +			} else {			 +				log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); +				requestStoreage.storePendingRequest(pendingReq); +				performRedirectToProtocolFinialization(pendingReq, response); +				 +			} +						  		} catch (EAAFException e) {			  			throw new TaskExecutionException(pendingReq, e.getMessage(), e); | 
