diff options
Diffstat (limited to 'id/server')
24 files changed, 1677 insertions, 91 deletions
| diff --git a/id/server/auth/src/main/webapp/WEB-INF/applicationContext.xml b/id/server/auth/src/main/webapp/WEB-INF/applicationContext.xml index a4a06d24a..563fd6ec7 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/applicationContext.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/applicationContext.xml @@ -11,7 +11,7 @@  	<bean id="processEngine" class="com.datentechnik.process_engine.ProcessEngineImpl">
  		<property name="transitionConditionExpressionEvaluator">
 -			<bean class="com.datentechnik.process_engine.spring.SpringExpressionEvaluator" />
 +			<bean class="com.datentechnik.process_engine.springweb.SpringWebExpressionEvaluator" />
  		</property>
  		<property name="processInstanceMaxIdleTimeSeconds" value="600" />
  		<property name="processDefinitions">
 diff --git a/id/server/auth/src/main/webapp/WEB-INF/web.xml b/id/server/auth/src/main/webapp/WEB-INF/web.xml index 4548e05d9..2dbceb4e9 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/web.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/web.xml @@ -120,28 +120,6 @@  	</servlet-mapping>  	<servlet> -		<description>Servlet receiving STORK SAML Response Messages from different C-PEPS</description> -		<display-name>PEPSConnectorServlet</display-name> -		<servlet-name>PEPSConnectorServlet</servlet-name> -		<servlet-class>at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet</servlet-class> -	</servlet> -	<servlet-mapping> -		<servlet-name>PEPSConnectorServlet</servlet-name> -		<url-pattern>/PEPSConnector</url-pattern> -	</servlet-mapping> - -	<servlet> -		<description>Servlet receiving STORK SAML Response Messages from different C-PEPS</description> -		<display-name>PEPSConnectorWithLocalSigningServlet</display-name> -		<servlet-name>PEPSConnectorWithLocalSigningServlet</servlet-name> -		<servlet-class>at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet</servlet-class> -	</servlet> -	<servlet-mapping> -		<servlet-name>PEPSConnectorWithLocalSigningServlet</servlet-name> -		<url-pattern>/PEPSConnectorWithLocalSigning</url-pattern> -	</servlet-mapping> -	 -	<servlet>  		<display-name>Dispatcher Servlet</display-name>  		<servlet-name>DispatcherServlet</servlet-name>  		<servlet-class>at.gv.egovernment.moa.id.entrypoints.DispatcherServlet</servlet-class> @@ -165,6 +143,8 @@  		<url-pattern>/VerifyAuthBlock</url-pattern>  		<url-pattern>/VerifyCertificate</url-pattern>  		<url-pattern>/VerifyIdentityLink</url-pattern> +		<url-pattern>/PEPSConnectorWithLocalSigning</url-pattern> +		<url-pattern>/PEPSConnector</url-pattern>  	</servlet-mapping>  	<session-config> diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java index c33e5c735..cf50a1bf5 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java @@ -1402,8 +1402,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 * Retrieves a session from the session store.  	 *  	 * @param id session ID -	 * @return <code>AuthenticationSession</code> stored with given session ID, -	 * <code>null</code> if session ID unknown +	 * @return <code>AuthenticationSession</code> stored with given session ID (never {@code null}). +	 * @throws AuthenticationException in case the session id does not reflect a valic, active session.  	 */  	public static AuthenticationSession getSession(String id)  			throws AuthenticationException { @@ -1707,10 +1707,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		//        String acsURL = new DataURLBuilder().buildDataURL(issuerValue,   		//    			PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN, moasession.getSessionID()); -		//solve Problem with sessionIDs  -		String acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; - -		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		String providerName = oaParam.getFriendlyName();  		Logger.debug("Issuer value: " + issuerValue); @@ -1744,8 +1740,12 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		List<String> value = new ArrayList<String>();  		Logger.debug("PEPS supports XMLSignatures:"+cpeps.isXMLSignatureSupported()); +		String acsURL;  		if(cpeps.isXMLSignatureSupported())//Send SignRequest to PEPS  		{ +			//solve Problem with sessionIDs  +			acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +			  			value.add(generateDssSignRequest(CreateXMLSignatureRequestBuilder.buildForeignIDTextToBeSigned("wie im  Signaturzertifikat (as in my signature certificate)", oaParam, moasession),  					"application/xhtml+xml", moasession.getCcc()));  			newAttribute.setValue(value); @@ -1776,6 +1776,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			}  		} +		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		if (Logger.isDebugEnabled()) {  			Logger.debug("The following attributes are requested for this OA:"); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java index a92d3f678..9a8372a2d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java @@ -52,10 +52,9 @@ public class StartAuthenticationBuilder {  	 * <ul>  	 * <li><strong>Either</strong> creates an "IdentityLinkForm" with embedded {@code InfoBoxReadRequest} to be submitted to a citizen card  	 * environment for reading the subject's IdentityLink</li> -	 * <li><strong>or</strong> creates a STORK auth request and redirects to a CPEPS.</li>  	 * </ul>  	 *  -	 * @return The "IdentityLinkForm" or an empty String in case of STORK. +	 * @return The IdentityLinkForm.  	 */  	public String build(AuthenticationSession moasession, HttpServletRequest req,  			HttpServletResponse resp) throws WrongParametersException, MOAIDException { @@ -64,26 +63,11 @@ public class StartAuthenticationBuilder {  			throw new AuthenticationException("auth.18", new Object[] { });  		} -	    STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig(); -	     -	    Logger.info("Starting authentication for a citizen of country: " + (StringUtils.isEmpty(moasession.getCcc()) ? "AT" : moasession.getCcc())); -	    // STORK or normal authentication -	    // TODO[branch]: STORK -	    if (storkConfig.isSTORKAuthentication(moasession.getCcc())) { -	    	//STORK authentication -	    	Logger.trace("Found C-PEPS configuration for citizen of country: " + moasession.getCcc()); -	    	Logger.debug("Starting STORK authentication"); -	    	 -	    	AuthenticationServer.startSTORKAuthentication(req, resp, moasession); -	    	return ""; -	    	 -	    } else { -	    	//normal MOA-ID authentication -	    	Logger.debug("Starting normal MOA-ID authentication"); -		    			    	    	 -	    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    +    	//normal MOA-ID authentication +    	Logger.debug("Starting normal MOA-ID authentication"); +	    			    	    	 +    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    -	    	return getIdentityLinkForm; -	    } +    	return getIdentityLinkForm;  	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java index 4cd192070..02e1cb12d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java @@ -97,6 +97,7 @@ import javax.xml.ws.BindingProvider;  /**
   * Endpoint for receiving STORK response messages
 + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.tasks.stork.PepsConnectorTask} instead.
   */
  public class PEPSConnectorServlet extends AuthServlet {
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java index 165445ea5..fa80bdab9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java @@ -109,6 +109,7 @@ import eu.stork.peps.exceptions.STORKSAMLEngineException;  /**   * Endpoint for receiving STORK response messages + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.tasks.stork.PepsConnectorHandleResponseWithoutSignatureTask} instead.   */  public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  	private static final long serialVersionUID = 1L; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java index 849ccf5db..01f8e8949 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java @@ -50,7 +50,7 @@ public class ProcessEngineSignalServlet extends AuthServlet {  	/**
  	 * Resumes the current process instance that has been suspended due to an asynchronous task. The process instance is
 -	 * retrieved from the MOA session referred to by the request parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}.
 +	 * retrieved from the MOA session referred to by the request parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.
  	 */
  	@Override
  	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/AbstractAuthServletTask.java index 7351933c1..9a5c2baee 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/AbstractAuthServletTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/AbstractAuthServletTask.java @@ -43,9 +43,6 @@ import com.datentechnik.process_engine.springweb.AbstractSpringWebSupportedTask;  /**
   * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing
   * etc.).</p> The code has been taken from {@link AuthServlet}.
 - * 
 - * @author tknall
 - * 
   */
  public abstract class AbstractAuthServletTask extends AbstractSpringWebSupportedTask {
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CertificateReadRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CertificateReadRequestTask.java index da8a3d997..8cd0db679 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CertificateReadRequestTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CertificateReadRequestTask.java @@ -29,18 +29,17 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * <ul>
   * <li>Renames the moa session id.</li>
   * <li>Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.</li>
 - * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code {/VerifyCertificate}</li>
 + * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
   * </ul>
   * Result:
   * <ul>
   * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code {/VerifyCertificate}</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 @@ -71,9 +70,9 @@ public class CertificateReadRequestTask extends AbstractAuthServletTask {  			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
  			boolean useMandate = session.getUseMandate();
 -			boolean identityLinkFound = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkFound"));
 +			boolean identityLinkAvailable = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkAvailable"));
 -			if (!identityLinkFound && useMandate) {
 +			if (!identityLinkAvailable && useMandate) {
  				Logger.error("Online-Mandate Mode for foreign citizencs not supported.");
  				throw new AuthenticationException("auth.13", null);
  			}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CreateIdentityLinkFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CreateIdentityLinkFormTask.java index 70afd477d..ff55eedeb 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CreateIdentityLinkFormTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/CreateIdentityLinkFormTask.java @@ -30,14 +30,14 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * In detail:
   * <ul>
   * <li>Renames the moa session id.</li>
 - * <li>Removes ExecutionContext property {@link MOAIDAuthConstants#PARAM_SESSIONID}.</li>
 + * <li>Removes ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.</li>
   * <li>Creates the http form mentioned above.</li>
   * <li>Returns the http form via HttpServletResponse.</li>
   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID} <strong>or</strong></li>
 - * <li>ExecutionContext property {@link MOAIDAuthConstants#PARAM_SESSIONID} (in case of legacy authentication without CCE selection, where the moa session is not provided by request parameter).</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} <strong>or</strong></li>
 + * <li>ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} (in case of legacy authentication without CCE selection, where the moa session is not provided by request parameter).</li>
   * </ul>
   * Result:
   * <ul>
 @@ -54,7 +54,6 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * </li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetForeignIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetForeignIDTask.java index 602ad527b..2ce6a1ae8 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetForeignIDTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetForeignIDTask.java @@ -42,7 +42,7 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * In detail:
   * <ul>
   * <li>Renames the moa session id.</li>
 - * <li>Parses the CreateXMLSignatureResponse retrieved from POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}.</li>
 + * <li>Parses the CreateXMLSignatureResponse retrieved from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
   * <li>Extracts signature and signer certificate.</li>
   * <li>Send request to SZR Gateway in order to get an identity link.</li>
   * <li>Updates moa session (sets identity link, QAA level 4, authentication data and foreigner flag).</li>
 @@ -50,8 +50,8 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
   * </ul>
   * Result:
   * <ul>
 @@ -59,7 +59,6 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * <li>Redirect to {@code /dispatcher}.</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetForeignIDServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetMISSessionIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetMISSessionIDTask.java index 40e33ae43..a7ee086af 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetMISSessionIDTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/GetMISSessionIDTask.java @@ -47,7 +47,7 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
   * </ul>
   * Result:
   * <ul>
 @@ -55,7 +55,6 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * <li>Redirect to {@code /dispatcher}.</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetMISSessionIDServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/PrepareAuthBlockSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/PrepareAuthBlockSignatureTask.java index 30777198c..566616fcd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/PrepareAuthBlockSignatureTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/PrepareAuthBlockSignatureTask.java @@ -31,14 +31,13 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
   * </ul>
   * Result:
   * <ul>
   * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code {/VerifyAuthBlock}</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyAuthenticationBlockTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyAuthenticationBlockTask.java index 2bc0bb8ad..956ec9c88 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyAuthenticationBlockTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyAuthenticationBlockTask.java @@ -45,15 +45,15 @@ import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;   * In detail:
   * <ul>
   * <li>Renames the moa session id.</li>
 - * <li>Takes the {@code CreateXMLSignatureResponse} from POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}.</li>
 + * <li>Takes the {@code CreateXMLSignatureResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
   * <li>Verifies the {@code CreateXMLSignatureResponse}.</li>
   * <li>Updates moa session.</li>
   * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
   * </ul>
   * Result:
   * <ul>
 @@ -70,7 +70,6 @@ import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;   * </li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyCertificateTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyCertificateTask.java index ddea4c414..854c78161 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyCertificateTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyCertificateTask.java @@ -29,11 +29,11 @@ import at.gv.egovernment.moa.spss.util.CertificateUtils;  import com.datentechnik.process_engine.api.ExecutionContext;
  /**
 - * Parses the certificate from {@code InfoBoxReadResponse} (via POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}), creates the auth block to be signed and returns a {@code CreateXMLSignatureRequest} for auth block signature.<p/>
 + * Parses the certificate from {@code InfoBoxReadResponse} (via POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}), creates the auth block to be signed and returns a {@code CreateXMLSignatureRequest} for auth block signature.<p/>
   * In detail:
   * <ul>
   * <li>Renames the moa session id.</li>
 - * <li>Retrieves the certificate via {@code InfoBoxReadResponse} from POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}.</li>
 + * <li>Retrieves the certificate via {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
   * <li>Verifies the certificate.</li>
   * <li>Creates the auth block to be signed using information from the certificate (Organwalter, foreign citizen.</li>
   * <li>Puts it in a {@code CreateXMLSignatureRequest}.</li>
 @@ -42,15 +42,14 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_SESSIONID} containing a {@code InfoBoxReadResponse}.</li>
   * </ul>
   * Result:
   * <ul>
   * <li>{@code CreateXMLSignatureRequest} send as HttpServletResponse (for CCE).</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyIdentityLinkTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyIdentityLinkTask.java index 5b21cd29c..eb884e9db 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyIdentityLinkTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/VerifyIdentityLinkTask.java @@ -28,23 +28,22 @@ import com.datentechnik.process_engine.api.ExecutionContext;   * In detail:
   * <ul>
   * <li>Renames the moa session id.</li>
 - * <li>Parses the identity link retrieved as {@code InfoBoxReadResponse} from POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}.</li>
 + * <li>Parses the identity link retrieved as {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
   * <li>Verifies the identity link.</li>
   * <li>Updates moa session.</li>
 - * <li>Puts boolean flag {@code identityLinkFound} into {@code ExecutionContext}.</li>
 + * <li>Puts boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
   * </ul>
   * Expects:
   * <ul>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}</li>
 - * <li>HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
   * </ul>
   * Result:
   * <ul>
   * <li>Identity link put into moa session.</li>
 - * <li>Boolean flag {@code identityLinkFound} into {@code ExecutionContext}.</li>
 + * <li>Boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
   * </ul>
   * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 - * @author tknall
   * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
   *
   */
 @@ -81,10 +80,10 @@ public class VerifyIdentityLinkTask extends AbstractAuthServletTask {  			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 -			boolean identityLinkFound = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
 +			boolean identityLinkAvailable = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
  			AuthenticationSessionStoreage.storeSession(session);
 -			executionContext.put("identityLinkFound", identityLinkFound);
 +			executionContext.put("identityLinkAvailable", identityLinkAvailable);
  		} catch (ParseException ex) {
  			handleError(null, ex, req, resp, pendingRequestID);
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/AbstractPepsConnectorWithLocalSigningTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/AbstractPepsConnectorWithLocalSigningTask.java new file mode 100644 index 000000000..eff7fe43f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/AbstractPepsConnectorWithLocalSigningTask.java @@ -0,0 +1,258 @@ +package at.gv.egovernment.moa.id.auth.tasks.stork;
 +
 +import at.gv.egovernment.moa.id.auth.tasks.AbstractAuthServletTask;
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.io.StringWriter;
 +import java.io.UnsupportedEncodingException;
 +import java.security.cert.CertificateException;
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.List;
 +
 +import javax.activation.DataSource;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.bind.JAXBContext;
 +import javax.xml.bind.JAXBElement;
 +import javax.xml.bind.JAXBException;
 +import javax.xml.parsers.ParserConfigurationException;
 +import javax.xml.transform.Source;
 +import javax.xml.transform.TransformerConfigurationException;
 +import javax.xml.transform.TransformerException;
 +import javax.xml.transform.TransformerFactoryConfigurationError;
 +import javax.xml.transform.stream.StreamSource;
 +
 +import org.apache.commons.codec.binary.Base64;
 +import org.apache.commons.io.IOUtils;
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.velocity.Template;
 +import org.apache.velocity.VelocityContext;
 +import org.apache.velocity.app.VelocityEngine;
 +import org.opensaml.saml2.core.StatusCode;
 +import org.xml.sax.SAXException;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.BKUException;
 +import at.gv.egovernment.moa.id.auth.exception.BuildException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.ParseException;
 +import at.gv.egovernment.moa.id.auth.exception.ServiceException;
 +import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet;
 +import at.gv.egovernment.moa.id.auth.stork.STORKException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
 +import at.gv.egovernment.moa.id.auth.tasks.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin;
 +import at.gv.egovernment.moa.id.config.ConfigurationException;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.HTTPUtils;
 +import at.gv.egovernment.moa.id.util.VelocityProvider;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.spss.MOAException;
 +import at.gv.egovernment.moa.spss.api.SPSSFactory;
 +import at.gv.egovernment.moa.spss.api.SignatureVerificationService;
 +import at.gv.egovernment.moa.spss.api.common.Content;
 +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo;
 +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation;
 +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest;
 +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
 +import at.gv.egovernment.moa.util.StringUtils;
 +import at.gv.util.xsd.xmldsig.SignatureType;
 +import at.gv.util.xsd.xmldsig.X509DataType;
 +
 +import com.datentechnik.process_engine.api.ExecutionContext;
 +
 +import eu.stork.oasisdss.api.ApiUtils;
 +import eu.stork.oasisdss.api.LightweightSourceResolver;
 +import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
 +import eu.stork.oasisdss.api.exceptions.UtilsException;
 +import eu.stork.oasisdss.profile.SignRequest;
 +import eu.stork.oasisdss.profile.SignResponse;
 +import eu.stork.peps.auth.commons.IPersonalAttributeList;
 +import eu.stork.peps.auth.commons.PEPSUtil;
 +import eu.stork.peps.auth.commons.PersonalAttribute;
 +import eu.stork.peps.auth.commons.STORKAuthnRequest;
 +import eu.stork.peps.auth.commons.STORKAuthnResponse;
 +import eu.stork.peps.auth.engine.STORKSAMLEngine;
 +import eu.stork.peps.exceptions.STORKSAMLEngineException;
 +
 +public abstract class AbstractPepsConnectorWithLocalSigningTask extends AbstractAuthServletTask {
 +
 +	String getCitizienSignatureFromSignResponse(SignResponse dssSignResponse) throws IllegalArgumentException,
 +			TransformerConfigurationException, UtilsException, TransformerException,
 +			TransformerFactoryConfigurationError, IOException, ApiUtilsException {
 +		// fetch signed doc
 +		DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse);
 +		if (ds == null) {
 +			throw new ApiUtilsException("No datasource found in response");
 +		}
 +
 +		InputStream incoming = ds.getInputStream();
 +		String citizenSignature = IOUtils.toString(incoming);
 +		incoming.close();
 +
 +		return citizenSignature;
 +	}
 +
 +	void SZRGInsertion(AuthenticationSession moaSession, IPersonalAttributeList personalAttributeList,
 +			String authnContextClassRef, String citizenSignature) throws STORKException, MOAIDException {
 +		Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
 +		Logger.debug("Citizen signature will be verified by SZR Gateway!");
 +
 +		Logger.debug("fetching OAParameters from database");
 +
 +		OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
 +				moaSession.getPublicOAURLPrefix());
 +		if (oaParam == null)
 +			throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() });
 +
 +		// retrieve target
 +		// TODO: check in case of SSO!!!
 +		String targetType = null;
 +		if (oaParam.getBusinessService()) {
 +			String id = oaParam.getIdentityLinkDomainIdentifier();
 +			if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
 +				targetType = id;
 +			else
 +				targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_ + moaSession.getDomainIdentifier();
 +		} else {
 +			targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
 +		}
 +
 +		Logger.debug("Starting connecting SZR Gateway");
 +		// contact SZR Gateway
 +		IdentityLink identityLink = null;
 +
 +		identityLink = STORKResponseProcessor.connectToSZRGateway(personalAttributeList, oaParam.getFriendlyName(),
 +				targetType, null, oaParam.getMandateProfiles(), citizenSignature);
 +		Logger.debug("SZR communication was successfull");
 +
 +		if (identityLink == null) {
 +			Logger.error("SZR Gateway did not return an identity link.");
 +			throw new MOAIDException("stork.10", null);
 +		}
 +		Logger.info("Received Identity Link from SZR Gateway");
 +		moaSession.setIdentityLink(identityLink);
 +
 +		Logger.debug("Adding addtional STORK attributes to MOA session");
 +		moaSession.setStorkAttributes(personalAttributeList);
 +
 +		// We don't have BKUURL, setting from null to "Not applicable"
 +		moaSession.setBkuURL("Not applicable (STORK Authentication)");
 +
 +		// free for single use
 +		moaSession.setAuthenticatedUsed(false);
 +
 +		// stork did the authentication step
 +		moaSession.setAuthenticated(true);
 +
 +		// TODO: found better solution, but QAA Level in response could be not supported yet
 +		try {
 +			if (authnContextClassRef == null)
 +				authnContextClassRef = PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel();
 +			moaSession.setQAALevel(authnContextClassRef);
 +
 +		} catch (Throwable e) {
 +			Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
 +			moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel());
 +
 +		}
 +
 +	}
 +
 +	X509Certificate getSignerCertificate(String citizenSignature) throws CertificateException, JAXBException,
 +			UnsupportedEncodingException {
 +		JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName());
 +		SignatureType root = ((JAXBElement<SignatureType>) ctx.createUnmarshaller().unmarshal(
 +				IOUtils.toInputStream(citizenSignature))).getValue();
 +
 +		// extract certificate
 +		for (Object current : root.getKeyInfo().getContent())
 +			if (((JAXBElement<?>) current).getValue() instanceof X509DataType) {
 +				for (Object currentX509Data : ((JAXBElement<X509DataType>) current).getValue()
 +						.getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
 +					JAXBElement<?> casted = ((JAXBElement<?>) currentX509Data);
 +					if (casted.getName().getLocalPart().equals("X509Certificate")) {
 +						return new X509Certificate(((String) casted.getValue()).getBytes("UTF-8"));
 +					}
 +				}
 +			}
 +		return null;
 +	}
 +
 +	VerifyXMLSignatureResponse verifyXMLSignature(String signature) throws AuthenticationException, ParseException,
 +			BKUException, BuildException, ConfigurationException, ServiceException, UnsupportedEncodingException,
 +			SAXException, IOException, ParserConfigurationException, MOAException {
 +		// Based on MOA demo client
 +		// Factory und Service instanzieren
 +		SPSSFactory spssFac = SPSSFactory.getInstance();
 +		SignatureVerificationService sigVerifyService = SignatureVerificationService.getInstance();
 +
 +		Content sigDocContent1 = spssFac.createContent(IOUtils.toInputStream(signature, "UTF-8"), null);
 +
 +		// Position der zu prüfenden Signatur im Dokument angeben
 +		// (Nachdem im XPath-Ausdruck ein NS-Präfix verwendet wird, muss in einer Lookup-Tabelle
 +		// der damit bezeichnete Namenraum mitgegeben werden)
 +		HashMap nSMap = new HashMap();
 +		nSMap.put("dsig", "http://www.w3.org/2000/09/xmldsig#");
 +		VerifySignatureLocation sigLocation = spssFac.createVerifySignatureLocation("//dsig:Signature", nSMap);
 +
 +		// Zu prüfendes Dokument und Signaturposition zusammenfassen
 +
 +		VerifySignatureInfo sigInfo = spssFac.createVerifySignatureInfo(sigDocContent1, sigLocation);
 +
 +		// Prüfrequest zusammenstellen
 +		VerifyXMLSignatureRequest verifyRequest = spssFac.createVerifyXMLSignatureRequest(null, // Wird Prüfzeit nicht
 +																								// angegeben, wird
 +																								// aktuelle Zeit
 +																								// verwendet
 +				sigInfo, null, // Keine Ergänzungsobjekte notwendig
 +				null, // Signaturmanifest-Prüfung soll nicht durchgeführt werden
 +				false, // Hash-Inputdaten, d.h. tatsächlich signierte Daten werden nicht zurückgeliefert
 +				"MOAIDBuergerkartePersonenbindungMitTestkarten");// TODO load from config
 +		// "Test-Signaturdienste"); // ID des verwendeten Vertrauensprofils
 +
 +		VerifyXMLSignatureResponse verifyResponse = null;
 +		try {
 +			// Aufruf der Signaturprüfung
 +			verifyResponse = sigVerifyService.verifyXMLSignature(verifyRequest);
 +		} catch (MOAException e) {
 +			// Service liefert Fehler
 +			System.err.println("Die Signaturprüfung hat folgenden Fehler geliefert:");
 +			System.err.println("Fehlercode: " + e.getMessageId());
 +			System.err.println("Fehlernachricht: " + e.getMessage());
 +			throw e;
 +		}
 +
 +		return verifyResponse;
 +	}
 +
 +	at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse convert(
 +			VerifyXMLSignatureResponse xMLVerifySignatureResponse) {
 +		at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse response = new at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse();
 +		response.setCertificateCheckCode(xMLVerifySignatureResponse.getCertificateCheck().getCode());
 +		response.setPublicAuthority(xMLVerifySignatureResponse.getSignerInfo().isPublicAuthority());
 +		// response.setPublicAuthorityCode(publicAuthorityCode)
 +		response.setQualifiedCertificate(xMLVerifySignatureResponse.getSignerInfo().isQualifiedCertificate());
 +		response.setSignatureCheckCode(xMLVerifySignatureResponse.getSignatureCheck().getCode());
 +		response.setSignatureManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
 +		// response.setSigningDateTime()
 +		// response.setX509certificate(x509certificate)
 +		response.setXmlDSIGManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
 +		// response.setXmlDSIGManigest(xMLVerifySignatureResponse.getSignatureManifestCheck())
 +		// response.setXmlDsigSubjectName(xmlDsigSubjectName)
 +		return response;
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/CreateStorkAuthRequestFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/CreateStorkAuthRequestFormTask.java new file mode 100644 index 000000000..3894567ed --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/CreateStorkAuthRequestFormTask.java @@ -0,0 +1,114 @@ +package at.gv.egovernment.moa.id.auth.tasks.stork;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang3.StringUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
 +import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.tasks.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.stork.CPEPS;
 +import at.gv.egovernment.moa.id.config.stork.STORKConfig;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +import com.datentechnik.process_engine.api.ExecutionContext;
 +
 +/**
 + * Creates a SAML2 STORK authentication request, embeds it in a form (in order to satisfy saml post binging) and returns the form withing the HttpServletResponse.<p/>
 + * In detail:
 + * <ul>
 + * <li>Validates the stork configuration in order to make sure the selected country is supported.</li>
 + * <li>Puts a flag ({@link #PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED}) into the ExecutionContext reflecting the capability of the C-PEPS to create xml signatures.</li>
 + * <li>Invokes {@link AuthenticationServer#startSTORKAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationSession)} which</li>
 + * <ul>
 + * <li>Creates and signs a SAML2 stork authentication request.</li>
 + * <li>Creates a signature request for auth block signature (either to be performed by the C-PEPS or locally).</li>
 + * <li>Using the velocity template engine in order to create a form with the embedded stork request.</li>
 + * <li>Writes the form to the response output stream.</li>
 + * </ul>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>Property {@code ccc} set within the moa session.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Form containing a SAML2 Stork authentication request and an action url pointing to the selected C-PEPS.</li>
 + * <li>Assertion consumer URL for C-PEPS set either to {@code /PEPSConnector} in case of a C-PEPS supporting xml signatures or {@code /PEPSConnectorWithLocalSigning} if the selected C-PEPS does not support xml signatures.</li>
 + * <li>In case of a C-PEPS not supporting xml signature: moasession with set signedDoc property (containing the signature request for local signing).</li>
 + * <li>ExecutionContext contains the boolean flag {@link #PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED}.
 + * </ul>
 + * Code taken from {@link StartAuthenticationBuilder#build(AuthenticationSession, HttpServletRequest, HttpServletResponse)}.<br/>
 + * Using {@link AuthenticationServer#startSTORKAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationSession)}
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + */
 +public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask {
 +
 +	/**
 +	 * Boolean value reflecting the capability of the selected c-peps of creating xml signatures.
 +	 */
 +	public static final String PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED = "C-PEPS:XMLSignatureSupported";
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		String pendingRequestID = null;
 +		String sessionID = null;
 +		try {
 +			setNoCachingHeaders(resp);
 +
 +			sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("CreateStorkAuthRequestFormTask", PARAM_SESSIONID, "auth.12");
 +			}
 +			AuthenticationSession moasession = AuthenticationServer.getSession(sessionID);
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +
 +			if (StringUtils.isEmpty(moasession.getCcc())) {
 +				// illegal state; task should not have been executed without a selected country
 +				throw new AuthenticationException("stork.22", new Object[] { sessionID });
 +			}
 +			STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig();
 +			if (!storkConfig.isSTORKAuthentication(moasession.getCcc())) {
 +				throw new AuthenticationException("stork.23", new Object[] { moasession.getCcc(), sessionID });
 +			}
 +
 +			// STORK authentication
 +			// cpeps cannot be null
 +			CPEPS cpeps = storkConfig.getCPEPS(moasession.getCcc());
 +			Logger.debug("Found C-PEPS configuration for citizen of country: " + moasession.getCcc());
 +			executionContext.put(PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED, cpeps.isXMLSignatureSupported());
 +
 +			Logger.info("Starting STORK authentication for a citizen of country: " + moasession.getCcc());
 +			AuthenticationServer.startSTORKAuthentication(req, resp, moasession);
 +
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("CreateStorkAuthRequestFormTask has an interal Error.", e);
 +			throw new MOAIDException("Internal error.", new Object[] { sessionID }, e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleLocalSignResponseTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleLocalSignResponseTask.java new file mode 100644 index 000000000..738988ff7 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleLocalSignResponseTask.java @@ -0,0 +1,218 @@ +package at.gv.egovernment.moa.id.auth.tasks.stork;
 +
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.io.StringWriter;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.transform.Source;
 +import javax.xml.transform.stream.StreamSource;
 +
 +import org.apache.commons.codec.binary.Base64;
 +import org.apache.velocity.Template;
 +import org.apache.velocity.VelocityContext;
 +import org.apache.velocity.app.VelocityEngine;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.VelocityProvider;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
 +
 +import com.datentechnik.process_engine.api.ExecutionContext;
 +
 +import eu.stork.oasisdss.api.ApiUtils;
 +import eu.stork.oasisdss.profile.SignResponse;
 +import eu.stork.peps.auth.commons.IPersonalAttributeList;
 +import eu.stork.peps.auth.commons.PersonalAttribute;
 +
 +/**
 + * Processes the citizen's signature, creates identity link using szr gateway and finalizes authentication.
 + * <p/>
 + * In detail:
 + * <ul>
 + * <li>Changes moa session id.</li>
 + * <li>Decodes and validates the sign response, extracting the citizen's signature.</li>
 + * <li>Verifies the citizen's signature.</li>
 + * <li>Create {@code signedDoc} attribute.</li>
 + * <li>Retrieve identity link from SZR gateway using the citizen's signature.</li>
 + * <li>If the S-PEPS did not provide any gender information, the szr gateway will not be able to issue an identity link.
 + * Therefore a form is presented asking for the subject's gender. The form finally submits the user back to the
 + * {@code /PepsConnectorWithLocalSigning} servlet (this task).</li>
 + * <li>The moa session is updated with authentication information.</li>
 + * <li>Change moa session id.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@code moaSessionID}</li>
 + * <li>HttpServletRequest parameter {@code signresponse}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Updated moa id session (signed auth block, signer certificate etc.)</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * <li>{@link ExecutionContext} contains boolean flag {@code identityLinkAvailable} indicating if an identitylink has been successfully creates or not.</li>
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case the szr gateway throws exception due to missing gender information:
 + * <ul>
 + * <li>Returns a form for gender selection with action url back to this servlet/task.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet}.<br/>
 + *
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + */
 +public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnectorWithLocalSigningTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
 +			throws Exception {
 +		String moaSessionID = request.getParameter("moaSessionID");
 +		String signResponse = request.getParameter("signresponse");
 +		Logger.info("moaSessionID:" + moaSessionID);
 +		Logger.info("signResponse:" + signResponse);
 +
 +		if (moaSessionID != null && signResponse != null) {
 +			// redirect from oasis with signresponse
 +			handleSignResponse(executionContext, request, response);
 +		} else {
 +			// should not occur
 +			throw new IOException("should not occur");
 +		}
 +		return;
 +	}
 +
 +	private void handleSignResponse(ExecutionContext executionContext, HttpServletRequest request,
 +			HttpServletResponse response) {
 +		Logger.info("handleSignResponse started");
 +		String moaSessionID = request.getParameter("moaSessionID");
 +		String signResponse = request.getParameter("signresponse");
 +		Logger.info("moaSessionID:" + moaSessionID);
 +		Logger.info("signResponse:" + signResponse);
 +		String pendingRequestID = null;
 +		try {
 +
 +			// load MOASession from database
 +			AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
 +			// change MOASessionID
 +			moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
 +			Logger.info("pendingRequestID:" + pendingRequestID);
 +			String signResponseString = new String(Base64.decodeBase64(signResponse), "UTF8");
 +			Logger.info("RECEIVED signresponse:" + signResponseString);
 +			// create SignResponse object
 +			Source response1 = new StreamSource(new java.io.StringReader(signResponseString));
 +			SignResponse dssSignResponse = ApiUtils.unmarshal(response1, SignResponse.class);
 +
 +			// SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(new
 +			// java.io.StringReader(Base64.signResponse)));
 +
 +			String citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);
 +
 +			// memorize signature into authblock
 +			moaSession.setAuthBlock(citizenSignature);
 +
 +			X509Certificate cert = getSignerCertificate(citizenSignature);
 +			moaSession.setSignerCertificate(cert);
 +			VerifyXMLSignatureResponse xMLVerifySignatureResponse = verifyXMLSignature(citizenSignature);
 +			at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse tmp = convert(xMLVerifySignatureResponse);
 +
 +			moaSession.setXMLVerifySignatureResponse(tmp);
 +			executionContext.put("identityLinkAvailable", false);
 +			try {
 +				IPersonalAttributeList personalAttributeList = moaSession.getAuthnResponseGetPersonalAttributeList();
 +				// Add SignResponse TODO Add signature (extracted from signResponse)?
 +				List<String> values = new ArrayList<String>();
 +				values.add(signResponseString);
 +				// values.add(citizenSignature);
 +				Logger.debug("Assembling signedDoc attribute");
 +				PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, "Available");
 +				personalAttributeList.add(signedDocAttribute);
 +
 +				String authnContextClassRef = moaSession.getAuthnContextClassRef();
 +				SZRGInsertion(moaSession, personalAttributeList, authnContextClassRef, citizenSignature);
 +				executionContext.put("identityLinkAvailable", true);
 +			} catch (STORKException e) {
 +				// this is really nasty but we work against the system here. We are supposed to get the gender attribute
 +				// from
 +				// stork. If we do not, we cannot register the person in the ERnP - we have to have the
 +				// gender for the represented person. So here comes the dirty hack.
 +				if (e.getCause() instanceof STORKException
 +						&& e.getCause().getMessage().equals("gender not found in response")) {
 +					try {
 +						Logger.trace("Initialize VelocityEngine...");
 +
 +						VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
 +						Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
 +						VelocityContext context = new VelocityContext();
 +						context.put("SAMLResponse", request.getParameter("SAMLResponse"));
 +						context.put("action", request.getRequestURL());
 +
 +						StringWriter writer = new StringWriter();
 +						template.merge(context, writer);
 +						response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
 +					} catch (Exception e1) {
 +						Logger.error("Error sending gender retrival form.", e1);
 +						// httpSession.invalidate();
 +						throw new MOAIDException("stork.10", null);
 +					}
 +
 +					return;
 +				}
 +
 +				Logger.error("Error connecting SZR Gateway", e);
 +				throw new MOAIDException("stork.10", null);
 +			}
 +
 +			Logger.debug("Add full STORK AuthnResponse to MOA session");
 +			moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
 +																					// authnResponse?
 +			moaSession.setForeigner(true);
 +
 +			// session is implicit stored in changeSessionID!!!!
 +			String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
 +
 +			// redirect
 +			String redirectURL = null;
 +			redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
 +					ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
 +					newMOASessionID);
 +			redirectURL = response.encodeRedirectURL(redirectURL);
 +
 +			response.sendRedirect(redirectURL);
 +			Logger.info("REDIRECT TO: " + redirectURL);
 +
 +		} catch (AuthenticationException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (MOAIDException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("PEPSConnector has an interal Error.", e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleResponseWithoutSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleResponseWithoutSignatureTask.java new file mode 100644 index 000000000..31bc28f5a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorHandleResponseWithoutSignatureTask.java @@ -0,0 +1,441 @@ +package at.gv.egovernment.moa.id.auth.tasks.stork;
 +
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.io.StringWriter;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.transform.Source;
 +import javax.xml.transform.stream.StreamSource;
 +
 +import org.apache.commons.codec.binary.Base64;
 +import org.apache.commons.io.IOUtils;
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.velocity.Template;
 +import org.apache.velocity.VelocityContext;
 +import org.apache.velocity.app.VelocityEngine;
 +import org.opensaml.saml2.core.StatusCode;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet;
 +import at.gv.egovernment.moa.id.auth.stork.STORKException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.HTTPUtils;
 +import at.gv.egovernment.moa.id.util.VelocityProvider;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.StringUtils;
 +
 +import com.datentechnik.process_engine.api.ExecutionContext;
 +
 +import eu.stork.oasisdss.api.ApiUtils;
 +import eu.stork.oasisdss.profile.SignRequest;
 +import eu.stork.oasisdss.profile.SignResponse;
 +import eu.stork.peps.auth.commons.IPersonalAttributeList;
 +import eu.stork.peps.auth.commons.PEPSUtil;
 +import eu.stork.peps.auth.commons.PersonalAttribute;
 +import eu.stork.peps.auth.commons.STORKAuthnRequest;
 +import eu.stork.peps.auth.commons.STORKAuthnResponse;
 +import eu.stork.peps.auth.engine.STORKSAMLEngine;
 +import eu.stork.peps.exceptions.STORKSAMLEngineException;
 +
 +/**
 + * Validates the SAML response from C-PEPS.
 + * <p/>
 + * In detail:
 + * <ul>
 + * <li>Decodes and validates SAML response from C-PEPS.</li>
 + * <li>Retrieves the moa session using the session id provided by HttpServletRequest parameter {@code RelayState} or by {@code inResponseTo} attribute of the saml response.</li>
 + * <li>Store saml response in moa session.</li>
 + * <li>Change moa session id.</li>
 + * <li>Redirect to {@code /PEPSConnectorWithLocalSigning}, with providing the moa session id as request parameter.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@code moaSessionID} <strong>to be {@code null}</strong></li>
 + * <li>HttpServletRequest parameter {@code signresponse} <strong>to be {@code null}</strong></li>
 + * <li>HttpServletRequest parameter {@code SAMLResponse}</li>
 + * <li>Either HttpServletRequest parameter {@code RelayState} or {@code inResponseTo} attribute within the saml response, both reflecting the moa session id.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Updated moa session (with saml response).</li>
 + * <li>Redirect to {@code /PEPSConnectorWithLocalSigning}, with providing the moa session id as request parameter.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet}.<br/>
 + *
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + */
 +public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPepsConnectorWithLocalSigningTask {
 +
 +	private String oasisDssWebFormURL = "https://testvidp.buergerkarte.at/oasis-dss/DSSWebFormServlet";
 +	// load from config below
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
 +			throws Exception {
 +		String moaSessionID = request.getParameter("moaSessionID");
 +		String signResponse = request.getParameter("signresponse");
 +		Logger.info("moaSessionID:" + moaSessionID);
 +		Logger.info("signResponse:" + signResponse);
 +
 +		if (moaSessionID == null && signResponse == null) {
 +			// normal saml response
 +			handleSAMLResponse(executionContext, request, response);
 +
 +		} else {
 +			// should not occur
 +			throw new IOException("should not occur");
 +		}
 +		return;
 +	}
 +
 +	private void handleSAMLResponse(ExecutionContext executionContext, HttpServletRequest request,
 +			HttpServletResponse response) {
 +		Logger.info("handleSAMLResponse started");
 +		String pendingRequestID = null;
 +
 +		setNoCachingHeaders(response);
 +		try {
 +			Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
 +			Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
 +
 +			Logger.trace("No Caching headers set for HTTP response");
 +
 +			// check if https or only http
 +			super.checkIfHTTPisAllowed(request.getRequestURL().toString());
 +
 +			Logger.debug("Beginning to extract SAMLResponse out of HTTP Request");
 +
 +			// extract STORK Response from HTTP Request
 +			// Decodes SAML Response
 +			byte[] decSamlToken;
 +			try {
 +				decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLResponse"));
 +				Logger.debug("SAMLResponse: " + new String(decSamlToken));
 +
 +			} catch (NullPointerException e) {
 +				Logger.error("Unable to retrieve STORK Response", e);
 +				throw new MOAIDException("stork.04", null);
 +			}
 +
 +			// Get SAMLEngine instance
 +			STORKSAMLEngine engine = STORKSAMLEngine.getInstance("outgoing");
 +
 +			STORKAuthnResponse authnResponse = null;
 +			try {
 +				// validate SAML Token
 +				Logger.debug("Starting validation of SAML response");
 +				authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) request.getRemoteHost());
 +				Logger.info("SAML response succesfully verified!");
 +			} catch (STORKSAMLEngineException e) {
 +				Logger.error("Failed to verify STORK SAML Response", e);
 +				throw new MOAIDException("stork.05", null);
 +			}
 +
 +			Logger.info("STORK SAML Response message succesfully extracted");
 +			Logger.debug("STORK response: ");
 +			Logger.debug(authnResponse.toString());
 +
 +			Logger.debug("Trying to find MOA Session-ID ...");
 +			// String moaSessionID = request.getParameter(PARAM_SESSIONID);
 +			// first use SAML2 relayState
 +			String moaSessionID = request.getParameter("RelayState");
 +
 +			// escape parameter strings
 +			moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
 +
 +			// check if SAML2 relaystate includes a MOA sessionID
 +			if (StringUtils.isEmpty(moaSessionID)) {
 +				// if relaystate is emtpty, use SAML response -> inResponseTo element as session identifier
 +
 +				moaSessionID = authnResponse.getInResponseTo();
 +				moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
 +
 +				if (StringUtils.isEmpty(moaSessionID)) {
 +					// No authentication session has been started before
 +					Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
 +					Logger.debug("PEPSConnectorURL was: " + request.getRequestURL());
 +					throw new AuthenticationException("auth.02", new Object[] { moaSessionID });
 +
 +				} else
 +					Logger.trace("Use MOA SessionID " + moaSessionID + " from AuthnResponse->inResponseTo attribute.");
 +
 +			} else
 +				// Logger.trace("MOA SessionID " + moaSessionID + " is found in http GET parameter.");
 +				Logger.trace("MOA SessionID " + moaSessionID + " is found in SAML2 relayState.");
 +
 +			/*
 +			 * INFO!!!! SAML message IDs has an different format then MOASessionIDs This is only a workaround because
 +			 * many PEPS does not support SAML2 relayState or MOASessionID as AttributConsumerServiceURL GET parameter
 +			 */
 +			// if (!ParamValidatorUtils.isValidSessionID(moaSessionID))
 +			// throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
 +
 +			// load MOASession from database
 +			AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
 +			// change MOASessionID
 +			moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			Logger.info("Found MOA sessionID: " + moaSessionID);
 +
 +			String statusCodeValue = authnResponse.getStatusCode();
 +
 +			if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
 +				Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
 +				throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
 +			}
 +
 +			Logger.info("Got SAML response with authentication success message.");
 +
 +			Logger.debug("MOA session is still valid");
 +
 +			STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
 +
 +			if (storkAuthnRequest == null) {
 +				Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +				throw new MOAIDException("stork.07", null);
 +			}
 +
 +			Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +
 +			// //////////// incorporate gender from parameters if not in stork response
 +
 +			IPersonalAttributeList attributeList = authnResponse.getPersonalAttributeList();
 +
 +			// but first, check if we have a representation case
 +			if (STORKResponseProcessor.hasAttribute("mandateContent", attributeList)
 +					|| STORKResponseProcessor.hasAttribute("representative", attributeList)
 +					|| STORKResponseProcessor.hasAttribute("represented", attributeList)) {
 +				// in a representation case...
 +				moaSession.setUseMandate("true");
 +
 +				// and check if we have the gender value
 +				PersonalAttribute gender = attributeList.get("gender");
 +				if (null == gender) {
 +					String gendervalue = (String) request.getParameter("gender");
 +					if (null != gendervalue) {
 +						gender = new PersonalAttribute();
 +						gender.setName("gender");
 +						ArrayList<String> tmp = new ArrayList<String>();
 +						tmp.add(gendervalue);
 +						gender.setValue(tmp);
 +
 +						authnResponse.getPersonalAttributeList().add(gender);
 +					}
 +				}
 +			}
 +
 +			
 +			
 +			// ////////////////////////////////////////////////////////////////////////
 +
 +			Logger.debug("Starting extraction of signedDoc attribute");
 +			// extract signed doc element and citizen signature
 +			String citizenSignature = null;
 +			try {
 +				PersonalAttribute signedDoc = authnResponse.getPersonalAttributeList().get("signedDoc");
 +				String signatureInfo = null;
 +				// FIXME: Remove nonsense code (signedDoc attribute... (throw Exception for "should not occur" situations)), adjust error messages in order to reflect the true problem...
 +				if (signedDoc != null) {
 +					signatureInfo = signedDoc.getValue().get(0);
 +					// should not occur
 +				} else {
 +
 +					// store SAMLResponse
 +					moaSession.setSAMLResponse(request.getParameter("SAMLResponse"));
 +					// store authnResponse
 +
 +					// moaSession.setAuthnResponse(authnResponse);//not serializable
 +					moaSession.setAuthnResponseGetPersonalAttributeList(authnResponse.getPersonalAttributeList());
 +
 +					String authnContextClassRef = null;
 +					try {
 +						authnContextClassRef = authnResponse.getAssertions().get(0).getAuthnStatements().get(0)
 +								.getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef();
 +					} catch (Throwable e) {
 +						Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
 +					}
 +
 +					moaSession.setAuthnContextClassRef(authnContextClassRef);
 +					moaSession.setReturnURL(request.getRequestURL());
 +
 +					// load signedDoc
 +					String signRequest = moaSession.getSignedDoc();
 +
 +					// session is implicit stored in changeSessionID!!!!
 +					String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +					// set return url to PEPSConnectorWithLocalSigningServlet and add newMOASessionID
 +					// signRequest
 +
 +					String issuerValue = AuthConfigurationProvider.getInstance().getPublicURLPrefix();
 +					String acsURL = issuerValue
 +							+ PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN;
 +
 +					String url = acsURL + "?moaSessionID=" + newMOASessionID;
 +					// redirect to OASIS module and sign there
 +
 +					boolean found = false;
 +					try {
 +						List<AttributeProviderPlugin> aps = AuthConfigurationProvider.getInstance()
 +								.getOnlineApplicationParameter(moaSession.getPublicOAURLPrefix()).getStorkAPs();
 +						Logger.info("Found AttributeProviderPlugins:" + aps.size());
 +						for (AttributeProviderPlugin ap : aps) {
 +							Logger.info("Found AttributeProviderPlugin attribute:" + ap.getAttributes());
 +							if (ap.getAttributes().equalsIgnoreCase("signedDoc")) {
 +								// FIXME: A servlet's class field is not thread safe!!!
 +								oasisDssWebFormURL = ap.getUrl();
 +								found = true;
 +								Logger.info("Loaded signedDoc attribute provider url from config:" + oasisDssWebFormURL);
 +								break;
 +							}
 +						}
 +					} catch (Exception e) {
 +						e.printStackTrace();
 +						Logger.error("Loading the signedDoc attribute provider url from config failed");
 +					}
 +					if (!found) {
 +						Logger.error("Failed to load the signedDoc attribute provider url from config");
 +					}
 +					performRedirect(url, request, response, signRequest);
 +
 +					return;
 +				}
 +				
 +				// FIXME: This servlet/task is intended to handle peps responses without signature, so why do we try to process that signature here?
 +				SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(
 +						new java.io.StringReader(signatureInfo)));
 +
 +				citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);
 +
 +				// memorize signature into authblock
 +				moaSession.setAuthBlock(citizenSignature);
 +
 +				X509Certificate cert = getSignerCertificate(citizenSignature);
 +				moaSession.setSignerCertificate(cert);
 +				moaSession.setForeigner(true);
 +
 +			} catch (Throwable e) {
 +				Logger.error("Could not extract citizen signature from C-PEPS", e);
 +				throw new MOAIDException("stork.09", null);
 +			}
 +
 +			// FIXME: Same here; we do not have the citizen's signature, so this code might be regarded as dead code.
 +			try {
 +				SZRGInsertion(moaSession, authnResponse.getPersonalAttributeList(), authnResponse.getAssertions()
 +						.get(0).getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef()
 +						.getAuthnContextClassRef(), citizenSignature);
 +			} catch (STORKException e) {
 +				// this is really nasty but we work against the system here. We are supposed to get the gender attribute
 +				// from
 +				// stork. If we do not, we cannot register the person in the ERnP - we have to have the
 +				// gender for the represented person. So here comes the dirty hack.
 +				if (e.getCause() instanceof STORKException
 +						&& e.getCause().getMessage().equals("gender not found in response")) {
 +					try {
 +						Logger.trace("Initialize VelocityEngine...");
 +
 +						VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
 +						Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
 +						VelocityContext context = new VelocityContext();
 +						context.put("SAMLResponse", request.getParameter("SAMLResponse"));
 +						context.put("action", request.getRequestURL());
 +
 +						StringWriter writer = new StringWriter();
 +						template.merge(context, writer);
 +
 +						response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
 +					} catch (Exception e1) {
 +						Logger.error("Error sending gender retrival form.", e1);
 +						// httpSession.invalidate();
 +						throw new MOAIDException("stork.10", null);
 +					}
 +
 +					return;
 +				}
 +
 +				Logger.error("Error connecting SZR Gateway", e);
 +				throw new MOAIDException("stork.10", null);
 +			}
 +
 +			Logger.debug("Add full STORK AuthnResponse to MOA session");
 +			moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
 +																					// authnResponse?
 +
 +			// session is implicit stored in changeSessionID!!!!
 +			String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
 +
 +			// redirect
 +			String redirectURL = null;
 +			redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
 +					ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
 +					newMOASessionID);
 +			redirectURL = response.encodeRedirectURL(redirectURL);
 +
 +			response.setContentType("text/html");
 +			response.setStatus(302);
 +			response.addHeader("Location", redirectURL);
 +			Logger.info("REDIRECT TO: " + redirectURL);
 +
 +		} catch (AuthenticationException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (MOAIDException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("PEPSConnector has an interal Error.", e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +
 +	}
 +
 +	private void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, String signRequestString)
 +			throws MOAIDException {
 +
 +		try {
 +			Logger.trace("Initialize VelocityEngine...");
 +
 +			VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
 +			Template template = velocityEngine.getTemplate("/resources/templates/oasis_dss_webform_binding.vm");
 +			VelocityContext context = new VelocityContext();
 +
 +			Logger.debug("performRedirect, signrequest:" + signRequestString);
 +			Source signDoc = new StreamSource(new java.io.StringReader(signRequestString));
 +			SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class);
 +			signRequest.setReturnURL("TODO");
 +			signRequestString = IOUtils.toString(ApiUtils.marshalToInputStream(signRequest));
 +			context.put("signrequest", Base64.encodeBase64String(signRequestString.getBytes("UTF8")));
 +			context.put("clienturl", url);
 +			context.put("action", oasisDssWebFormURL);
 +
 +			StringWriter writer = new StringWriter();
 +			template.merge(context, writer);
 +
 +			resp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
 +		} catch (Exception e) {
 +			Logger.error("Error sending DSS signrequest.", e);
 +			throw new MOAIDException("stork.11", null);
 +		}
 +	}
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorTask.java new file mode 100644 index 000000000..0e4e2a0f7 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/tasks/stork/PepsConnectorTask.java @@ -0,0 +1,567 @@ +package at.gv.egovernment.moa.id.auth.tasks.stork;
 +
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.io.StringWriter;
 +import java.net.URL;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.List;
 +import java.util.Properties;
 +
 +import javax.activation.DataSource;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.bind.JAXBContext;
 +import javax.xml.bind.JAXBElement;
 +import javax.xml.namespace.QName;
 +import javax.xml.transform.stream.StreamSource;
 +import javax.xml.ws.BindingProvider;
 +import javax.xml.ws.Service;
 +import javax.xml.ws.soap.SOAPBinding;
 +
 +import org.apache.commons.io.IOUtils;
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.velocity.Template;
 +import org.apache.velocity.VelocityContext;
 +import org.apache.velocity.app.VelocityEngine;
 +import org.opensaml.saml2.core.StatusCode;
 +
 +import com.datentechnik.process_engine.api.ExecutionContext;
 +
 +import eu.stork.documentservice.DocumentService;
 +import eu.stork.documentservice.data.DatabaseConnectorMySQLImpl;
 +import eu.stork.oasisdss.api.ApiUtils;
 +import eu.stork.oasisdss.api.LightweightSourceResolver;
 +import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
 +import eu.stork.oasisdss.profile.DocumentType;
 +import eu.stork.oasisdss.profile.DocumentWithSignature;
 +import eu.stork.oasisdss.profile.SignResponse;
 +import eu.stork.peps.auth.commons.IPersonalAttributeList;
 +import eu.stork.peps.auth.commons.PEPSUtil;
 +import eu.stork.peps.auth.commons.PersonalAttribute;
 +import eu.stork.peps.auth.commons.PersonalAttributeList;
 +import eu.stork.peps.auth.commons.STORKAttrQueryRequest;
 +import eu.stork.peps.auth.commons.STORKAuthnRequest;
 +import eu.stork.peps.auth.commons.STORKAuthnResponse;
 +import eu.stork.peps.auth.engine.STORKSAMLEngine;
 +import eu.stork.peps.exceptions.STORKSAMLEngineException;
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
 +import at.gv.egovernment.moa.id.auth.tasks.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.HTTPUtils;
 +import at.gv.egovernment.moa.id.util.VelocityProvider;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.StringUtils;
 +import at.gv.util.xsd.xmldsig.SignatureType;
 +import at.gv.util.xsd.xmldsig.X509DataType;
 +
 +/**
 + * Evaluates the SAML response from the C-PEPS and authenticates the user.
 + * <p/>
 + * In detail:
 + * <ul>
 + * <li>Decodes and validates the SAML response from the C-PEPS.</li>
 + * <li>Change moa session id.</li>
 + * <li>Extracts the subject's gender from request parameter {@code gender} if not available from the saml response.</li>
 + * <li>Extracts the {@code signedDoc} attribute from the response, get signed doc payload using stork attribute query request.</li>
 + * <li>Request SZR gateway for verification of the citizen's signature and for creating of an identity link.</li>
 + * <li>In case of mandate mode: If the S-PEPS did not provide any gender information, the szr gateway will not be able to issue an identity link. Therefore a form is presented asking for the subject's gender. The form submits the user back to the {@code /PepsConnector} servlet (this task).</li>
 + * <li>The moa session is updated with authentication information.</li>
 + * <li>Change moa session id.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@code SAMLResponse}</li>
 + * <li>Either HttpServletRequest parameter {@code RelayState} or {@code inResponseTo} attribute from the SAML response (both depicting the moa session id)</li>
 + * <li>HttpServletRequest parameter {@code gender} in case the request comes from the gender selection form</li>
 + * <li>{@code signedDoc} attribute within the SAML response.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Updated moa id session (identity link, stork attributes...)</li>
 + * <li>{@link ExecutionContext} contains boolean flag {@code identityLinkAvailable} indicating if an identitylink has been successfully creates or not.</li>
 + * <li>Redirect to {@code /dispatcher}.</li> 
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case the szr gateway throws exception due to missing gender information:
 + * <ul>
 + * <li>Returns a form for gender selection with action url back to this servlet/task.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet}.<br/>
 + *
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + */
 +public class PepsConnectorTask extends AbstractAuthServletTask {
 +
 +	private String dtlUrl = null;
 +
 +	public PepsConnectorTask() {
 +		super();
 +		Properties props = new Properties();
 +		try {
 +			props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties"));
 +			dtlUrl = props.getProperty("docservice.url");
 +		} catch (IOException e) {
 +			dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService";
 +			Logger.error("Loading DTL config failed, using default value:" + dtlUrl);
 +			e.printStackTrace();
 +		}
 +	}
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
 +			throws Exception {
 +		String pendingRequestID = null;
 +
 +		setNoCachingHeaders(response);
 +
 +		try {
 +
 +			Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
 +			Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
 +
 +			// check if https or only http
 +			super.checkIfHTTPisAllowed(request.getRequestURL().toString());
 +
 +			Logger.debug("Beginning to extract SAMLResponse out of HTTP Request");
 +
 +			// extract STORK Response from HTTP Request
 +			// Decodes SAML Response
 +			byte[] decSamlToken;
 +			try {
 +				decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLResponse"));
 +				Logger.debug("SAMLResponse: " + new String(decSamlToken));
 +
 +			} catch (NullPointerException e) {
 +				Logger.error("Unable to retrieve STORK Response", e);
 +				throw new MOAIDException("stork.04", null);
 +			}
 +
 +			// Get SAMLEngine instance
 +			STORKSAMLEngine engine = STORKSAMLEngine.getInstance("outgoing");
 +
 +			STORKAuthnResponse authnResponse = null;
 +			try {
 +				// validate SAML Token
 +				Logger.debug("Starting validation of SAML response");
 +				authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) request.getRemoteHost());
 +				Logger.info("SAML response succesfully verified!");
 +			} catch (STORKSAMLEngineException e) {
 +				Logger.error("Failed to verify STORK SAML Response", e);
 +				throw new MOAIDException("stork.05", null);
 +			}
 +
 +			Logger.info("STORK SAML Response message succesfully extracted");
 +			Logger.debug("STORK response: ");
 +			Logger.debug(authnResponse.toString());
 +
 +			Logger.debug("Trying to find MOA Session-ID ...");
 +			// String moaSessionID = request.getParameter(PARAM_SESSIONID);
 +			// first use SAML2 relayState
 +			String moaSessionID = request.getParameter("RelayState");
 +
 +			// escape parameter strings
 +			moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
 +
 +			// check if SAML2 relaystate includes a MOA sessionID
 +			if (StringUtils.isEmpty(moaSessionID)) {
 +				// if relaystate is emtpty, use SAML response -> inResponseTo element as session identifier
 +
 +				moaSessionID = authnResponse.getInResponseTo();
 +				moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
 +
 +				if (StringUtils.isEmpty(moaSessionID)) {
 +					// No authentication session has been started before
 +					Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
 +					Logger.debug("PEPSConnectorURL was: " + request.getRequestURL());
 +					throw new AuthenticationException("auth.02", new Object[] { moaSessionID });
 +
 +				} else
 +					Logger.trace("Use MOA SessionID " + moaSessionID + " from AuthnResponse->inResponseTo attribute.");
 +
 +			} else
 +				// Logger.trace("MOA SessionID " + moaSessionID + " is found in http GET parameter.");
 +				Logger.trace("MOA SessionID " + moaSessionID + " is found in SAML2 relayState.");
 +
 +			/*
 +			 * INFO!!!! SAML message IDs has an different format then MOASessionIDs This is only a workaround because
 +			 * many PEPS does not support SAML2 relayState or MOASessionID as AttributConsumerServiceURL GET parameter
 +			 */
 +			// if (!ParamValidatorUtils.isValidSessionID(moaSessionID))
 +			// throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
 +
 +			// load MOASession from database
 +			AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
 +			// change MOASessionID
 +			moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			Logger.info("Found MOA sessionID: " + moaSessionID);
 +
 +			String statusCodeValue = authnResponse.getStatusCode();
 +
 +			if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
 +				Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
 +				throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
 +			}
 +
 +			Logger.info("Got SAML response with authentication success message.");
 +
 +			Logger.debug("MOA session is still valid");
 +
 +			STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
 +
 +			if (storkAuthnRequest == null) {
 +				Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +				throw new MOAIDException("stork.07", null);
 +			}
 +
 +			Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +
 +			// //////////// incorporate gender from parameters if not in stork response
 +
 +			IPersonalAttributeList attributeList = authnResponse.getPersonalAttributeList();
 +
 +			// but first, check if we have a representation case
 +			if (STORKResponseProcessor.hasAttribute("mandateContent", attributeList)
 +					|| STORKResponseProcessor.hasAttribute("representative", attributeList)
 +					|| STORKResponseProcessor.hasAttribute("represented", attributeList)) {
 +				// in a representation case...
 +				moaSession.setUseMandate("true");
 +
 +				// and check if we have the gender value
 +				PersonalAttribute gender = attributeList.get("gender"); // TODO Do we need to check gender value if
 +																		// there is no representation case?
 +				if (null == gender) {
 +					String gendervalue = (String) request.getParameter("gender");
 +					if (null != gendervalue) {
 +						gender = new PersonalAttribute();
 +						gender.setName("gender");
 +						ArrayList<String> tmp = new ArrayList<String>();
 +						tmp.add(gendervalue);
 +						gender.setValue(tmp);
 +
 +						authnResponse.getPersonalAttributeList().add(gender);
 +					}
 +				}
 +			}
 +
 +			// ////////////////////////////////////////////////////////////////////////
 +
 +			Logger.debug("Starting extraction of signedDoc attribute");
 +			// extract signed doc element and citizen signature
 +			String citizenSignature = null;
 +			try {
 +				String signatureInfo = authnResponse.getPersonalAttributeList().get("signedDoc").getValue().get(0); // TODO ERROR HANDLING
 +
 +				Logger.debug("signatureInfo:" + signatureInfo);
 +
 +				SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(
 +						new java.io.StringReader(signatureInfo)));
 +
 +				// fetch signed doc
 +				DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse);
 +				if (ds == null) {
 +					throw new ApiUtilsException("No datasource found in response");
 +				}
 +
 +				InputStream incoming = ds.getInputStream();
 +				citizenSignature = IOUtils.toString(incoming);
 +				incoming.close();
 +
 +				Logger.debug("citizenSignature:" + citizenSignature);
 +				if (isDocumentServiceUsed(citizenSignature) == true) {
 +					Logger.debug("Loading document from DocumentService.");
 +					String url = getDtlUrlFromResponse(dssSignResponse);
 +					// get Transferrequest
 +					String transferRequest = getDocTransferRequest(dssSignResponse.getDocUI(), url);
 +					// Load document from DocujmentService
 +					byte[] data = getDocumentFromDtl(transferRequest, url);
 +					citizenSignature = new String(data, "UTF-8");
 +					Logger.debug("Overridung citizenSignature with:" + citizenSignature);
 +				}
 +
 +				JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName());
 +				SignatureType root = ((JAXBElement<SignatureType>) ctx.createUnmarshaller().unmarshal(
 +						IOUtils.toInputStream(citizenSignature))).getValue();
 +
 +				// memorize signature into authblock
 +				moaSession.setAuthBlock(citizenSignature);
 +
 +				// extract certificate
 +				for (Object current : root.getKeyInfo().getContent())
 +					if (((JAXBElement<?>) current).getValue() instanceof X509DataType) {
 +						for (Object currentX509Data : ((JAXBElement<X509DataType>) current).getValue()
 +								.getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
 +							JAXBElement<?> casted = ((JAXBElement<?>) currentX509Data);
 +							if (casted.getName().getLocalPart().equals("X509Certificate")) {
 +								moaSession.setSignerCertificate(new X509Certificate(((String) casted.getValue())
 +										.getBytes("UTF-8")));
 +								break;
 +							}
 +						}
 +					}
 +
 +			} catch (Throwable e) {
 +				Logger.error("Could not extract citizen signature from C-PEPS", e);
 +				throw new MOAIDException("stork.09", null);
 +			}
 +			Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
 +			Logger.debug("Citizen signature will be verified by SZR Gateway!");
 +
 +			Logger.debug("fetching OAParameters from database");
 +
 +			// //read configuration paramters of OA
 +			// AuthenticationSession moasession;
 +			// try {
 +			// moasession = AuthenticationSessionStoreage.getSession(moaSessionID);
 +			// } catch (MOADatabaseException e2) {
 +			// Logger.error("could not retrieve moa session");
 +			// throw new AuthenticationException("auth.01", null);
 +			// }
 +			OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
 +					moaSession.getPublicOAURLPrefix());
 +			if (oaParam == null)
 +				throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() });
 +
 +			// retrieve target
 +			// TODO: check in case of SSO!!!
 +			String targetType = null;
 +			if (oaParam.getBusinessService()) {
 +				String id = oaParam.getIdentityLinkDomainIdentifier();
 +				if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
 +					targetType = id;
 +				else
 +					targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_ + moaSession.getDomainIdentifier();
 +			} else {
 +				targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
 +			}
 +
 +			Logger.debug("Starting connecting SZR Gateway");
 +			// contact SZR Gateway
 +			IdentityLink identityLink = null;
 +			executionContext.put("identityLinkAvailable", false);
 +			try {
 +				identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(),
 +						oaParam.getFriendlyName(), targetType, null, oaParam.getMandateProfiles(), citizenSignature);
 +			} catch (STORKException e) {
 +				// this is really nasty but we work against the system here. We are supposed to get the gender attribute
 +				// from
 +				// stork. If we do not, we cannot register the person in the ERnP - we have to have the
 +				// gender for the represented person. So here comes the dirty hack.
 +				if (e.getCause() instanceof STORKException
 +						&& e.getCause().getMessage().equals("gender not found in response")) {
 +					try {
 +						Logger.trace("Initialize VelocityEngine...");
 +
 +						VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
 +						Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
 +						VelocityContext context = new VelocityContext();
 +						context.put("SAMLResponse", request.getParameter("SAMLResponse"));
 +						context.put("action", request.getRequestURL());
 +
 +						StringWriter writer = new StringWriter();
 +						template.merge(context, writer);
 +
 +						response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
 +					} catch (Exception e1) {
 +						Logger.error("Error sending gender retrival form.", e1);
 +						// httpSession.invalidate();
 +						throw new MOAIDException("stork.10", null);
 +					}
 +
 +					return;
 +				}
 +
 +				Logger.error("Error connecting SZR Gateway", e);
 +				throw new MOAIDException("stork.10", null);
 +			}
 +			Logger.debug("SZR communication was successfull");
 +
 +			if (identityLink == null) {
 +				Logger.error("SZR Gateway did not return an identity link.");
 +				throw new MOAIDException("stork.10", null);
 +			}
 +			moaSession.setForeigner(true);
 +
 +			Logger.info("Received Identity Link from SZR Gateway");
 +			executionContext.put("identityLinkAvailable", true);
 +			moaSession.setIdentityLink(identityLink);
 +
 +			Logger.debug("Adding addtional STORK attributes to MOA session");
 +			moaSession.setStorkAttributes(authnResponse.getPersonalAttributeList());
 +
 +			Logger.debug("Add full STORK AuthnResponse to MOA session");
 +			moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));
 +
 +			// We don't have BKUURL, setting from null to "Not applicable"
 +			moaSession.setBkuURL("Not applicable (STORK Authentication)");
 +
 +			// free for single use
 +			moaSession.setAuthenticatedUsed(false);
 +
 +			// stork did the authentication step
 +			moaSession.setAuthenticated(true);
 +
 +			// TODO: found better solution, but QAA Level in response could be not supported yet
 +			try {
 +
 +				moaSession.setQAALevel(authnResponse.getAssertions().get(0).getAuthnStatements().get(0)
 +						.getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef());
 +
 +			} catch (Throwable e) {
 +				Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
 +				moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel());
 +
 +			}
 +
 +			// session is implicit stored in changeSessionID!!!!
 +			String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
 +
 +			Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
 +
 +			// redirect
 +			String redirectURL = null;
 +			redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
 +					ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
 +					newMOASessionID);
 +			redirectURL = response.encodeRedirectURL(redirectURL);
 +
 +			// response.setContentType("text/html");
 +			// response.setStatus(302);
 +			// response.addHeader("Location", redirectURL);
 +			response.sendRedirect(redirectURL);
 +			Logger.info("REDIRECT TO: " + redirectURL);
 +
 +		} catch (AuthenticationException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (MOAIDException e) {
 +			handleError(null, e, request, response, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("PEPSConnector has an interal Error.", e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +
 +	}
 +
 +	private boolean isDocumentServiceUsed(String citizenSignature) // TODo add better check
 +	{
 +		if (citizenSignature
 +				.contains("<table border=\"0\"><tr><td>Service Name:</td><td>{http://stork.eu}DocumentService</td></tr><tr><td>Port Name:</td><td>{http://stork.eu}DocumentServicePort</td></tr></table>"))
 +			return true;
 +		return false;
 +	}
 +
 +	/**
 +	 * Get DTL uril from the oasis sign response
 +	 * 
 +	 * @param signRequest
 +	 *            The signature response
 +	 * @return The URL of DTL service
 +	 * @throws SimpleException
 +	 */
 +	private String getDtlUrlFromResponse(SignResponse dssSignResponse) {
 +		List<DocumentWithSignature> documents = ApiUtils.findNamedElement(dssSignResponse.getOptionalOutputs(),
 +				ApiUtils.OPTIONAL_OUTPUT_DOCUMENTWITHSIGNATURE, DocumentWithSignature.class);
 +		DocumentType sourceDocument = documents.get(0).getDocument();
 +
 +		if (sourceDocument.getDocumentURL() != null)
 +			return sourceDocument.getDocumentURL();
 +		else
 +			return null;// throw new Exception("No document url found");
 +	}
 +
 +	// From DTLPEPSUTIL
 +
 +	/**
 +	 * Get document from DTL
 +	 * 
 +	 * @param transferRequest
 +	 *            The transfer request (attribute query)
 +	 * @param eDtlUrl
 +	 *            The DTL url of external DTL
 +	 * @return the document data
 +	 * @throws SimpleException
 +	 */
 +	private byte[] getDocumentFromDtl(String transferRequest, String eDtlUrl) throws Exception {
 +		URL url = null;
 +		try {
 +			url = new URL(dtlUrl);
 +			QName qname = new QName("http://stork.eu", "DocumentService");
 +
 +			Service service = Service.create(url, qname);
 +			DocumentService docservice = service.getPort(DocumentService.class);
 +
 +			BindingProvider bp = (BindingProvider) docservice;
 +			SOAPBinding binding = (SOAPBinding) bp.getBinding();
 +			binding.setMTOMEnabled(true);
 +
 +			if (eDtlUrl.equalsIgnoreCase(dtlUrl))
 +				return docservice.getDocument(transferRequest, "");
 +			else
 +				return docservice.getDocument(transferRequest, eDtlUrl);
 +		} catch (Exception e) {
 +			e.printStackTrace();
 +			throw new Exception("Error in getDocumentFromDtl", e);
 +		}
 +	}
 +
 +	/**
 +	 * Get a document transfer request (attribute query)
 +	 * 
 +	 * @param docId
 +	 * @return
 +	 * @throws SimpleException
 +	 */
 +	private String getDocTransferRequest(String docId, String destinationUrl) throws Exception {
 +		String spCountry = docId.substring(0, docId.indexOf("/"));
 +		final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
 +		STORKAttrQueryRequest req = new STORKAttrQueryRequest();
 +		req.setAssertionConsumerServiceURL(dtlUrl);
 +		req.setDestination(destinationUrl);
 +		req.setSpCountry(spCountry);
 +		req.setQaa(3);// TODO
 +		PersonalAttributeList pal = new PersonalAttributeList();
 +		PersonalAttribute attr = new PersonalAttribute();
 +		attr.setName("docRequest");
 +		attr.setIsRequired(true);
 +		attr.setValue(Arrays.asList(docId));
 +		pal.add(attr);
 +		req.setPersonalAttributeList(pal);
 +
 +		STORKAttrQueryRequest req1;
 +		try {
 +			req1 = engine.generateSTORKAttrQueryRequest(req);
 +			return PEPSUtil.encodeSAMLTokenUrlSafe(req1.getTokenSaml());
 +		} catch (STORKSAMLEngineException e) {
 +			e.printStackTrace();
 +			throw new Exception("Error in doc request attribute query generation", e);
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/resources/resources/processes/DefaultAuthentication.process.xml b/id/server/idserverlib/src/main/resources/resources/processes/DefaultAuthentication.process.xml index 48c9ee56c..b7d0d0f8b 100644 --- a/id/server/idserverlib/src/main/resources/resources/processes/DefaultAuthentication.process.xml +++ b/id/server/idserverlib/src/main/resources/resources/processes/DefaultAuthentication.process.xml @@ -2,7 +2,7 @@  <pd:ProcessDefinition id="DefaultAuthentication" xmlns:pd="http://www.datentechnik.com/process-engine/processdefinition/v1">
  <!--
 -	- National authentication with Austrian Citizen Card and mobile signature.
 +	- National authentication with Austrian Citizen Card and mobile signature with our without mandate.
  	- Legacy authentication for foreign citizens using MOCCA supported signature cards.
  -->
  	<pd:Task id="createIdentityLinkForm"    class="at.gv.egovernment.moa.id.auth.tasks.CreateIdentityLinkFormTask" />
 @@ -21,7 +21,7 @@  	<pd:Transition from="createIdentityLinkForm"    to="verifyIdentityLink" />
 -	<pd:Transition from="verifyIdentityLink"        to="certificateReadRequest" conditionExpression="!ctx['identityLinkFound'] || ctx['useMandate']" />
 +	<pd:Transition from="verifyIdentityLink"        to="certificateReadRequest" conditionExpression="!ctx['identityLinkAvailable'] || ctx['useMandate']" />
  	<pd:Transition from="verifyIdentityLink"        to="prepareAuthBlockSignature" />
  	<pd:Transition from="prepareAuthBlockSignature" to="verifyAuthBlock" />
 diff --git a/id/server/idserverlib/src/main/resources/resources/processes/STORKAuthentication.process.xml b/id/server/idserverlib/src/main/resources/resources/processes/STORKAuthentication.process.xml new file mode 100644 index 000000000..592603457 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/resources/processes/STORKAuthentication.process.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?>
 +<pd:ProcessDefinition id="STORKAuthentication" xmlns:pd="http://www.datentechnik.com/process-engine/processdefinition/v1">
 +
 +<!--
 +	- STORK authentication both with C-PEPS supporting xml signatures and with C-PEPS not supporting xml signatures.
 +-->
 +	<pd:Task id="createStorkAuthRequestForm"      class="at.gv.egovernment.moa.id.auth.tasks.stork.CreateStorkAuthRequestFormTask" />
 +	<pd:Task id="pepsConnector"                   class="at.gv.egovernment.moa.id.auth.tasks.stork.PepsConnectorTask"                               async="true" />
 +	<pd:Task id="pepsConnectorWithoutSignature"   class="at.gv.egovernment.moa.id.auth.tasks.stork.PepsConnectorHandleResponseWithoutSignatureTask" async="true" />
 +	<pd:Task id="pepsConnectorWithLocalSignature" class="at.gv.egovernment.moa.id.auth.tasks.stork.PepsConnectorHandleLocalSignResponseTask"        async="true" />
 +
 +	<!-- Process is triggered either by GenerateIFrameTemplateServlet (upon bku selection) or by AuthenticationManager (upon legacy authentication start using legacy parameters. -->
 +	<pd:StartEvent id="start" />
 +	
 +	<pd:Transition from="start" to="createStorkAuthRequestForm" />
 +	
 +	<pd:Transition from="createStorkAuthRequestForm" to="pepsConnector" conditionExpression="ctx['C-PEPS:XMLSignatureSupported']" />
 +	<pd:Transition from="createStorkAuthRequestForm" to="pepsConnectorWithoutSignature" />
 +	
 +	<pd:Transition from="pepsConnector" to="pepsConnector" conditionExpression="!ctx['identityLinkAvailable']" /> <!-- honor strange intermediate step of asking for the subject's gender -->
 +	<pd:Transition from="pepsConnector" to="end" />
 +	
 +	<pd:Transition from="pepsConnectorWithoutSignature"   to="pepsConnectorWithLocalSignature" />
 +	<pd:Transition from="pepsConnectorWithLocalSignature" to="pepsConnectorWithoutSignature" conditionExpression="!ctx['identityLinkAvailable']" /> <!-- honor strange intermediate step of asking for the subject's gender -->
 +	<pd:Transition from="pepsConnectorWithLocalSignature" to="end" />
 +	
 +	<pd:EndEvent id="end" />
 +
 +</pd:ProcessDefinition>
 diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 5dff986c2..ad01644a1 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -229,6 +229,9 @@ stork.18=STORK-SAML Engine konnte nicht initialisiert werden.  stork.19=Das erforderliche Attribut ist f\u00FCr naturliche Personen nicht vorhanden\: {0}
  stork.20=Fehler bei der Datenkonversion - eingegebens Datum fehlerhaft
  stork.21=Der angeforderte QAA-level {0} ist h\u00F6her als der QAA-level der Authentifizierung {1}
 +stork.22=Der STORK Authentifizierung erfordert die Auswahl des Herkunftslandes der Betroffenen.
 +stork.23=Die STORK Authentifizierung f\u00FCr "{0}" wird nicht unterst\u00FCtzt.
 +stork.24=Die STORK Authentifizierungsantwort enth\uFFFDlt leere Angaben zum Geschlecht.
  pvp2.00={0} ist kein gueltiger consumer service index
  pvp2.01=Fehler beim kodieren der PVP2 Antwort
 | 
