aboutsummaryrefslogtreecommitdiff
path: root/id/server/idserverlib/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/idserverlib/src/main/java')
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java15
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java136
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java92
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java33
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java20
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java378
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java42
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java57
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java28
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java103
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java120
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java185
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java183
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java104
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java250
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java163
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java102
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java149
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java6
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java15
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java83
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java96
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java7
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java126
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java82
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java101
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java10
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java10
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java9
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java3
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java68
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java1
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java14
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java28
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java35
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java7
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java29
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java255
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java142
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java109
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java111
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java79
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java44
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java224
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java35
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java98
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java356
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java36
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java164
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java30
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java63
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java23
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java25
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java23
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java89
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java43
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java90
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java42
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java158
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java69
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java45
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java94
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java136
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java61
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java116
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java74
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java143
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java35
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java10
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java21
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java35
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java52
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SchemaValidationException.java (renamed from id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java)29
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java58
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java18
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java14
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java86
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java1
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java5
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java109
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java11
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java11
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java78
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java11
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java46
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java112
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java3
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java63
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java3
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java24
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java55
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java7
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java22
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java10
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java31
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java3
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java8
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java4
-rw-r--r--id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java18
112 files changed, 5868 insertions, 1032 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java
index b68db92a4..f45a16780 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java
@@ -23,6 +23,7 @@
package at.gv.egovernment.moa.id.advancedlogging;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
@@ -160,8 +161,9 @@ public class StatisticLogger {
dblog.setPv(false);
}
+ InputStream is = null;
try {
- InputStream is = new ByteArrayInputStream(mandate.getMandate());
+ is = new ByteArrayInputStream(mandate.getMandate());
JAXBContext jc = JAXBContext.newInstance(Mandate.class);
Unmarshaller u = jc.createUnmarshaller();
@@ -189,6 +191,17 @@ public class StatisticLogger {
} catch (JAXBException e) {
Logger.warn("Advancted logging can not parse mandate.", e);
+
+ } finally {
+ if (is!=null) {
+ try {
+ is.close();
+
+ } catch (IOException e) {
+ Logger.warn("Close InputStream failed." , e);
+
+ }
+ }
}
}
}
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 43384c58a..eab7c511e 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
@@ -11,9 +11,11 @@ import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
+import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.CertificateException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
//import java.security.cert.CertificateFactory;
import java.util.Calendar;
@@ -29,6 +31,7 @@ import javax.xml.transform.TransformerException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
@@ -311,27 +314,28 @@ public class AuthenticationServer implements MOAIDAuthConstants {
}
/**
- * Processes an <code>&lt;InfoboxReadResponse&gt;</code> sent by the
- * security layer implementation.<br>
+ * Processes an <code>&lt;InfoboxReadResponse&gt;</code> sent by the security layer implementation.<br>
* <ul>
* <li>Validates given <code>&lt;InfoboxReadResponse&gt;</code></li>
- * <li>Parses identity link enclosed in
- * <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * <li>Parses identity link enclosed in <code>&lt;InfoboxReadResponse&gt;</code></li>
* <li>Verifies identity link by calling the MOA SP component</li>
* <li>Checks certificate authority of identity link</li>
* <li>Stores identity link in the session</li>
* <li>Verifies all additional infoboxes returned from the BKU</li>
* <li>Creates an authentication block to be signed by the user</li>
- * <li>Creates and returns a <code>&lt;CreateXMLSignatureRequest&gt;</code>
- * containg the authentication block, meant to be returned to the security
- * layer implementation</li>
+ * <li>Creates and returns a <code>&lt;CreateXMLSignatureRequest&gt;</code> containg the authentication block, meant
+ * to be returned to the security layer implementation</li>
* </ul>
- *
- * @param sessionID ID of associated authentication session data
- * @param infoboxReadResponseParameters The parameters from the response returned from the BKU
- * including the <code>&lt;InfoboxReadResponse&gt;</code>
- * @return String representation of the
- * <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ *
+ * @param sessionID
+ * ID of associated authentication session data
+ * @param infoboxReadResponseParameters
+ * The parameters from the response returned from the BKU including the
+ * <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return String "found!" in case the identity link could be retrieved and successfully validated, {@code null} in
+ * case the identity link could not be retrieved (indicates that the card did not contain an identity link
+ * which might indicate a foreign identity). Note that failing to parse or failing to validate the identity
+ * link results in an Exception being thrown.
* @throws BKUException
*/
public String verifyIdentityLink(AuthenticationSession session,
@@ -1057,6 +1061,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {
ByteArrayInputStream bais = new ByteArrayInputStream(mandate
.getMandate());
Document doc = DOMUtils.parseDocumentSimple(bais);
+ bais.close();
return doc.getDocumentElement();
}
@@ -1095,14 +1100,14 @@ public class AuthenticationServer implements MOAIDAuthConstants {
* <li>Stores authentication data in the authentication data store indexed
* by the SAML artifact</li>
* <li>Deletes authentication session</li>
- * <li>Returns the SAML artifact, encoded BASE64</li>
+ * <li><strike>Returns the SAML artifact, encoded BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)</li>
* </ul>
*
* @param sessionID session ID of the running authentication session
* @param xmlCreateXMLSignatureReadResponse String representation of the
* <code>&lt;CreateXMLSignatureResponse&gt;</code>
- * @return SAML artifact needed for retrieving authentication data, encoded
- * BASE64
+ * @return <strike>SAML artifact needed for retrieving authentication data, encoded
+ * BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)
* @throws BKUException
*/
public String verifyAuthenticationBlock(AuthenticationSession session,
@@ -1362,17 +1367,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {
/**
* Gets the foreign authentication data.<br>
* <ul>
- * <li>Creates authentication data</li>
+ * <li><strong>Creates authentication data</strong></li>
* <li>Creates a corresponding SAML artifact</li>
* <li>Stores authentication data in the authentication data store indexed
* by the SAML artifact</li>
* <li>Deletes authentication session</li>
- * <li>Returns the SAML artifact, encoded BASE64</li>
+ * <li><strike>Returns the SAML artifact, encoded BASE64</strike></li>
* </ul>
*
* @param sessionID session ID of the running authentication session
- * @return SAML artifact needed for retrieving authentication data, encoded
- * BASE64
+ * @return String "new Session"
*/
public String getForeignAuthenticationData(AuthenticationSession session)
throws AuthenticationException, BuildException, ParseException,
@@ -1381,46 +1385,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {
if (session == null)
throw new AuthenticationException("auth.10", new Object[]{
REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID});
-
- // // post processing of the infoboxes
- // Iterator iter = session.getInfoboxValidatorIterator();
- // boolean formpending = false;
- // if (iter != null) {
- // while (!formpending && iter.hasNext()) {
- // Vector infoboxValidatorVector = (Vector) iter.next();
- // String identifier = (String) infoboxValidatorVector.get(0);
- // String friendlyName = (String) infoboxValidatorVector.get(1);
- // InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector
- // .get(2);
- // InfoboxValidationResult infoboxValidationResult = null;
- // try {
- // infoboxValidationResult = infoboxvalidator.validate(session
- // .getIdentityLink().getSamlAssertion());
- // } catch (ValidateException e) {
- // Logger.error("Error validating " + identifier + " infobox:"
- // + e.getMessage());
- // throw new ValidateException("validator.44",
- // new Object[]{friendlyName});
- // }
- // if (!infoboxValidationResult.isValid()) {
- // Logger.info("Validation of " + identifier
- // + " infobox failed.");
- // throw new ValidateException("validator.40", new Object[]{
- // friendlyName,
- // infoboxValidationResult.getErrorMessage()});
- // }
- // String form = infoboxvalidator.getForm();
- // if (ParepUtils.isEmpty(form)) {
- // AddAdditionalSAMLAttributes(
- // session,
- // infoboxValidationResult.getExtendedSamlAttributes(),
- // identifier, friendlyName);
- // } else {
- // return "Redirect to Input Processor";
- // }
- // }
- // }
-
VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponse();
X509Certificate cert = session.getSignerCertificate();
vsresp.setX509certificate(cert);
@@ -1442,8 +1406,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 {
@@ -1749,10 +1713,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);
@@ -1772,7 +1732,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {
boolean globallyMandatory = false;
for (StorkAttribute currentGlobalAttribute : storkConfig.getStorkAttributes())
if (current.getName().equals(currentGlobalAttribute.getName())) {
- globallyMandatory = currentGlobalAttribute.isMandatory();
+ globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.isMandatory());
break;
}
@@ -1787,12 +1747,18 @@ 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);
attributeList.add(newAttribute);
+
+ // TODO[branch]: STORK AuthReq CPEPS acsURL "/PEPSConnector"
}
else//Process SignRequest locally with MOCCA
{
@@ -1808,6 +1774,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {
moasession.setSignedDoc(signedDoc);
acsURL = issuerValue + PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN;
+ // TODO[branch]: STORK AuthReq acsURL "/PEPSConnectorWithLocalSigning"
try {
AuthenticationSessionStoreage.storeSession(moasession);
} catch (MOADatabaseException e) {
@@ -1816,6 +1783,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:");
@@ -1880,6 +1848,17 @@ public class AuthenticationServer implements MOAIDAuthConstants {
//send
moasession.setStorkAuthnRequest(authnRequest);
+ // do PEPS-conform logging for easier evaluation
+ try {
+ // 2015-03-12 16:44:27.144#S-PEPS receives request from SP#spurl#spepsurl#spapp#spdomain#citizen country#qaa#msghash#msg_id id1#
+ Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS receives request from SP#" +
+ moasession.getPublicOAURLPrefix() + "#" + issuerValue + "#" + spApplication + "#" +
+ new URL(moasession.getPublicOAURLPrefix()).getHost() + "#" + moasession.getCcc() + "#" + oaParam.getQaaLevel() +
+ "#_hash_#" + moasession.getProcessInstanceId() + "#");
+ } catch (Exception e1) {
+ Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
+ }
+
AuthenticationSessionStoreage.changeSessionID(moasession, authnRequest.getSamlId());
@@ -1900,6 +1879,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {
StringWriter writer = new StringWriter();
template.merge(context, writer);
+ // TODO[branch]: SAML2 Form Submit to CPEPS, response to acsURL Servlet
+
resp.setContentType("text/html;charset=UTF-8");
resp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
@@ -1910,6 +1891,17 @@ public class AuthenticationServer implements MOAIDAuthConstants {
}
Logger.info("STORK AuthnRequest successfully successfully prepared for client with target location: " + authnRequest.getDestination());
+
+ // do PEPS-conform logging for easier evaluation
+ try {
+ // 2015-03-12 16:44:27.144#S-PEPS generates request to C-PEPS#spepsurl#cpepsurl#spapp#spdomain#citizen country#qaa#msghash#msg_id id1#id2#
+ Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS generates request to C-PEPS#" +
+ issuerValue + "#" + destination + "#" + spApplication + "#" +
+ new URL(moasession.getPublicOAURLPrefix()).getHost() + "#" + moasession.getCcc() + "#" + oaParam.getQaaLevel() +
+ "#_hash_#" + moasession.getProcessInstanceId() + "#" + authnRequest.getSamlId() + "#");
+ } catch (Exception e1) {
+ Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
+ }
}
private static String generateDssSignRequest(String text, String mimeType, String citizenCountry) {
@@ -1986,6 +1978,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {
} catch (Throwable e) {
throw new CertificateException(e);
+
+ } finally {
+ try {
+ is.close();
+
+ } catch (IOException e) {
+ Logger.warn("Close InputStream failed." , e);
+
+ }
+
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java
index fe35866b1..104cd8622 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java
@@ -45,7 +45,7 @@ public class AuthenticationSessionCleaner implements Runnable {
public static void start() {
// start the session cleanup thread
Thread sessionCleaner =
- new Thread(new AuthenticationSessionCleaner());
+ new Thread(new AuthenticationSessionCleaner(), "AuthenticationSessionCleaner");
sessionCleaner.setName("SessionCleaner");
sessionCleaner.setDaemon(true);
sessionCleaner.setPriority(Thread.MIN_PRIORITY);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
index db8b4dd80..5223a181d 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
@@ -149,7 +149,9 @@ public interface MOAIDAuthConstants {
Collections.unmodifiableMap(new HashMap<String, String>() {
private static final long serialVersionUID = 1L;
{
+ put("AT", "Other Countries");//"Workaround for PEPS Simulator"
put("BE", "Belgi&euml;/Belgique");
+ //put("CH", "Schweiz");
put("EE", "Eesti");
put("ES", "Espa&ntilde;a");
put("FI", "Suomi");
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java
index db36356c0..025c4c652 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java
@@ -147,13 +147,15 @@ public class MOAIDAuthInitializer {
.toString() }, ex);
}
}
-
+
// Initializes IAIKX509TrustManager logging
+ /*
String log4jConfigURL = System.getProperty("log4j.configuration");
Logger.info("Log4J Configuration: " + log4jConfigURL);
if (log4jConfigURL != null) {
IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL));
}
+ */
// Initializes the Axis secure socket factory for use in calling the
// MOA-SP web service
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
index 52488c3cb..cd751ce7f 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
@@ -43,6 +43,7 @@ import javax.xml.bind.Marshaller;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeQuery;
+import org.opensaml.saml2.core.AuthnStatement;
import org.opensaml.saml2.core.Response;
import org.opensaml.ws.soap.common.SOAPException;
import org.opensaml.xml.XMLObject;
@@ -214,7 +215,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
} else {
//build AuthenticationData from MOASession
- buildAuthDataFormMOASession(authdata, session, oaParam);
+ buildAuthDataFormMOASession(authdata, session, oaParam, protocolRequest);
}
@@ -271,12 +272,13 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
AssertionAttributeExtractor extractor =
new AssertionAttributeExtractor(intfResp);
- if (!extractor.containsAllRequiredAttributes()) {
+ if (!extractor.containsAllRequiredAttributes()) {
+ Logger.info("Received assertion does no contain a minimum set of attributes. Starting AttributeQuery process ...");
//collect attributes by using BackChannel communication
String endpoint = idp.getIDPAttributQueryServiceURL();
if (MiscUtil.isEmpty(endpoint)) {
- Logger.error("No AttributeQueryURL for interfederationIDP " + oaParam.getPublicURLPrefix());
- throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + oaParam.getPublicURLPrefix(), null);
+ Logger.error("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix());
+ throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix(), null);
}
//build attributQuery request
@@ -321,7 +323,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
//parse response information to authData
- buildAuthDataFormInterfederationResponse(authdata, session, extractor, oaParam);
+ buildAuthDataFormInterfederationResponse(authdata, session, extractor, oaParam, req);
} catch (SOAPException e) {
throw new BuildException("builder.06", null, e);
@@ -348,7 +350,8 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
AuthenticationData authData,
AuthenticationSession session,
AssertionAttributeExtractor extractor,
- IOAAuthParameters oaParam)
+ IOAAuthParameters oaParam,
+ IRequest req)
throws BuildException, AssertionAttributeExtractorExeption {
Logger.debug("Build AuthData from assertion starts ....");
@@ -358,14 +361,35 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
authData.setFamilyName(extractor.getSingleAttributeValue(PVPConstants.PRINCIPAL_NAME_NAME));
authData.setGivenName(extractor.getSingleAttributeValue(PVPConstants.GIVEN_NAME_NAME));
authData.setDateOfBirth(extractor.getSingleAttributeValue(PVPConstants.BIRTHDATE_NAME));
- authData.setBPKType(extractor.getSingleAttributeValue(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME));
authData.setCcc(extractor.getSingleAttributeValue(PVPConstants.EID_ISSUING_NATION_NAME));
authData.setBkuURL(extractor.getSingleAttributeValue(PVPConstants.EID_CCS_URL_NAME));
authData.setIdentificationValue(extractor.getSingleAttributeValue(PVPConstants.EID_SOURCE_PIN_NAME));
authData.setIdentificationType(extractor.getSingleAttributeValue(PVPConstants.EID_SOURCE_PIN_TYPE_NAME));
+
+ if (extractor.containsAttribute(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME)) {
+ String bpkType = extractor.getSingleAttributeValue(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME);
+ if (bpkType.startsWith(Constants.URN_PREFIX_CDID) &&
+ !bpkType.substring(Constants.URN_PREFIX_CDID.length(),
+ Constants.URN_PREFIX_CDID.length() + 1).equals("+")) {
+ Logger.warn("Receive uncorrect encoded bBKType attribute " + bpkType + " Starting attribute value correction ... ");
+ bpkType = Constants.URN_PREFIX_CDID + "+" + bpkType.substring(Constants.URN_PREFIX_CDID.length() + 1);
+
+ }
+
+ authData.setBPKType(bpkType);
+ }
+
if (extractor.containsAttribute(PVPConstants.BPK_NAME)) {
String pvpbPK = extractor.getSingleAttributeValue(PVPConstants.BPK_NAME);
+
+ if (pvpbPK.startsWith("bPK:")) {
+ Logger.warn("Attribute " + PVPConstants.BPK_NAME
+ + " contains a not standardize prefix! Staring attribute value correction process ...");
+ pvpbPK = pvpbPK.substring("bPK:".length());
+
+ }
+
String[] spitted = pvpbPK.split(":");
authData.setBPK(spitted[1]);
if (MiscUtil.isEmpty(authData.getBPKType())) {
@@ -513,7 +537,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
//build OA specific bPK/wbPK information
- buildOAspecificbPK(oaParam, authData,
+ buildOAspecificbPK(req, oaParam, authData,
authData.getIdentificationValue(),
authData.getIdentificationType());
@@ -521,7 +545,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
if (MiscUtil.isEmpty(authData.getBPK())) {
Logger.debug("Calcutlate bPK from baseID");
- buildOAspecificbPK(oaParam, authData,
+ buildOAspecificbPK(req, oaParam, authData,
authData.getIdentificationValue(),
authData.getIdentificationType());
@@ -536,7 +560,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
} else {
Logger.debug("Found PVP QAA level. QAA mapping process starts ... ");
- String mappedQAA = PVPtoSTORKMapper.getInstance().mapQAALevel(qaaLevel);
+ String mappedQAA = PVPtoSTORKMapper.getInstance().mapToQAALevel(qaaLevel);
if (MiscUtil.isNotEmpty(mappedQAA))
authData.setQAALevel(mappedQAA);
@@ -586,7 +610,8 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
if (extractor.containsAttribute(PVPConstants.EID_IDENTITY_LINK_NAME)) {
try {
InputStream idlStream = Base64Utils.decodeToStream(extractor.getSingleAttributeValue(PVPConstants.EID_IDENTITY_LINK_NAME), false);
- IdentityLink idl = new IdentityLinkAssertionParser(idlStream).parseIdentityLink();
+ IdentityLink idl = new IdentityLinkAssertionParser(idlStream).parseIdentityLink();
+ idlStream.close();
buildOAspecificIdentityLink(oaParam, authData, idl);
} catch (ParseException e) {
@@ -744,6 +769,12 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
}
+ //set PVP OU attribute
+ if (extractor.containsAttribute(PVPConstants.OU_NAME)) {
+ authData.setPvpAttribute_OU(extractor.getSingleAttributeValue(PVPConstants.OU_NAME));
+ Logger.debug("Found PVP 'OU' attribute in response -> " + authData.getPvpAttribute_OU());
+
+ }
//set STORK attributes
if (extractor.containsAttribute(PVPConstants.EID_STORK_TOKEN_NAME)) {
@@ -761,8 +792,19 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
authData.setSsoSession(true);
authData.setInterfederatedSSOSession(true);
- if (extractor.getFullAssertion().getConditions() != null && extractor.getFullAssertion().getConditions().getNotOnOrAfter() != null)
+ if (extractor.getFullAssertion().getAuthnStatements() != null
+ && extractor.getFullAssertion().getAuthnStatements().size() > 0) {
+ for (AuthnStatement el : extractor.getFullAssertion().getAuthnStatements()) {
+ if (el.getSessionNotOnOrAfter() != null) {
+ authData.setSsoSessionValidTo(el.getSessionNotOnOrAfter().toDate());
+ break;
+ }
+ }
+
+ } else {
authData.setSsoSessionValidTo(extractor.getFullAssertion().getConditions().getNotOnOrAfter().toDate());
+
+ }
//only for SAML1
if (PVPConstants.STORK_QAA_1_4.equals(authData.getQAALevel()))
@@ -805,7 +847,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
private static void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session,
- IOAAuthParameters oaParam) throws BuildException, ConfigurationException {
+ IOAAuthParameters oaParam, IRequest protocolRequest) throws BuildException, ConfigurationException {
IdentityLink identityLink = session.getIdentityLink();
@@ -864,7 +906,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
} catch (Exception e) {
- Logger.error("Failed to extract country code from certificate", e);
+ Logger.error("Failed to extract country code from certificate with message: " + e.getMessage());
}
@@ -919,7 +961,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
Logger.trace("Authenticated User is OW: " + mandate.getOWbPK());
} else {
- buildOAspecificbPK(oaParam, authData,
+ buildOAspecificbPK(protocolRequest, oaParam, authData,
identityLink.getIdentificationValue(),
identityLink.getIdentificationType());
@@ -951,7 +993,13 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
//resign IDL
IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
Element resignedilAssertion;
- resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion());
+
+ AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
+ if (config.isIdentityLinkResigning()) {
+ resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion(), config.getIdentityLinkResigningKey());
+ } else {
+ resignedilAssertion = businessServiceIdl.getSamlAssertion();
+ }
IdentityLinkAssertionParser resignedIDLParser = new IdentityLinkAssertionParser(resignedilAssertion);
IdentityLink resignedIDL = resignedIDLParser.parseIdentityLink();
@@ -963,7 +1011,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
}
- private static void buildOAspecificbPK(IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException {
+ private static void buildOAspecificbPK(IRequest protocolRequest, IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException {
if (oaParam.getBusinessService()) {
//since we have foreigner, wbPK is not calculated in BKU
@@ -984,9 +1032,15 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
if (baseIDType.equals(Constants.URN_PREFIX_BASEID)) {
// only compute bPK if online application is a public service and we have the Stammzahl
- String bpkBase64 = new BPKBuilder().buildBPK(baseID, oaParam.getTarget());
+ String target = null;
+ if (protocolRequest instanceof SAML1RequestImpl)
+ target = protocolRequest.getTarget();
+ else
+ target = oaParam.getTarget();
+
+ String bpkBase64 = new BPKBuilder().buildBPK(baseID, target);
authData.setBPK(bpkBase64);
- authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + oaParam.getTarget());
+ authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + target);
}
Logger.trace("Authenticate user with bPK " + authData.getBPK());
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 484fe1f9e..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
@@ -47,6 +47,15 @@ public class StartAuthenticationBuilder {
}
+ /**
+ * Depending on the selected citizen's country ({@code moasession.ccc}):
+ * <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>
+ * </ul>
+ *
+ * @return The IdentityLinkForm.
+ */
public String build(AuthenticationSession moasession, HttpServletRequest req,
HttpServletResponse resp) throws WrongParametersException, MOAIDException {
@@ -54,25 +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
- 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/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
index 26c22fb4a..76bf93249 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
@@ -304,6 +304,8 @@ public class AuthenticationSession implements Serializable {
private String authnContextClassRef;
// private String requestedProtocolURL = null;
+ private String processInstanceId;
+
public String getAuthnContextClassRef() {
return authnContextClassRef;
}
@@ -1110,6 +1112,22 @@ public class AuthenticationSession implements Serializable {
*/
public Date getSessionCreated() {
return sessionCreated;
- }
+ }
+
+ /**
+ * Returns the identifier of the process instance associated with this moaid session.
+ * @return The process instance id (may be {@code null} if no process has been created yet).
+ */
+ public String getProcessInstanceId() {
+ return processInstanceId;
+ }
+
+ /**
+ * Sets the process instance identifier in order to associate a certain process instance with this moaid session.
+ * @param processInstanceId The process instance id.
+ */
+ public void setProcessInstanceId(String processInstanceId) {
+ this.processInstanceId = processInstanceId;
+ }
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java
new file mode 100644
index 000000000..67ddd170a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java
@@ -0,0 +1,378 @@
+package at.gv.egovernment.moa.id.auth.modules;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.lang3.ArrayUtils;
+
+import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
+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.servlet.AuthServlet;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
+import at.gv.egovernment.moa.id.process.springweb.MoaIdTask;
+import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
+import at.gv.egovernment.moa.id.storage.IExceptionStore;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * 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}.
+ */
+public abstract class AbstractAuthServletTask extends MoaIdTask {
+
+ protected static final String ERROR_CODE_PARAM = "errorid";
+
+ protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown,
+ HttpServletRequest req, HttpServletResponse resp) {
+
+ if (null != errorMessage) {
+ Logger.error(errorMessage);
+ req.setAttribute("ErrorMessage", errorMessage);
+ }
+
+ if (null != exceptionThrown) {
+ if (null == errorMessage)
+ errorMessage = exceptionThrown.getMessage();
+ Logger.error(errorMessage, exceptionThrown);
+ req.setAttribute("ExceptionThrown", exceptionThrown);
+ }
+
+ if (Logger.isDebugEnabled()) {
+ req.setAttribute("LogLevel", "debug");
+ }
+
+
+ StatisticLogger logger = StatisticLogger.getInstance();
+ logger.logErrorOperation(exceptionThrown);
+
+
+ // forward this to errorpage-auth.jsp where the HTML error page is
+ // generated
+ ServletContext context = req.getServletContext();
+ RequestDispatcher dispatcher = context
+ .getRequestDispatcher("/errorpage-auth.jsp");
+ try {
+
+ resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
+
+ dispatcher.forward(req, resp);
+ } catch (ServletException e) {
+ Logger.error(e);
+ } catch (IOException e) {
+ Logger.error(e);
+ }
+ }
+
+ /**
+ * Handles an error. <br>>
+ * <ul>
+ * <li>Logs the error</li>
+ * <li>Places error message and exception thrown into the request as request
+ * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li>
+ * <li>Sets HTTP status 500 (internal server error)</li>
+ * </ul>
+ *
+ * @param errorMessage
+ * error message
+ * @param exceptionThrown
+ * exception thrown
+ * @param req
+ * servlet request
+ * @param resp
+ * servlet response
+ */
+ protected void handleError(String errorMessage, Throwable exceptionThrown,
+ HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
+
+ if (null != errorMessage) {
+ Logger.error(errorMessage);
+ req.setAttribute("ErrorMessage", errorMessage);
+ }
+
+ if (null != exceptionThrown) {
+ if (null == errorMessage)
+ errorMessage = exceptionThrown.getMessage();
+ Logger.error(errorMessage, exceptionThrown);
+ req.setAttribute("ExceptionThrown", exceptionThrown);
+ }
+
+ if (Logger.isDebugEnabled()) {
+ req.setAttribute("LogLevel", "debug");
+ }
+
+ if (!(exceptionThrown instanceof MOAIDException)) {
+ Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
+
+ }
+
+ IExceptionStore store = DBExceptionStoreImpl.getStore();
+ String id = store.storeException(exceptionThrown);
+
+ if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
+
+ String redirectURL = null;
+
+ redirectURL = ServletUtils.getBaseUrl(req);
+ redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id
+ + "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID;
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ return;
+
+ } else {
+
+ //Exception can not be stored in database
+ handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
+ }
+ }
+
+ /**
+ * Handles a <code>WrongParametersException</code>.
+ *
+ * @param req
+ * servlet request
+ * @param resp
+ * servlet response
+ */
+ protected void handleWrongParameters(WrongParametersException ex,
+ HttpServletRequest req, HttpServletResponse resp) {
+ Logger.error(ex.toString());
+ req.setAttribute("WrongParameters", ex.getMessage());
+
+ // forward this to errorpage-auth.jsp where the HTML error page is
+ // generated
+ ServletContext context = req.getServletContext();
+ RequestDispatcher dispatcher = context
+ .getRequestDispatcher("/errorpage-auth.jsp");
+ try {
+ setNoCachingHeaders(resp);
+ dispatcher.forward(req, resp);
+ } catch (ServletException e) {
+ Logger.error(e);
+ } catch (IOException e) {
+ Logger.error(e);
+ }
+ }
+
+ /**
+ * Logs all servlet parameters for debugging purposes.
+ */
+ protected void logParameters(HttpServletRequest req) {
+ for (Enumeration params = req.getParameterNames(); params
+ .hasMoreElements();) {
+ String parname = (String) params.nextElement();
+ Logger.debug("Parameter " + parname + req.getParameter(parname));
+ }
+ }
+
+ /**
+ * Parses the request input stream for parameters, assuming parameters are
+ * encoded UTF-8 (no standard exists how browsers should encode them).
+ *
+ * @param req
+ * servlet request
+ *
+ * @return mapping parameter name -> value
+ *
+ * @throws IOException
+ * if parsing request parameters fails.
+ *
+ * @throws FileUploadException
+ * if parsing request parameters fails.
+ */
+ protected Map<String, String> getParameters(HttpServletRequest req) throws IOException,
+ FileUploadException {
+
+ Map<String, String> parameters = new HashMap<String, String>();
+
+ if (ServletFileUpload.isMultipartContent(req)) {
+ // request is encoded as mulitpart/form-data
+ FileItemFactory factory = new DiskFileItemFactory();
+ ServletFileUpload upload = null;
+ upload = new ServletFileUpload(factory);
+ List items = null;
+ items = upload.parseRequest(req);
+ for (int i = 0; i < items.size(); i++) {
+ FileItem item = (FileItem) items.get(i);
+ if (item.isFormField()) {
+ // Process only form fields - no file upload items
+ String logString = item.getString("UTF-8");
+
+ // TODO use RegExp
+ String startS = "<pr:Identification><pr:Value>";
+ String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>";
+ String logWithMaskedBaseid = logString;
+ int start = logString.indexOf(startS);
+ if (start > -1) {
+ int end = logString.indexOf(endS);
+ if (end > -1) {
+ logWithMaskedBaseid = logString.substring(0, start);
+ logWithMaskedBaseid += startS;
+ logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx";
+ logWithMaskedBaseid += logString.substring(end,
+ logString.length());
+ }
+ }
+ parameters
+ .put(item.getFieldName(), item.getString("UTF-8"));
+ Logger.debug("Processed multipart/form-data request parameter: \nName: "
+ + item.getFieldName()
+ + "\nValue: "
+ + logWithMaskedBaseid);
+ }
+ }
+ }
+
+ else {
+ // request is encoded as application/x-www-urlencoded
+ // [tknall]: we must not consume request body input stream once servlet-api request parameters have been accessed
+
+ /*
+ InputStream in = req.getInputStream();
+
+ String paramName;
+ String paramValueURLEncoded;
+ do {
+ paramName = new String(readBytesUpTo(in, '='));
+ if (paramName.length() > 0) {
+ paramValueURLEncoded = readBytesUpTo(in, '&');
+ String paramValue = URLDecoder.decode(paramValueURLEncoded,
+ "UTF-8");
+ parameters.put(paramName, paramValue);
+ }
+ } while (paramName.length() > 0);
+ in.close();
+ */
+
+ Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator();
+ while (requestParamIt.hasNext()) {
+ Entry<String, String[]> entry = requestParamIt.next();
+ String key = entry.getKey();
+ String[] values = entry.getValue();
+ // take the last value from the value array since the legacy code above also does it this way
+ parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]);
+ }
+
+ }
+
+ return parameters;
+ }
+
+ /**
+ * Reads bytes up to a delimiter, consuming the delimiter.
+ *
+ * @param in
+ * input stream
+ * @param delimiter
+ * delimiter character
+ * @return String constructed from the read bytes
+ * @throws IOException
+ */
+ protected String readBytesUpTo(InputStream in, char delimiter)
+ throws IOException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ boolean done = false;
+ int b;
+ while (!done && (b = in.read()) >= 0) {
+ if (b == delimiter)
+ done = true;
+ else
+ bout.write(b);
+ }
+ return bout.toString();
+ }
+
+ /**
+ * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
+ *
+ * @param resp
+ * The HttpServletResponse.
+ */
+ public void setNoCachingHeaders(HttpServletResponse resp) {
+ resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
+ }
+
+ /**
+ * Adds a parameter to a URL.
+ *
+ * @param url
+ * the URL
+ * @param paramname
+ * parameter name
+ * @param paramvalue
+ * parameter value
+ * @return the URL with parameter added
+ */
+ protected static String addURLParameter(String url, String paramname,
+ String paramvalue) {
+ String param = paramname + "=" + paramvalue;
+ if (url.indexOf("?") < 0)
+ return url + "?" + param;
+ else
+ return url + "&" + param;
+ }
+
+ /**
+ * Checks if HTTP requests are allowed
+ *
+ * @param authURL
+ * requestURL
+ * @throws AuthenticationException
+ * if HTTP requests are not allowed
+ * @throws ConfigurationException
+ */
+ protected void checkIfHTTPisAllowed(String authURL)
+ throws AuthenticationException, ConfigurationException {
+ // check if HTTP Connection may be allowed (through
+ // FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
+
+ //Removed from MOA-ID 2.0 config
+// String boolStr = AuthConfigurationProvider
+// .getInstance()
+// .getGenericConfigurationParameter(
+// AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
+ if ((!authURL.startsWith("https:"))
+ //&& (false == BoolUtils.valueOf(boolStr))
+ )
+ throw new AuthenticationException("auth.07", new Object[] { authURL
+ + "*" });
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java
new file mode 100644
index 000000000..8983403d8
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java
@@ -0,0 +1,42 @@
+package at.gv.egovernment.moa.id.auth.modules;
+
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.model.ProcessDefinition;
+
+/**
+ * Provides metadata of a certain module. Uses for module discovery and process selection.
+ */
+public interface AuthModule {
+
+ /**
+ * Returns the priority of the module. The priority defines the order of the respective module within the chain of
+ * discovered modules. Higher priorized modules are asked before lower priorized modules for a process that they can
+ * handle.
+ * <p/>
+ * Internal default modules are priorized neutral ({@code 0}. Use a higher priority ({@code 1...Integer.MAX_VALUE})
+ * in order to have your module(s) priorized or a lower priority ({@code Integer.MIN_VALUE...-1}) in order to put
+ * your modules behind default modules.
+ *
+ * @return the priority of the module.
+ */
+ int getPriority();
+
+ /**
+ * Selects a process (description), referenced by its unique id, which is able to perform authentication with the
+ * given {@link ExecutionContext}. Returns {@code null} if no appropriate process (description) was available within
+ * this module.
+ *
+ * @param context
+ * an ExecutionContext for a process.
+ * @return the process-ID of a process which is able to work with the given ExecutionContext, or {@code null}.
+ */
+ String selectProcess(ExecutionContext context);
+
+ /**
+ * Returns the an Array of {@link ProcessDefinition}s of the processes included in this module.
+ *
+ * @return an array of resource uris of the processes included in this module.
+ */
+ String[] getProcessDefinitions();
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java
new file mode 100644
index 000000000..3e9f4cf14
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Federal Chancellery Austria
+ * MOA-ID has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egovernment.moa.id.auth.modules;
+
+import at.gv.egovernment.moa.id.process.ProcessExecutionException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class TaskExecutionException extends ProcessExecutionException {
+
+ private static final long serialVersionUID = 1L;
+ Throwable originalException = null;
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public TaskExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ originalException = cause;
+
+ }
+
+ /**
+ * Get the original internal exception from task
+ *
+ * @return the originalException
+ */
+ public Throwable getOriginalException() {
+ return originalException;
+ }
+
+
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java
new file mode 100644
index 000000000..8ae4a9999
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java
@@ -0,0 +1,28 @@
+package at.gv.egovernment.moa.id.auth.modules.internal;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egovernment.moa.id.auth.modules.AuthModule;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * Module descriptor
+ */
+public class DefaultAuthModuleImpl implements AuthModule {
+
+ @Override
+ public int getPriority() {
+ return 0;
+ }
+
+ @Override
+ public String selectProcess(ExecutionContext context) {
+ return StringUtils.isBlank((String) context.get("ccc")) ? "DefaultAuthentication" : null;
+ }
+
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml" };
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java
new file mode 100644
index 000000000..ed3089a41
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java
@@ -0,0 +1,103 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.BooleanUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilderCertificate;
+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.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.<p/>
+ * In detail:
+ * <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>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <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}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class CertificateReadRequestTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ // TODO[branch]: Foreign citizen or mandate mode; respond with IRR for certificates, dataURL = "/VerifyCertificate"
+ Logger.info("Send InfoboxReadRequest to BKU to get signer certificate.");
+
+ setNoCachingHeaders(resp);
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("CertificateReadRequestTask", PARAM_SESSIONID, "auth.12");
+ }
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ boolean useMandate = session.getUseMandate();
+ boolean identityLinkAvailable = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkAvailable"));
+
+ if (!identityLinkAvailable && useMandate) {
+ Logger.error("Online-Mandate Mode for foreign citizencs not supported.");
+ throw new AuthenticationException("auth.13", null);
+ }
+
+ // change MOASessionID
+ AuthenticationSessionStoreage.changeSessionID(session);
+
+ // create the InfoboxReadRequest to get the certificate
+ String infoboxReadRequest = new InfoboxReadRequestBuilderCertificate().build(true);
+
+ // build dataurl (to the VerifyCertificateSerlvet)
+ String dataurl = new DataURLBuilder().buildDataURL(session.getAuthURL(), REQ_VERIFY_CERTIFICATE,
+ session.getSessionID());
+
+ ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest,
+ AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
+
+ } catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (IOException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java
new file mode 100644
index 000000000..ee6f0d5a4
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java
@@ -0,0 +1,120 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.ObjectUtils;
+
+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.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import at.gv.egovernment.moa.util.StringUtils;
+
+/**
+ * Creates a http form including an embedded {@code InfoBoxReadRequest} for reading the identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</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 {@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>
+ * <li>The identity link form via HttpServletResponse.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case of STORK authentication
+ * <ul>
+ * <li>Creates STORK auth SAML request.</li>
+ * <li>Creates and returns a form for submitting the SAML request to the CPEPS (post binding).</li>
+ * <li>Returns the form via HttpServletResponse.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class CreateIdentityLinkFormTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ String moasessionid = StringEscapeUtils.escapeHtml(ObjectUtils.defaultIfNull(req.getParameter(PARAM_SESSIONID), (String) executionContext.get(PARAM_SESSIONID)));
+ AuthenticationSession moasession = null;
+ try {
+
+ if (MiscUtil.isEmpty(moasessionid)) {
+ Logger.warn("MOASessionID is empty.");
+ throw new MOAIDException("auth.18", new Object[] {});
+ }
+
+ try {
+ moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ AuthenticationSessionStoreage.changeSessionID(moasession);
+ executionContext.remove(PARAM_SESSIONID);
+
+ } catch (MOADatabaseException e) {
+ Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database");
+ throw new MOAIDException("init.04", new Object[] { moasessionid });
+
+ } catch (Throwable e) {
+ Logger.info("No HTTP Session found!");
+ throw new MOAIDException("auth.18", new Object[] {});
+ }
+
+ StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
+ String getIdentityLinkForm = startauth.build(moasession, req, resp);
+
+ if (!StringUtils.isEmpty(getIdentityLinkForm)) {
+ resp.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.print(getIdentityLinkForm);
+ out.flush();
+ Logger.debug("Finished GET " + GenerateIFrameTemplateServlet.class);
+ }
+
+ } catch (WrongParametersException ex) {
+// handleWrongParameters(ex, req, resp);
+ throw new TaskExecutionException(ex.getMessage(), ex);
+ }
+
+ catch (MOAIDException ex) {
+// handleError(null, ex, req, resp, pendingRequestID);
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (Exception e) {
+ Logger.error("CreateIdentityLinkFormTask has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java
new file mode 100644
index 000000000..6bf68e2eb
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java
@@ -0,0 +1,185 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.w3c.dom.Element;
+
+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.CreateXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+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.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.client.SZRGWClientException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;
+
+/**
+ * Evaluates the {@code CreateXMLSignatureResponse}, extracts signature and certificate and asks the SZR Gateway for an identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</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>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <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>
+ * <li>Identity link, QAA level 4 and foreigner flag put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetForeignIDServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class GetForeignIDTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ Logger.debug("POST GetForeignIDServlet");
+
+ setNoCachingHeaders(resp);
+
+ Map<String, String> parameters;
+
+ try {
+ parameters = getParameters(req);
+
+ } catch (FileUploadException | IOException e) {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
+ }
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+ String pendingRequestID = null;
+ String redirectURL = null;
+ AuthenticationSession session = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("GetForeignID", PARAM_SESSIONID, "auth.12");
+ }
+ String xmlCreateXMLSignatureResponse = (String) parameters.get(PARAM_XMLRESPONSE);
+ if (!ParamValidatorUtils.isValidXMLDocument(xmlCreateXMLSignatureResponse)) {
+ throw new WrongParametersException("GetForeignID", PARAM_XMLRESPONSE, "auth.12");
+ }
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+ session = AuthenticationServer.getSession(sessionID);
+
+ // change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.debug(xmlCreateXMLSignatureResponse);
+
+ CreateXMLSignatureResponse csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureResponse)
+ .parseResponseDsig();
+
+ try {
+ String serializedAssertion = DOMUtils.serializeNode(csresp.getDsigSignature());
+ session.setAuthBlock(serializedAssertion);
+
+ } catch (TransformerException e) {
+ throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
+
+ } catch (IOException e) {
+ throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
+
+ }
+
+ Element signature = csresp.getDsigSignature();
+
+ try {
+ session.setSignerCertificate(AuthenticationServer.getCertificateFromXML(signature));
+ } catch (CertificateException e) {
+ Logger.error("Could not extract certificate from CreateXMLSignatureResponse");
+ throw new MOAIDException("auth.14", null);
+ }
+
+ // make SZR request to the identity link
+ CreateIdentityLinkResponse response = AuthenticationServer.getInstance().getIdentityLink(signature);
+
+ if (null != response.getErrorResponse()) {
+ // TODO fix exception parameter
+ throw new SZRGWClientException("service.08", (String) response.getErrorResponse().getErrorCode(),
+ (String) response.getErrorResponse().getInfo());
+ } else {
+ IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(new ByteArrayInputStream(
+ response.getIdentityLink()));
+ IdentityLink identitylink = ilParser.parseIdentityLink();
+ session.setIdentityLink(identitylink);
+
+ // set QAA Level four in case of card authentifcation
+ session.setQAALevel(PVPConstants.STORK_QAA_1_4);
+
+ AuthenticationServer.getInstance().getForeignAuthenticationData(session);
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Changed MOASession " + sessionID + " to Session " + newMOASessionID);
+ Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
+
+ redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID),
+ newMOASessionID);
+ redirectURL = resp.encodeRedirectURL(redirectURL);
+
+ // TODO[branch]: Final step back to /dispatcher
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("Session store error", null);
+ }
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+
+ } catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (Exception e) {
+ Logger.error("GetForeignIDServlet has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java
new file mode 100644
index 000000000..4ff5672bd
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java
@@ -0,0 +1,183 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+import iaik.pki.PKIException;
+
+import java.security.GeneralSecurityException;
+import java.util.List;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang.StringEscapeUtils;
+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.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.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+/**
+ * Retrieves a mandate from the online mandate issuing service.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Retrieves the mandate referenced within the moa session from the online (external) mandate issuing service.</li>
+ * <li>Verifies the mandate.</li>
+ * <li>Puts mandate into moa session.</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Mandate put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetMISSessionIDServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class GetMISSessionIDTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ Logger.debug("POST GetMISSessionIDServlet");
+
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+
+ AuthenticationSession session = null;
+ String pendingRequestID = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyCertificate",
+ PARAM_SESSIONID, "auth.12");
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ String misSessionID = session.getMISSessionID();
+
+ AuthConfigurationProvider authConf = AuthConfigurationProvider
+ .getInstance();
+ ConnectionParameter connectionParameters = authConf
+ .getOnlineMandatesConnectionParameter();
+ SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(
+ AuthConfigurationProvider.getInstance(),
+ connectionParameters);
+
+ List<MISMandate> list = MISSimpleClient.sendGetMandatesRequest(
+ connectionParameters.getUrl(), misSessionID, sslFactory);
+
+ if (list == null || list.size() == 0) {
+ Logger.error("Keine Vollmacht gefunden.");
+ throw new AuthenticationException("auth.15", null);
+ }
+
+ // for now: list contains only one element
+ MISMandate mandate = (MISMandate) list.get(0);
+
+ // TODO[tlenz]: UTF-8 ?
+ String sMandate = new String(mandate.getMandate());
+ if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {
+ Logger.error("Mandate is empty.");
+ throw new AuthenticationException("auth.15",
+ new Object[] { GET_MIS_SESSIONID });
+ }
+
+ //check if it is a parsable XML
+ byte[] byteMandate = mandate.getMandate();
+ // TODO[tlenz]: UTF-8 ?
+ String stringMandate = new String(byteMandate);
+ DOMUtils.parseDocument(stringMandate, false,
+ null, null).getDocumentElement();
+
+ // extract RepresentationType
+ AuthenticationServer.getInstance().verifyMandate(session, mandate);
+
+ session.setMISMandate(mandate);
+ session.setAuthenticatedUsed(false);
+ session.setAuthenticated(true);
+
+ //set QAA Level four in case of card authentifcation
+ session.setQAALevel(PVPConstants.STORK_QAA_1_4);
+
+ String oldsessionID = session.getSessionID();
+
+ //Session is implicite stored in changeSessionID!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Changed MOASession " + oldsessionID + " to Session " + newMOASessionID);
+ Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
+
+ String redirectURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(),
+ session.getAction(), pendingRequestID), newMOASessionID);
+ redirectURL = resp.encodeRedirectURL(redirectURL);
+
+ // TODO[branch]: Final step back to /dispatcher
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ } catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (GeneralSecurityException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (PKIException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (SAXException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (ParserConfigurationException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (Exception e) {
+ Logger.error("MISMandateValidation has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java
new file mode 100644
index 000000000..3ae35bc24
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java
@@ -0,0 +1,104 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+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 at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+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.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+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.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Creates {@code CreateXMLSignatureRequest} for auth block signature.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Creates {@code CreateXMLSignatureRequest} for auth block signature.</li>
+ * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code /VerifyAuthBlock}</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <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}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class PrepareAuthBlockSignatureTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
+
+ Logger.debug("Process IdentityLink");
+
+ setNoCachingHeaders(resp);
+
+ String pendingRequestID = null;
+
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
+ }
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ // change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Normal");
+
+ // TODO[branch]: Default behaviour; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
+
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ session.getPublicOAURLPrefix());
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
+
+ String createXMLSignatureRequest = AuthenticationServer.getInstance()
+ .getCreateXMLSignatureRequestAuthBlockOrRedirect(session, authConf, oaParam);
+
+ AuthenticationSessionStoreage.storeSession(session);
+
+ ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session,
+ createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT,
+ "VerifyIdentityLink");
+
+ } catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (Exception e) {
+ Logger.error("IdentityLinkValidation has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java
new file mode 100644
index 000000000..64dcb0f41
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java
@@ -0,0 +1,250 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+import iaik.pki.PKIException;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.w3c.dom.Element;
+
+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.MISSimpleClientException;
+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.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+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.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSessionId;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+/**
+ * Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</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 {@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>
+ * <li>Authentication data put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case of mandate mode
+ * <ul>
+ * <li>Creates a mandate session at the external mandate issuing service.</li>
+ * <li>Redirects the user's browser to the online mandate issuing service GUI.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet
+
+ Logger.debug("POST VerifyAuthenticationBlock");
+
+ String pendingRequestID = null;
+
+ Map<String, String> parameters;
+ try
+ {
+ parameters = getParameters(req);
+
+ } catch (FileUploadException | IOException e)
+ {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
+ }
+
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+ String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ String redirectURL = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
+ if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE, "auth.12");
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ String authenticatedMOASessionId = AuthenticationServer.getInstance().verifyAuthenticationBlock(session, createXMLSignatureResponse);
+
+ if (authenticatedMOASessionId == null) {
+ //mandate Mode
+
+ AuthConfigurationProvider authConf= AuthConfigurationProvider.getInstance();
+ ConnectionParameter connectionParameters = authConf.getOnlineMandatesConnectionParameter();
+ SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters);
+
+ // get identitity link as byte[]
+ Element elem = session.getIdentityLink().getSamlAssertion();
+ String s = DOMUtils.serializeNode(elem);
+
+ //System.out.println("IDL: " + s);
+
+ byte[] idl = s.getBytes("UTF-8");
+
+ // redirect url
+ // build redirect(to the GetMISSessionIdSerlvet)
+
+ //change MOASessionID before MIS request
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ redirectURL =
+ new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ GET_MIS_SESSIONID,
+ newMOASessionID);
+
+ String oaURL = session.getOAURLRequested();
+ OAAuthParameter oaParam = authConf.getOnlineApplicationParameter(oaURL);
+ List<String> profiles = oaParam.getMandateProfiles();
+
+ if (profiles == null) {
+ Logger.error("No Mandate/Profile for OA configured.");
+ throw new AuthenticationException("config.21", new Object[] { GET_MIS_SESSIONID});
+ }
+
+ String oaFriendlyName = oaParam.getFriendlyName();
+ String mandateReferenceValue = session.getMandateReferenceValue();
+ byte[] cert = session.getEncodedSignerCertificate();
+ byte[] authBlock = session.getAuthBlock().getBytes("UTF-8");
+
+ //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_+session.getDomainIdentifier();
+
+ } else {
+ targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
+ }
+
+ MISSessionId misSessionID = MISSimpleClient.sendSessionIdRequest(
+ connectionParameters.getUrl(),
+ idl,
+ cert,
+ oaFriendlyName,
+ redirectURL,
+ mandateReferenceValue,
+ profiles,
+ targetType,
+ authBlock,
+ sslFactory);
+
+ if (misSessionID == null) {
+ Logger.error("Fehler bei Anfrage an Vollmachten Service. MIS Session ID ist null.");
+ throw new MISSimpleClientException("Fehler bei Anfrage an Vollmachten Service.");
+ }
+
+ String redirectMISGUI = misSessionID.getRedirectURL();
+ session.setMISSessionID(misSessionID.getSessiondId());
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("Session store error", null);
+ }
+
+ // TODO[branch]: Mandate; redirect to MIS website; website redirects back to "/GetMISSessionID"
+
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectMISGUI);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+ else {
+ // TODO[branch]: Final step back to /dispatcher
+ redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID), authenticatedMOASessionId);
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ }
+
+ }
+
+ catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (GeneralSecurityException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (PKIException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (TransformerException e) {
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ } catch (Exception e) {
+ Logger.error("AuthBlockValidation has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java
new file mode 100644
index 000000000..607641532
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java
@@ -0,0 +1,163 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.spss.util.CertificateUtils;
+
+/**
+ * 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 {@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>
+ * <li>Updates moa session.</li>
+ * <li>Responds with {@code CreateXMLSignatureRequest}.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <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}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyCertificateTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet
+
+ Logger.debug("POST VerifyCertificateServlet");
+
+ Map<String, String> parameters;
+ try
+ {
+ parameters = getParameters(req);
+ } catch (FileUploadException | IOException e)
+ {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
+ }
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+
+ AuthenticationSession session = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyCertificate", PARAM_SESSIONID, "auth.12");
+
+ session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ X509Certificate cert = AuthenticationServer.getInstance().getCertificate(sessionID, parameters);
+ if (cert == null) {
+ Logger.error("Certificate could not be read.");
+ throw new AuthenticationException("auth.14", null);
+ }
+
+ boolean useMandate = session.getUseMandate();
+
+ if (useMandate) {
+
+ // verify certificate for OrganWalter
+ String createXMLSignatureRequestOrRedirect = AuthenticationServer.getInstance().verifyCertificate(session, cert);
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("session store error", null);
+ }
+
+ // TODO[branch]: Mandate; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
+ ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
+
+ }
+ else {
+
+
+ String countrycode = CertificateUtils.getIssuerCountry(cert);
+ if (countrycode != null) {
+ if (countrycode.compareToIgnoreCase("AT") == 0) {
+ Logger.error("Certificate issuer country code is \"AT\". Login not support in foreign identities mode.");
+ throw new AuthenticationException("auth.22", null);
+ }
+ }
+
+ // Foreign Identities Modus
+ String createXMLSignatureRequest = AuthenticationServer.getInstance().createXMLSignatureRequestForeignID(session, cert);
+ // build dataurl (to the GetForeignIDSerlvet)
+ String dataurl =
+ new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ REQ_GET_FOREIGN_ID,
+ session.getSessionID());
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("session store error", null);
+ }
+
+ // TODO[branch]: Foreign citizen; respond with CXSR for authblock signature, dataURL "/GetForeignID"
+ ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
+
+ Logger.debug("Send CreateXMLSignatureRequest to BKU");
+ }
+ }
+ catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (Exception e) {
+ Logger.error("CertificateValidation has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java
new file mode 100644
index 000000000..44557453a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java
@@ -0,0 +1,102 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+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.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Verifies the identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</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 identityLinkAvailable} into {@code ExecutionContext}.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <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 identityLinkAvailable} into {@code ExecutionContext}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyIdentityLinkTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws TaskExecutionException {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
+
+ Logger.debug("POST VerifyIdentityLink");
+
+ setNoCachingHeaders(resp);
+
+ Map<String, String> parameters;
+
+ try {
+ parameters = getParameters(req);
+ } catch (Exception e) {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
+ }
+
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
+ }
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ boolean identityLinkAvailable = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
+ AuthenticationSessionStoreage.storeSession(session);
+
+ executionContext.put("identityLinkAvailable", identityLinkAvailable);
+
+ } catch (ParseException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (MOAIDException ex) {
+ throw new TaskExecutionException(ex.getMessage(), ex);
+
+ } catch (Exception e) {
+ Logger.error("IdentityLinkValidation has an interal Error.", e);
+ throw new TaskExecutionException(e.getMessage(), e);
+
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java
new file mode 100644
index 000000000..9c950366c
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java
@@ -0,0 +1,149 @@
+package at.gv.egovernment.moa.id.auth.modules.registration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.Resource;
+
+import at.gv.egovernment.moa.id.auth.modules.AuthModule;
+import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException;
+import at.gv.egovernment.moa.id.process.ProcessEngine;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * This class handles registering modules. The modules are detected either with
+ * the ServiceLoader mechanism or via Spring. All detected modules are ranked
+ * according to their priority.
+ */
+public class ModuleRegistration {
+
+ private static ModuleRegistration instance = new ModuleRegistration();
+
+ private List<AuthModule> priorizedModules = new ArrayList<>();
+
+ @Autowired
+ private ApplicationContext ctx;
+
+ @Autowired
+ private ProcessEngine processEngine;
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ public static ModuleRegistration getInstance() {
+ return instance;
+ }
+
+ private ModuleRegistration() {
+ }
+
+ @PostConstruct
+ private void init() {
+ // load modules via the ServiceLoader
+ initServiceLoaderModules();
+
+ // load modules via Spring
+ initSpringModules();
+
+ // order modules according to their priority
+ sortModules();
+ }
+
+ /**
+ * Discovers modules which use the ServiceLoader mechanism.
+ */
+ private void initServiceLoaderModules() {
+ log.info("Looking for auth modules.");
+ ServiceLoader<AuthModule> loader = ServiceLoader.load(AuthModule.class);
+ Iterator<AuthModule> modules = loader.iterator();
+ while (modules.hasNext()) {
+ AuthModule module = modules.next();
+ log.info("Detected module {}", module.getClass().getName());
+ registerModuleProcessDefinitions(module);
+ priorizedModules.add(module);
+ }
+ }
+
+ /**
+ * Discovers modules which use Spring.
+ */
+ private void initSpringModules() {
+ log.debug("Discovering Spring modules.");
+ Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class);
+ for (AuthModule module : modules.values()) {
+ registerModuleProcessDefinitions(module);
+ priorizedModules.add(module);
+ }
+ }
+
+ /**
+ * Registers the resource uris for the module.
+ *
+ * @param module
+ * the module.
+ */
+ private void registerModuleProcessDefinitions(AuthModule module) {
+ for (String uri : module.getProcessDefinitions()) {
+ Resource resource = ctx.getResource(uri);
+ if (resource.isReadable()) {
+ log.info("Registering process definition '{}'.", uri);
+ try (InputStream processDefinitionInputStream = resource.getInputStream()) {
+ processEngine.registerProcessDefinition(processDefinitionInputStream);
+ } catch (IOException e) {
+ log.error("Process definition '{}' could NOT be read.", uri, e);
+ } catch (ProcessDefinitionParserException e) {
+ log.error("Error while parsing process definition '{}'", uri, e);
+ }
+ } else {
+ log.error("Process definition '{}' cannot be read.", uri);
+ }
+ }
+ }
+
+ /**
+ * Order the modules in descending order according to their priority.
+ */
+ private void sortModules() {
+ Collections.sort(priorizedModules, new Comparator<AuthModule>() {
+ @Override
+ public int compare(AuthModule thisAuthModule, AuthModule otherAuthModule) {
+ int thisOrder = thisAuthModule.getPriority();
+ int otherOrder = otherAuthModule.getPriority();
+ return (thisOrder < otherOrder ? 1 : (thisOrder == otherOrder ? 0 : -1));
+ }
+ });
+ }
+
+ /**
+ * Returns the process description id of the first process, in the highest ranked
+ * module, which is able to work with the given execution context.
+ *
+ * @param context
+ * the {@link ExecutionContext}.
+ * @return the process id or {@code null}
+ */
+ public String selectProcess(ExecutionContext context) {
+ for (AuthModule module : priorizedModules) {
+ String id = module.selectProcess(context);
+ if (StringUtils.isNotEmpty(id)) {
+ log.debug("Process with id '{}' selected, for context '{}'.", id, context);
+ return id;
+ }
+ }
+ log.info("No process is able to handle context '{}'.", context);
+ return null;
+ }
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java
index e2802c1d2..a5783bfb7 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java
@@ -106,7 +106,7 @@ public class IdentityLinkAssertionParser {
+ PDATA
+ "Person";
/** Xpath expression to the PersonData GivenName element */
- private static final String PERSON_GIVEN_NAME_XPATH =
+ public static final String PERSON_GIVEN_NAME_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
@@ -114,7 +114,7 @@ public class IdentityLinkAssertionParser {
+ PDATA
+ "GivenName";
/** Xpath expression to the PersonData FamilyName element */
- private static final String PERSON_FAMILY_NAME_XPATH =
+ public static final String PERSON_FAMILY_NAME_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
@@ -122,7 +122,7 @@ public class IdentityLinkAssertionParser {
+ PDATA
+ "FamilyName";
/** Xpath expression to the PersonData DateOfBirth element */
- private static final String PERSON_DATE_OF_BIRTH_XPATH =
+ public static final String PERSON_DATE_OF_BIRTH_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java
index 1bc3702e4..f538d2d12 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java
@@ -132,12 +132,13 @@ public class StartAuthentificationParameterParser implements MOAIDAuthConstants{
String targetFriendlyNameConfig = oaParam.getTargetFriendlyName();
if (StringUtils.isEmpty(targetConfig)
-// || (module.equals(SAML1Protocol.PATH) &&
-// !StringUtils.isEmpty(target))
+ || (module.equals(SAML1Protocol.PATH) &&
+ !StringUtils.isEmpty(target))
) {
- // no target attribut is given in OA config
- // target is used from request
- // check parameter
+ //INFO: ONLY SAML1 legacy mode
+ // if SAML1 is used and target attribute is given in request
+ // use requested target
+ // check target parameter
if (!ParamValidatorUtils.isValidTarget(target)) {
Logger.error("Selected target is invalid. Using target: " + target);
throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12");
@@ -211,8 +212,8 @@ public class StartAuthentificationParameterParser implements MOAIDAuthConstants{
authURL = authURL.concat(":" + req.getServerPort());
}
authURL = authURL.concat(req.getContextPath() + "/");
-
- if (!authURL.startsWith("https:"))
+
+ if (!authURL.startsWith("https:") && !AuthConfigurationProvider.getInstance().isHTTPAuthAllowed())
throw new AuthenticationException("auth.07",
new Object[] { authURL + "*" });
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java
index e5b2c598c..c4c4b2691 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java
@@ -66,14 +66,22 @@ import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
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.modules.TaskExecutionException;
import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
+import at.gv.egovernment.moa.id.process.ProcessEngine;
+import at.gv.egovernment.moa.id.process.ProcessExecutionException;
import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
import at.gv.egovernment.moa.id.storage.IExceptionStore;
import at.gv.egovernment.moa.id.util.ServletUtils;
@@ -97,6 +105,11 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {
protected static final String ERROR_CODE_PARAM = "errorid";
+ /**
+ * The process engine.
+ */
+ private ProcessEngine processEngine;
+
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
@@ -174,29 +187,36 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {
protected void handleError(String errorMessage, Throwable exceptionThrown,
HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
- if (null != errorMessage) {
- Logger.error(errorMessage);
- req.setAttribute("ErrorMessage", errorMessage);
- }
-
- if (null != exceptionThrown) {
- if (null == errorMessage)
- errorMessage = exceptionThrown.getMessage();
- Logger.error(errorMessage, exceptionThrown);
- req.setAttribute("ExceptionThrown", exceptionThrown);
- }
-
- if (Logger.isDebugEnabled()) {
- req.setAttribute("LogLevel", "debug");
+ Throwable loggedException = null;
+
+ if (exceptionThrown != null
+ && exceptionThrown instanceof ProcessExecutionException) {
+ ProcessExecutionException procExc =
+ (ProcessExecutionException) exceptionThrown;
+ if (procExc.getCause() != null &&
+ procExc.getCause() instanceof TaskExecutionException) {
+ TaskExecutionException taskExc = (TaskExecutionException) procExc.getCause();
+ loggedException = taskExc.getOriginalException();
+ if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) {
+ Logger.error(exceptionThrown.getMessage(), exceptionThrown);
+
+ } else
+ Logger.error(exceptionThrown.getMessage());
+
+ }
}
+
+ if (loggedException == null)
+ loggedException = exceptionThrown;
+
- if (!(exceptionThrown instanceof MOAIDException)) {
- Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
+ if (!(loggedException instanceof MOAIDException)) {
+ Logger.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException);
}
IExceptionStore store = DBExceptionStoreImpl.getStore();
- String id = store.storeException(exceptionThrown);
+ String id = store.storeException(loggedException);
if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
@@ -217,7 +237,7 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {
} else {
//Exception can not be stored in database
- handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
+ handleErrorNoRedirect(errorMessage, loggedException, req, resp);
}
}
@@ -454,4 +474,31 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {
}
+
+ /**
+ * Returns the underlying process engine instance.
+ *
+ * @return The process engine (never {@code null}).
+ * @throws NoSuchBeanDefinitionException
+ * if no {@link ProcessEngine} bean was found.
+ * @throws NoUniqueBeanDefinitionException
+ * if more than one {@link ProcessEngine} bean was found.
+ * @throws BeansException
+ * if a problem getting the {@link ProcessEngine} bean occurred.
+ * @throws IllegalStateException
+ * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a
+ * Spring web environment.
+ */
+ public synchronized ProcessEngine getProcessEngine() {
+ if (processEngine == null) {
+ WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
+ if (ctx == null) {
+ throw new IllegalStateException(
+ "Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment.");
+ }
+ processEngine = ctx.getBean(ProcessEngine.class);
+ }
+ return processEngine;
+ }
+
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java
index 2ef8ab5ec..ad4776a45 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java
@@ -23,52 +23,42 @@
package at.gv.egovernment.moa.id.auth.servlet;
import java.io.IOException;
-import java.io.PrintWriter;
import java.util.List;
-import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
-import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer;
-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.modules.registration.ModuleRegistration;
import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.commons.db.dao.config.TemplateType;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
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.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestStorage;
+import at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol;
+
+import at.gv.egovernment.moa.id.process.ExecutionContextImpl;
+import at.gv.egovernment.moa.id.process.ProcessInstance;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
-import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.MiscUtil;
-import at.gv.egovernment.moa.util.StringUtils;
public class GenerateIFrameTemplateServlet extends AuthServlet {
private static final long serialVersionUID = 1L;
- public void init(ServletConfig servletConfig) throws ServletException {
-// try {
-// super.init(servletConfig);
-// MOAIDAuthInitializer.initialize();
-// Logger.debug("default platform file.encoding: " + System.getProperty("file.encoding"));
-// Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null));
-// }
-// catch (Exception ex) {
-// Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex);
-// throw new ServletException(ex);
-// }
- }
-
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Logger.info("Receive " + GenerateIFrameTemplateServlet.class + " Request");
@@ -95,7 +85,7 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {
moasession = AuthenticationSessionStoreage.getSession(moasessionid);
- AuthenticationSessionStoreage.changeSessionID(moasession);
+// AuthenticationSessionStoreage.changeSessionID(moasession);
} catch (MOADatabaseException e) {
Logger.info("MOASession with SessionID="+ moasessionid + " is not found in Database");
@@ -116,11 +106,15 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {
else {
- //load Parameters from config
- String target = oaParam.getTarget();
-
-
-
+ //get Target from config or from request in case of SAML 1
+ String target = null;
+ IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
+ if (MiscUtil.isNotEmpty(pendingReq.getTarget()) &&
+ pendingReq.requestedModule().equals(SAML1Protocol.PATH))
+ target = pendingReq.getTarget();
+ else
+ target = oaParam.getTarget();
+
String bkuURL = oaParam.getBKUURL(bkuid);
if (MiscUtil.isEmpty(bkuURL)) {
Logger.info("No OA specific BKU defined. Use BKU from default configuration");
@@ -161,28 +155,37 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {
moasession.getAction(),
req);
}
-
- StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
- String getIdentityLinkForm = startauth.build(moasession, req, resp);
-
- //store MOASession
+
+ ExecutionContext ec = new ExecutionContextImpl();
+ // set execution context
+ ec.put("ccc", moasession.getCcc());
+ ec.put("useMandate", moasession.getUseMandate());
+ ec.put("bkuURL", moasession.getBkuURL());
+
+ // select and create process instance
+ String processDefinitionId = ModuleRegistration.getInstance().selectProcess(ec);
+ String processInstanceId = getProcessEngine().createProcessInstance(processDefinitionId, ec);
+
+ if (processDefinitionId == null) {
+ Logger.warn("No suitable process found for SessionID " + moasession.getSessionID());
+ throw new MOAIDException("process.02", new Object[] { moasession.getSessionID() });
+ }
+
+ // keep process instance id in moa session
+ moasession.setProcessInstanceId(processInstanceId);
+
+ // make sure moa session has been persisted before running the process
try {
AuthenticationSessionStoreage.storeSession(moasession);
-
} catch (MOADatabaseException e) {
Logger.error("Database Error! MOASession is not stored!");
- throw new MOAIDException("init.04", new Object[] {
- moasession.getSessionID()});
+ throw new MOAIDException("init.04", new Object[] { moasession.getSessionID() });
}
-
- if (!StringUtils.isEmpty(getIdentityLinkForm)) {
- resp.setContentType("text/html;charset=UTF-8");
- PrintWriter out = new PrintWriter(resp.getOutputStream());
- out.print(getIdentityLinkForm);
- out.flush();
- Logger.debug("Finished GET "+GenerateIFrameTemplateServlet.class);
- }
- }
+
+ // start process
+ getProcessEngine().start(processInstanceId);
+
+ }
catch (WrongParametersException ex) {
handleWrongParameters(ex, req, resp);
}
@@ -199,4 +202,13 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {
ConfigurationDBUtils.closeSession();
}
}
+
+
+
+
+
+
+
+
+
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java
index bbc704f22..41c2a9c6a 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java
@@ -69,6 +69,7 @@ import at.gv.egovernment.moa.id.auth.data.IdentityLink;
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.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetForeignIDTask;
import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
import at.gv.egovernment.moa.id.client.SZRGWClientException;
@@ -85,6 +86,7 @@ import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;
* Servlet requested for getting the foreign eID
* provided by the security layer implementation.
* Utilizes the {@link AuthenticationServer}.
+ * @deprecated Use {@link GetForeignIDTask} instead.
*
*/
public class GetForeignIDServlet extends AuthServlet {
@@ -134,6 +136,8 @@ public class GetForeignIDServlet extends AuthServlet {
Logger.debug("POST GetForeignIDServlet");
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java
index 9e2e845b5..043b660c1 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java
@@ -67,6 +67,7 @@ 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.modules.internal.tasks.GetMISSessionIDTask;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.config.ConnectionParameter;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
@@ -83,7 +84,7 @@ import at.gv.egovernment.moa.util.DOMUtils;
/**
* Servlet requested for getting the foreign eID provided by the security layer
* implementation. Utilizes the {@link AuthenticationServer}.
- *
+ * @deprecated Use {@link GetMISSessionIDTask} instead.
*/
public class GetMISSessionIDServlet extends AuthServlet {
@@ -136,6 +137,8 @@ public class GetMISSessionIDServlet extends AuthServlet {
Logger.debug("POST GetMISSessionIDServlet");
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,
MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,
@@ -197,6 +200,7 @@ public class GetMISSessionIDServlet extends AuthServlet {
// for now: list contains only one element
MISMandate mandate = (MISMandate) list.get(0);
+ // TODO[tlenz]: UTF-8 ?
String sMandate = new String(mandate.getMandate());
if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {
Logger.error("Mandate is empty.");
@@ -206,6 +210,7 @@ public class GetMISSessionIDServlet extends AuthServlet {
//check if it is a parsable XML
byte[] byteMandate = mandate.getMandate();
+ // TODO[tlenz]: UTF-8 ?
String stringMandate = new String(byteMandate);
DOMUtils.parseDocument(stringMandate, false,
null, null).getDocumentElement();
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java
deleted file mode 100644
index e04f97e6e..000000000
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*******************************************************************************
- * Copyright 2014 Federal Chancellery Austria
- * MOA-ID has been developed in a cooperation between BRZ, the Federal
- * Chancellery Austria - ICT staff unit, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * http://www.osor.eu/eupl/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- ******************************************************************************/
-package at.gv.egovernment.moa.id.auth.servlet;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import at.gv.egovernment.moa.id.config.ConfigurationException;
-import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
-import at.gv.egovernment.moa.id.monitoring.TestManager;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.MiscUtil;
-
-public class MonitoringServlet extends AuthServlet {
-
- private static final long serialVersionUID = 1L;
- private static final String REQUEST_ATTR_MODULE = "module";
-
-
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- try {
- AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
-
- if (config.isMonitoringActive()) {
- Logger.debug("Monitoring Servlet received request");
-
- TestManager tests = TestManager.getInstance();
-
- String modulename = req.getParameter(REQUEST_ATTR_MODULE);
- if (MiscUtil.isEmpty(modulename)) {
-
- List<String> error = tests.executeTests();
- if (error != null && error.size() > 0) {
- createErrorMessage(req, resp, error);
-
- } else {
- resp.setStatus(HttpServletResponse.SC_OK);
- resp.setContentType("text/html;charset=UTF-8");
- resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess()));
- Logger.info("Monitoring Servlet finished without errors");
- }
-
- } else {
- if (tests.existsModule(modulename)) {
- List<String> errors = tests.executeTest(modulename);
- if (errors != null && errors.size() > 0) {
- createErrorMessage(req, resp, errors);
-
- } else {
- resp.setStatus(HttpServletResponse.SC_OK);
- resp.setContentType("text/html;charset=UTF-8");
- resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess()));
- Logger.info("Monitoring Servlet finished without errors");
- }
-
- } else {
- Logger.warn("NO Testmodule exists with modulename " + modulename);
- resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
- resp.setContentType("text/html;charset=UTF-8");
- PrintWriter out;
- try {
- out = new PrintWriter(resp.getOutputStream());
- out.write("NO Testmodule exists with modulename " + modulename);
- out.flush();
-
- } catch (IOException e) {
- Logger.warn("Internal Monitoring Servlet Error. ", e);
- }
- }
-
- }
- }
-
- } catch (ConfigurationException e) {
- createErrorMessage(req, resp, Arrays.asList(e.getMessage()));
- }
- }
-
- private void createErrorMessage(HttpServletRequest req, HttpServletResponse resp, List<String> errorMessage) {
- Logger.warn("Monitoring Servlet found some Error: " + errorMessage);
- resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- resp.setContentType("text/html;charset=UTF-8");
- PrintWriter out;
- try {
- out = new PrintWriter(resp.getOutputStream());
- for (String error : errorMessage)
- out.write(error + "<br>");
- out.flush();
-
- } catch (IOException e) {
- Logger.warn("Internal Monitoring Servlet Error. ", e);
- }
- }
-
- private String getHtml(String text) {
- return "<html><head><title>Reponse</title></head><body>" + text +"</body></html>";
- }
-}
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 3dd2afd96..24daa76a3 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
@@ -28,8 +28,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import java.util.Properties;
@@ -48,6 +50,8 @@ import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.opensaml.saml2.core.StatusCode;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
import at.gv.egovernment.moa.id.auth.AuthenticationServer;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
@@ -55,6 +59,7 @@ 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.parser.IdentityLinkAssertionParser;
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;
@@ -65,9 +70,12 @@ 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.IdentityLinkReSigner;
import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.StringUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
import at.gv.util.xsd.xmldsig.SignatureType;
import at.gv.util.xsd.xmldsig.X509DataType;
import eu.stork.oasisdss.api.ApiUtils;
@@ -98,6 +106,7 @@ import javax.xml.ws.BindingProvider;
/**
* Endpoint for receiving STORK response messages
+ * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorTask} instead.
*/
public class PEPSConnectorServlet extends AuthServlet {
@@ -149,6 +158,8 @@ public class PEPSConnectorServlet extends AuthServlet {
try {
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
@@ -192,6 +203,15 @@ public class PEPSConnectorServlet extends AuthServlet {
Logger.debug("STORK response: ");
Logger.debug(authnResponse.toString());
+ // do PEPS-conform logging for easier evaluation
+ try {
+ // 2015-03-12 16:44:27.144#S-PEPS receives response from C-PEPS#orig_msg_id id2 (in response to)#orig_msg_id id1 (in response to)#status#msghash#msg_id id3#
+ Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS receives response from C-PEPS#" +
+ authnResponse.getInResponseTo() + "#NA#" + authnResponse.getMessage() + "#_hash_#" + authnResponse.getSamlId() + "#");
+ } catch (Exception e1) {
+ Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
+ }
+
Logger.debug("Trying to find MOA Session-ID ...");
//String moaSessionID = request.getParameter(PARAM_SESSIONID);
//first use SAML2 relayState
@@ -434,14 +454,61 @@ public class PEPSConnectorServlet extends AuthServlet {
targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
}
- Logger.debug("Starting connecting SZR Gateway");
- //contact SZR Gateway
IdentityLink identityLink = null;
try {
- identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(),
+ AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
+ if(config.isStorkFakeIdLActive() && config.getStorkFakeIdLCountries().contains(storkAuthnRequest.getCitizenCountryCode())) {
+ // create fake IdL
+ // - fetch IdL template from resources
+ InputStream s = PEPSConnectorServlet.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
+ Element idlTemplate = DOMUtils.parseXmlValidating(s);
+
+ identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
+
+ // replace data
+ Element idlassertion = identityLink.getSamlAssertion();
+ // - set bpk/wpbk;
+ Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ if(!STORKResponseProcessor.hasAttribute("eIdentifier", attributeList))
+ throw new STORKException("eIdentifier is missing");
+ String eIdentifier = STORKResponseProcessor.getAttributeValue("eIdentifier", attributeList, false);
+ prIdentification.getFirstChild().setNodeValue(eIdentifier);
+
+ // - set last name
+ Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ if(!STORKResponseProcessor.hasAttribute("surname", attributeList))
+ throw new STORKException("surname is missing");
+ String familyName = STORKResponseProcessor.getAttributeValue("surname", attributeList, false);
+ prFamilyName.getFirstChild().setNodeValue(familyName);
+
+ // - set first name
+ Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ if(!STORKResponseProcessor.hasAttribute("givenName", attributeList))
+ throw new STORKException("givenName is missing");
+ String givenName = STORKResponseProcessor.getAttributeValue("givenName", attributeList, false);
+ prGivenName.getFirstChild().setNodeValue(givenName);
+
+ // - set date of birth
+ Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+ if(!STORKResponseProcessor.hasAttribute("dateOfBirth", attributeList))
+ throw new STORKException("dateOfBirth is missing");
+ String dateOfBirth = STORKResponseProcessor.getAttributeValue("dateOfBirth", attributeList, false);
+ prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth);
+
+ identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+
+ //resign IDL
+ IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
+ Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey());
+ identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink();
+ } else {
+ //contact SZR Gateway
+ Logger.debug("Starting connecting SZR Gateway");
+ 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
@@ -498,6 +565,15 @@ public class PEPSConnectorServlet extends AuthServlet {
// stork did the authentication step
moaSession.setAuthenticated(true);
+ // do PEPS-conform logging for easier evaluation
+ try {
+ // 2015-03-12 16:44:27.144#S-PEPS generates response to SP#orig_msg_id id1 (in response to)#status#msghash#msg_id id4#
+ Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS generates response to SP#" +
+ "#NA#" + authnResponse.getMessage() + "#_hash_#" + moaSession.getProcessInstanceId() + "#");
+ } catch (Exception e1) {
+ Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
+ }
+
// //TODO: found better solution, but QAA Level in response could be not supported yet
// try {
//
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 3bc79f8bd..337a9ed31 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.modules.stork.tasks.PepsConnectorHandleResponseWithoutSignatureTask} instead.
*/
public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {
private static final long serialVersionUID = 1L;
@@ -131,6 +132,8 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
String moaSessionID1 = request.getParameter("moaSessionID");
String signResponse = request.getParameter("signresponse");
Logger.info("moaSessionID1:"+moaSessionID1);
@@ -473,6 +476,7 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {
Logger.info("Found AttributeProviderPlugin attribute:"+ap.getAttributes());
if(ap.getAttributes().equalsIgnoreCase("signedDoc"))
{
+ // FIXME[tlenz]: A servlet's class field is not thread safe.
oasisDssWebFormURL = ap.getUrl();
found = true;
Logger.info("Loaded signedDoc attribute provider url from config:"+oasisDssWebFormURL);
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
new file mode 100644
index 000000000..43b6c03d4
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java
@@ -0,0 +1,101 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+
+/**
+ * Servlet that resumes a suspended process (in case of asynchronous tasks).
+ *
+ * @author tknall
+ *
+ */
+public class ProcessEngineSignalServlet extends AuthServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
+ *
+ * @param resp
+ * The HttpServletResponse.
+ */
+ private void setNoCachingHeaders(HttpServletResponse resp) {
+ resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
+ }
+
+ /**
+ * Processes a GET request, delegating the call to {@link #doPost(HttpServletRequest, HttpServletResponse)}.
+ */
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ this.doPost(req, resp);
+ }
+
+ /**
+ * 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 {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.
+ */
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ String sessionID = StringEscapeUtils.escapeHtml(getMoaSessionId(req));
+
+ setNoCachingHeaders(resp);
+ String pendingRequestID = null;
+ try {
+
+ if (sessionID == null) {
+ throw new IllegalStateException("Unable to determine MOA session id.");
+ }
+
+ // retrieve moa session
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ // process instance is mandatory
+ if (session.getProcessInstanceId() == null) {
+ throw new IllegalStateException("MOA session does not provide process instance id.");
+ }
+
+ // wake up next task
+ getProcessEngine().signal(session.getProcessInstanceId());
+
+ } catch (Exception ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+ } finally {
+ MOASessionDBUtils.closeSession();
+ }
+
+ }
+
+ /**
+ * Retrieves the current MOA session id from the HttpServletRequest parameter
+ * {@link MOAIDAuthConstants#PARAM_SESSIONID}.
+ * <p/>
+ * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the
+ * respective MOA session id.
+ *
+ * @param request
+ * The unterlying HttpServletRequest.
+ * @return The current MOA session id.
+ */
+ public String getMoaSessionId(HttpServletRequest request) {
+ return StringEscapeUtils.escapeHtml(request.getParameter(PARAM_SESSIONID));
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java
index e7fa9cbd7..a8fe71485 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java
@@ -71,6 +71,7 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;
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.modules.internal.tasks.VerifyAuthenticationBlockTask;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.ConnectionParameter;
@@ -92,6 +93,7 @@ import at.gv.egovernment.moa.util.DOMUtils;
*
* @author Paul Ivancsics
* @version $Id$
+ * @deprecated Use {@link VerifyAuthenticationBlockTask} instead.
*/
public class VerifyAuthenticationBlockServlet extends AuthServlet {
@@ -153,6 +155,8 @@ public class VerifyAuthenticationBlockServlet extends AuthServlet {
Logger.debug("POST VerifyAuthenticationBlock");
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java
index a3397f561..2aa717a65 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java
@@ -65,6 +65,7 @@ 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.modules.internal.tasks.VerifyCertificateTask;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
@@ -77,6 +78,7 @@ import at.gv.egovernment.moa.spss.util.CertificateUtils;
* Servlet requested for getting the foreign eID
* provided by the security layer implementation.
* Utilizes the {@link AuthenticationServer}.
+ * @deprecated Use {@link VerifyCertificateTask} instead.
*
*/
public class VerifyCertificateServlet extends AuthServlet {
@@ -126,6 +128,8 @@ public class VerifyCertificateServlet extends AuthServlet {
Logger.debug("POST VerifyCertificateServlet");
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
+
resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
@@ -180,7 +184,8 @@ public class VerifyCertificateServlet extends AuthServlet {
throw new MOAIDException("session store error", null);
}
- ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
+ ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
+
}
else {
@@ -208,8 +213,7 @@ public class VerifyCertificateServlet extends AuthServlet {
throw new MOAIDException("session store error", null);
}
- ServletUtils.writeCreateXMLSignatureRequest(resp, session, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
-
+ ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
Logger.debug("Send CreateXMLSignatureRequest to BKU");
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java
index 3b503f07b..b8e57ed43 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java
@@ -53,7 +53,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.lang.StringEscapeUtils;
import at.gv.egovernment.moa.id.auth.AuthenticationServer;
@@ -65,8 +64,8 @@ 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.ParseException;
import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyIdentityLinkTask;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
-import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
@@ -82,6 +81,7 @@ import at.gv.egovernment.moa.logging.Logger;
*
* @author Paul Ivancsics
* @version $Id$
+ * @deprecated Use {@link VerifyIdentityLinkTask} instead.
*/
public class VerifyIdentityLinkServlet extends AuthServlet {
@@ -135,6 +135,8 @@ public class VerifyIdentityLinkServlet extends AuthServlet {
throws ServletException, IOException {
Logger.debug("POST VerifyIdentityLink");
+
+ Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
Map<String, String> parameters;
String pendingRequestID = null;
@@ -201,7 +203,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {
session.getSessionID());
- ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
+ ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
}
@@ -231,7 +233,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {
//ServletUtils.writeCreateXMLSignatureRequestURLEncoded(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
Logger.debug("ContentType set to: text/xml;charset=UTF-8 (ServletUtils)");
- ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
+ ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
}
else {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java
index 7113dcf70..3809ec4bc 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java
@@ -39,6 +39,7 @@ import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
import at.gv.egovernment.moa.id.auth.AuthenticationServer;
import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
@@ -102,7 +103,7 @@ public class STORKResponseProcessor {
private static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList) throws STORKException {
return getAttributeValue(attributeName, attributeList, true);
}
- private static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList, boolean throwException) throws STORKException {
+ public static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList, boolean throwException) throws STORKException {
try {
String result = attributeList.get(attributeName).getValue().get(0);
Logger.trace(attributeName + " : " + result);
@@ -286,6 +287,12 @@ public class STORKResponseProcessor {
Object attributeValue = attribute.getValue();
if (null == attributeValue)
attributeValue = attribute.getComplexValue();
+
+ // escape attributeValue
+ attributeValue = StringEscapeUtils.escapeXml10(attributeValue.toString());
+ // and remove trailing and tailing brackets. Might break something but we never saw an array with more than one entry!
+ attributeValue = ((String) attributeValue).substring(1, ((String) attributeValue).length() - 1);
+
ExtendedSAMLAttribute extendedSAMLAttribute =
new ExtendedSAMLAttributeImpl(attribute.getName(), attributeValue, Constants.STORK_NS_URI, 0);
moaExtendedSAMLAttributeList.add(extendedSAMLAttribute);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java
index e1cd59c26..61b26b59a 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java
@@ -65,6 +65,7 @@ import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;
+import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
@@ -137,7 +138,7 @@ public class SZRGWClient {
if (address == null) {
throw new NullPointerException("Address (SZR-gateway ServiceURL) must not be null.");
}
- HttpClient client = new HttpClient();
+ HttpClient client = HttpClientWithProxySupport.getHttpClient();
PostMethod method = new PostMethod(address);
method.setRequestHeader("SOAPAction", "");
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java
index 88ed7885f..24def1e02 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java
@@ -124,7 +124,7 @@ public class ConfigurationProvider {
protected String certstoreDirectory;
- protected boolean trustmanagerrevoationchecking;
+ protected boolean trustmanagerrevoationchecking = true;
/**
* Returns the main configuration file directory used to configure MOA-ID
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java
index b02c0946c..828bf99ca 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java
@@ -40,7 +40,7 @@ public class AuthConfigLoader implements Runnable {
try {
Thread.sleep(INTERVAL * 1000);
- Logger.info("check for new config.");
+ Logger.trace("check for new config.");
MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();
if (moaidconfig != null) {
@@ -77,7 +77,7 @@ public class AuthConfigLoader implements Runnable {
public static void start() {
// start the session cleanup thread
- Thread configLoader = new Thread(new AuthConfigLoader());
+ Thread configLoader = new Thread(new AuthConfigLoader(), "AuthConfigLoader");
configLoader.setName("ConfigurationLoader");
configLoader.setDaemon(true);
configLoader.setPriority(Thread.MIN_PRIORITY);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java
index 89d02c183..6a2f2db44 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java
@@ -53,6 +53,7 @@ import java.io.IOException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -110,10 +111,10 @@ import at.gv.egovernment.moa.id.config.auth.data.ProtocolAllowed;
import at.gv.egovernment.moa.id.config.legacy.BuildFromLegacyConfig;
import at.gv.egovernment.moa.id.config.stork.STORKConfig;
import at.gv.egovernment.moa.id.data.IssuerAndSerial;
+import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
-import at.gv.util.config.EgovUtilConfiguration;
import at.gv.util.config.EgovUtilPropertiesConfiguration;
/**
@@ -344,6 +345,7 @@ public class AuthConfigurationProvider extends ConfigurationProvider {
config.addAnnotatedClass(OldSSOSessionIDStore.class);
config.addAnnotatedClass(ExceptionStore.class);
config.addAnnotatedClass(InterfederationSessionStore.class);
+ config.addAnnotatedClass(ProcessInstanceStore.class);
config.addProperties(moaSessionProp);
MOASessionDBUtils.initHibernate(config, moaSessionProp);
@@ -1007,6 +1009,49 @@ public class AuthConfigurationProvider extends ConfigurationProvider {
return null;
}
+ /**
+ * Checks if is fakeIdL is activated.
+ *
+ * @return true, if fake IdLs are available for stork
+ */
+ public boolean isStorkFakeIdLActive() {
+ String prop = props.getProperty("stork.fakeIdL.active", "false");
+ return Boolean.valueOf(prop);
+ }
+
+ /**
+ * Gets the countries which will receive a fake IdL
+ *
+ * @return the countries
+ */
+ public List<String> getStorkFakeIdLCountries() {
+ String prop = props.getProperty("stork.fakeIdL.countries", "");
+ return Arrays.asList(prop.replaceAll(" ", "").split(","));
+ }
+
+ /**
+ * Gets the resigning key (group) for the stork fake IdL.
+ *
+ * @return the resigning key
+ */
+ public String getStorkFakeIdLResigningKey() {
+ String prop = props.getProperty("stork.fakeIdL.keygroup");
+ if (MiscUtil.isNotEmpty(prop))
+ return prop;
+ else
+ return null;
+ }
+
+ /**
+ * Gets the countries for which it is configured to require no signature
+ *
+ * @return the stork no signature countries
+ */
+ public List<String> getStorkNoSignatureCountries() {
+ String prop = props.getProperty("stork.fakeIdL.noSignatureCountries", "");
+ return Arrays.asList(prop.replaceAll(" ", "").split(","));
+ }
+
public boolean isMonitoringActive() {
String prop = props.getProperty("configuration.monitoring.active", "false");
return Boolean.valueOf(prop);
@@ -1027,7 +1072,14 @@ public class AuthConfigurationProvider extends ConfigurationProvider {
else
return null;
}
-
+
+ // allow http to be used in call, used in systems proxied on the same instance
+ public boolean isHTTPAuthAllowed() {
+ String prop = props.getProperty("configuration.localhttpallowed.active", "false");
+ return Boolean.valueOf(prop);
+ }
+
+
public boolean isAdvancedLoggingActive() {
String prop = props.getProperty("configuration.advancedlogging.active", "false");
return Boolean.valueOf(prop);
@@ -1047,12 +1099,19 @@ public class AuthConfigurationProvider extends ConfigurationProvider {
return !Boolean.valueOf(prop);
}
+
//Load document service url from moa properties
public String getDocumentServiceUrl() {
String prop = props.getProperty("stork.documentservice.url", "false");
return prop;
}
+
+ public boolean isPVPSchemaValidationActive() {
+ String prop = props.getProperty("protocols.pvp2.schemavalidation", "true");
+ return Boolean.valueOf(prop);
+ }
+
/**
* Returns the STORK Configuration
* @return STORK Configuration
@@ -1084,10 +1143,11 @@ private void setCertStoreDirectory() throws ConfigurationException {
private void setTrustManagerRevocationChecking() throws ConfigurationException {
AuthComponentGeneral auth = getAuthComponentGeneral();
- if (auth.getGeneralConfiguration() != null)
+ if (auth.getGeneralConfiguration() != null &&
+ auth.getGeneralConfiguration().isTrustManagerRevocationChecking() != null)
trustmanagerrevoationchecking = auth.getGeneralConfiguration().isTrustManagerRevocationChecking();
else {
- Logger.warn("Error in MOA-ID Configuration. No CertStoreDirectory defined.");
+ Logger.warn("No TrustMangerRevoationChecking defined. Use default value = TRUE");
throw new ConfigurationException("config.02", null);
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java
index 90b72b72b..933dddb31 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java
@@ -46,6 +46,7 @@
package at.gv.egovernment.moa.id.config.auth;
+import java.io.IOException;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java
index 787a480f0..b7d5ebed5 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java
@@ -55,10 +55,12 @@ public class BPKDecryptionParameters implements Serializable{
/**
* @return
+ * @throws IOException
*/
- public PrivateKey getPrivateKey() {
+ public PrivateKey getPrivateKey() {
+ InputStream in = null;
try {
- InputStream in = new ByteArrayInputStream(keyStore);
+ in = new ByteArrayInputStream(keyStore);
KeyStore store = KeyStoreUtils.loadKeyStore(in , keyStorePassword);
char[] chPassword = " ".toCharArray();
@@ -83,6 +85,14 @@ public class BPKDecryptionParameters implements Serializable{
} catch (NoSuchAlgorithmException e) {
Logger.error("Can not load private key from keystore.", e);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ Logger.warn("Close InputStream failed." , e);
+ }
+ }
}
return null;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java
index 9067d8fc4..3d4b53f7c 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java
@@ -151,6 +151,8 @@ public class BuildFromLegacyConfig {
if (genericConfiguration.containsKey(ConfigurationProvider.TRUST_MANAGER_REVOCATION_CHECKING))
authGeneral.setTrustManagerRevocationChecking(
Boolean.valueOf((String)genericConfiguration.get(ConfigurationProvider.TRUST_MANAGER_REVOCATION_CHECKING)));
+ else
+ authGeneral.setTrustManagerRevocationChecking(true);
if (genericConfiguration.containsKey(ConfigurationProvider.DIRECTORY_CERTSTORE_PARAMETER_PROPERTY))
authGeneral.setCertStoreDirectory(
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
index 65c413ef9..05b008515 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
@@ -133,7 +133,9 @@ public class AuthenticationData implements IAuthData, Serializable {
private String authBlock = null;
private List<String> encbPKList = null;
+ //ISA 1.18 attributes
private List<AuthenticationRole> roles = null;
+ private String pvpAttribute_OU = null;
private boolean useMandate = false;
private MISMandate mandate = null;
@@ -707,6 +709,7 @@ public class AuthenticationData implements IAuthData, Serializable {
return roles;
}
+ //ISA 1.18 attributes
/**
* @param roles the roles to set
*/
@@ -716,26 +719,31 @@ public class AuthenticationData implements IAuthData, Serializable {
this.roles.add(role);
}
+
+ /**
+ * @return the pvpAttribute_OU
+ */
+ public String getPvpAttribute_OU() {
+ return pvpAttribute_OU;
+ }
+
+ /**
+ * @param pvpAttribute_OU the pvpAttribute_OU to set
+ */
+ public void setPvpAttribute_OU(String pvpAttribute_OU) {
+ this.pvpAttribute_OU = pvpAttribute_OU;
+ }
/* (non-Javadoc)
* @see at.gv.egovernment.moa.id.data.IAuthData#isBusinessService()
*/
@Override
public boolean isBusinessService() {
- // TODO Auto-generated method stub
return this.businessService;
}
public void setIsBusinessService(boolean flag) {
this.businessService = flag;
- }
-
-
-
-
-
-
-
-
+ }
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java
index 8915b2442..b3b29f6c5 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
/**
* @author tlenz
@@ -51,23 +52,29 @@ public class AuthenticationRoleFactory {
List<String> param = Arrays.asList(params.split(","));
String test = new String();
for (String el : param) {
- test = test.concat(el);
- if (!test.endsWith("\\") ||
- (test.endsWith("\\\\") && !test.endsWith("\\\\\\")) ) {
- String[] keyValue = test.split("=");
- if (keyValue.length < 2) {
- role.addParameter(keyValue[0].trim(), "");
- Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim());
+ if (MiscUtil.isNotEmpty(el)) {
+ test = test.concat(el);
+ if (!test.endsWith("\\") ||
+ (test.endsWith("\\\\") && !test.endsWith("\\\\\\")) ) {
+ String[] keyValue = test.split("=");
+ if (keyValue.length < 2) {
+ role.addParameter(keyValue[0].trim(), "");
+ Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim());
- } else {
- role.addParameter(keyValue[0].trim(), keyValue[1].trim());
- Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()
- + " value=" + keyValue[1].trim());
+ } else {
+ role.addParameter(keyValue[0].trim(), keyValue[1].trim());
+ Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()
+ + " value=" + keyValue[1].trim());
- }
+ }
- test = new String();
- }
+ test = new String();
+
+ } else {
+ test = test.substring(0, test.length()-1).concat(",");
+
+ }
+ }
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
index ebbf62ce7..ccc90a031 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
@@ -69,7 +69,9 @@ public interface IAuthData {
IdentityLink getIdentityLink();
byte[] getSignerCertificate();
String getAuthBlock();
-
+
+ //ISA 1.18 attributes
+ String getPvpAttribute_OU();
List<AuthenticationRole> getAuthenticationRoles();
boolean isPublicAuthority();
@@ -90,5 +92,6 @@ public interface IAuthData {
String getCcc();
STORKAuthnRequest getStorkAuthnRequest();
String getStorkAuthnResponse();
- IPersonalAttributeList getStorkAttributes();
+ IPersonalAttributeList getStorkAttributes();
+
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
index 03cb6c1c4..e3b7524ae 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
@@ -23,7 +23,6 @@
package at.gv.egovernment.moa.id.entrypoints;
import java.io.IOException;
-
import java.util.Iterator;
import javax.servlet.ServletConfig;
@@ -97,10 +96,13 @@ public class DispatcherServlet extends AuthServlet{
boolean useSSOOA = false;
String protocolRequestID = null;
-
try {
Logger.info("REQUEST: " + req.getRequestURI());
Logger.info("QUERY : " + req.getQueryString());
+
+
+// *** start of error handling ***
+
String errorid = req.getParameter(ERROR_CODE_PARAM);
if (errorid != null) {
@@ -117,7 +119,7 @@ public class DispatcherServlet extends AuthServlet{
pendingRequestID = (String) idObject;
}
- if (throwable != null) {
+ if (throwable != null) {
IRequest errorRequest = null;
if (pendingRequestID != null) {
@@ -173,6 +175,11 @@ public class DispatcherServlet extends AuthServlet{
return;
}
+// *** end of error handling ***
+
+
+// *** start of protocol specific stuff ***
+
Object moduleObject = req.getParameter(PARAM_TARGET_MODULE);
String module = null;
if (moduleObject != null && (moduleObject instanceof String)) {
@@ -272,7 +279,7 @@ public class DispatcherServlet extends AuthServlet{
//create interfederated MOASession
String sessionID =
AuthenticationSessionStoreage.createInterfederatedSession(protocolRequest, true, ssoId);
- req.getParameterMap().put(PARAM_SESSIONID, sessionID);
+ req.getParameterMap().put(PARAM_SESSIONID, new String[]{ sessionID });
Logger.info("PreProcessing of SSO interfederation response complete. ");
@@ -357,7 +364,11 @@ public class DispatcherServlet extends AuthServlet{
}
}
-
+
+// *** end of protocol specific stuff ***
+
+// *** start handling authentication ***
+
AuthenticationManager authmanager = AuthenticationManager.getInstance();
String moasessionID = null;
@@ -473,7 +484,11 @@ public class DispatcherServlet extends AuthServlet{
//build authenticationdata from session information and OA configuration
authData = AuthenticationDataBuilder.buildAuthenticationData(protocolRequest, moasession);
}
-
+
+// *** end handling authentication ***
+
+// *** start finalizing authentication (SSO, final redirects, statistic logging etc) ***
+
SLOInformationInterface assertionID = moduleAction.processRequest(protocolRequest, req, resp, authData);
RequestStorage.removePendingRequest(protocolRequestID);
@@ -506,6 +521,8 @@ public class DispatcherServlet extends AuthServlet{
}
+// *** end finalizing authentication ***
+
} catch (Throwable e) {
Logger.warn("An authentication error occured: ", e);;
// Try handle module specific, if not possible rethrow
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
index a4d63b144..49f3df25c 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
@@ -59,17 +59,17 @@ import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.soap.common.SOAPException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.security.SecurityException;
+import org.springframework.beans.factory.annotation.Autowired;
import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder;
import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder;
-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.BuildException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration;
import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;
-import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
@@ -77,6 +77,12 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.data.SLOInformationContainer;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+
+import at.gv.egovernment.moa.id.process.ExecutionContextImpl;
+import at.gv.egovernment.moa.id.process.ProcessEngine;
+import at.gv.egovernment.moa.id.process.ProcessExecutionException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
@@ -87,32 +93,33 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest;
import at.gv.egovernment.moa.id.storage.AssertionStorage;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper;
import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
-import at.gv.egovernment.moa.util.StringUtils;
-public class AuthenticationManager extends AuthServlet {
+public class AuthenticationManager implements MOAIDAuthConstants {
- private static AuthenticationManager instance = null;
-
- private static final long serialVersionUID = 1L;
+ private static final AuthenticationManager INSTANCE = new AuthenticationManager();
public static final String MOA_SESSION = "MoaAuthenticationSession";
public static final String MOA_AUTHENTICATED = "MoaAuthenticated";
public static final int SLOTIMEOUT = 30 * 1000; //30 sec
+ @Autowired
+ private ProcessEngine processEngine;
+
+ private AuthenticationManager() {
+ }
+
public static AuthenticationManager getInstance() {
- if (instance == null) {
- instance = new AuthenticationManager();
- }
-
- return instance;
+ return INSTANCE;
}
/**
@@ -320,7 +327,7 @@ public class AuthenticationManager extends AuthServlet {
try {
authSession = AuthenticationSessionStoreage
.getSession(moaSessionID);
-
+
if(authSession == null) {
Logger.info("NO MOA Authentication data for ID " + moaSessionID);
return;
@@ -381,6 +388,7 @@ public class AuthenticationManager extends AuthServlet {
//get IDP metadata
try {
OAAuthParameter idp = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(target.getRequestedIDP());
+ OAAuthParameter sp = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(target.getOAURL());
if (!idp.isInderfederationIDP() || !idp.isInboundSSOInterfederationAllowed()) {
Logger.info("Requested interfederation IDP " + target.getRequestedIDP() + " is not valid for interfederation.");
@@ -389,7 +397,7 @@ public class AuthenticationManager extends AuthServlet {
return;
}
-
+
EntityDescriptor idpEntity = MOAMetadataProvider.getInstance().
getEntityDescriptor(target.getRequestedIDP());
@@ -409,7 +417,7 @@ public class AuthenticationManager extends AuthServlet {
redirectEndpoint == null )
redirectEndpoint = sss;
}
-
+
if (redirectEndpoint != null) {
AuthnRequest authReq = SAML2Utils
@@ -422,16 +430,10 @@ public class AuthenticationManager extends AuthServlet {
authReq.setAssertionConsumerServiceIndex(0);
authReq.setIssueInstant(new DateTime());
- Subject subject = SAML2Utils.createSAMLObject(Subject.class);
- NameID name = SAML2Utils.createSAMLObject(NameID.class);
- Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
-
+ Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath();
- name.setValue(serviceURL);
issuer.setValue(serviceURL);
- subject.setNameID(name);
- authReq.setSubject(subject);
issuer.setFormat(NameIDType.ENTITY);
authReq.setIssuer(issuer);
NameIDPolicy policy = SAML2Utils
@@ -446,13 +448,55 @@ public class AuthenticationManager extends AuthServlet {
SAML2Utils.createSAMLObject(RequestedAuthnContext.class);
AuthnContextClassRef authnClassRef =
- SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
- authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4");
+ SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
+
+ if (sp != null && sp.isSTORKPVPGateway()){
+ //use PVP SecClass instead of STORK QAA level
+ String secClass = null;
+ if (target instanceof MOASTORKRequest) {
+
+ try {
+ MOASTORKRequest storkReq = (MOASTORKRequest) target;
+ secClass = PVPtoSTORKMapper.getInstance().mapToSecClass(
+ PVPConstants.STORK_QAA_PREFIX + storkReq.getStorkAuthnRequest().getQaa());
+
+ } catch (Exception e) {
+ Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e);
+
+ }
+ }
+
+ if (MiscUtil.isNotEmpty(secClass))
+ authnClassRef.setAuthnContextClassRef(secClass);
+ else
+ authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3");
+
+ } else {
+ if (target instanceof MOASTORKRequest) {
+ //use requested QAA level from STORK request
+ try {
+ MOASTORKRequest storkReq = (MOASTORKRequest) target;
+ authnClassRef.setAuthnContextClassRef(
+ PVPConstants.STORK_QAA_PREFIX + storkReq.getStorkAuthnRequest().getQaa());
+ Logger.debug("Use STORK-QAA level " + authnClassRef.getAuthnContextClassRef()
+ + " from STORK request");
+
+ } catch (Exception e) {
+ Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e);
+
+ }
+
+ }
+
+ if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef()))
+ authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4");
+
+ }
+
reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
reqAuthContext.getAuthnContextClassRefs().add(authnClassRef);
authReq.setRequestedAuthnContext(reqAuthContext);
-
-
+
IEncoder binding = null;
if (redirectEndpoint.getBinding().equals(
SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
@@ -508,7 +552,10 @@ public class AuthenticationManager extends AuthServlet {
throws ServletException, IOException, MOAIDException {
Logger.debug("Starting authentication on this IDP ...");
- setNoCachingHeadersInHttpRespone(request, response);
+ response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
+ response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
+ response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
+ response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE);
List<String> legacyallowed_prot = AuthConfigurationProvider.getInstance().getLegacyAllowedProtocols();
@@ -529,79 +576,95 @@ public class AuthenticationManager extends AuthServlet {
throw new MOAIDException("init.04", new Object[] {});
}
-
- if (legacyallowed && legacyparamavail) {
-
- //parse request parameter into MOASession
- StartAuthentificationParameterParser.parse(request, response, moasession, target);
-
- Logger.info("Start Authentication Module: " + moasession.getModul()
- + " Action: " + moasession.getAction());
-
- StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
-
- String getIdentityLinkForm = startauth.build(moasession, request, response);
-
- //store MOASession
- try {
- AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());
- } catch (MOADatabaseException e) {
- Logger.error("Database Error! MOASession is not stored!");
- throw new MOAIDException("init.04", new Object[] {
- moasession.getSessionID()});
- }
-
- if (!StringUtils.isEmpty(getIdentityLinkForm)) {
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter out = new PrintWriter(response.getOutputStream());
- out.print(getIdentityLinkForm);
- out.flush();
- Logger.debug("Finished GET StartAuthentication");
- }
-
- } else {
- //load Parameters from OnlineApplicationConfiguration
- OAAuthParameter oaParam = AuthConfigurationProvider.getInstance()
- .getOnlineApplicationParameter(target.getOAURL());
+ try {
- if (oaParam == null) {
- throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() });
- }
-
- else {
+ if (legacyallowed && legacyparamavail) {
- //check if an MOASession exists and if not create an new MOASession
- //moasession = getORCreateMOASession(request);
+ //parse request parameter into MOASession
+ StartAuthentificationParameterParser.parse(request, response, moasession, target);
+
+ Logger.info("Start Authentication Module: " + moasession.getModul()
+ + " Action: " + moasession.getAction());
+
+ // create execution context
+ ExecutionContext executionContext = new ExecutionContextImpl();
+ executionContext.put("ccc", moasession.getCcc());
+ executionContext.put("useMandate", moasession.getUseMandate());
+ executionContext.put("bkuURL", moasession.getBkuURL());
+ executionContext.put(PARAM_SESSIONID, moasession.getSessionID());
- //set OnlineApplication configuration in Session
- moasession.setOAURLRequested(target.getOAURL());
- moasession.setAction(target.requestedAction());
- moasession.setModul(target.requestedModule());
- }
-
- //Build authentication form
-
-
- String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix();
- String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),
- target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID());
-
- //store MOASession
- try {
- AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());
- } catch (MOADatabaseException e) {
- Logger.error("Database Error! MOASession is not stored!");
- throw new MOAIDException("init.04", new Object[] {
- moasession.getSessionID()});
+ // create process instance
+ String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext);
+
+ if (processDefinitionId == null) {
+ Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() );
+ throw new MOAIDException("process.02",new Object[] {
+ moasession.getSessionID()});
+ }
+
+ String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext);
+
+ // keep process instance id in moa session
+ moasession.setProcessInstanceId(processInstanceId);
+
+ // make sure moa session has been persisted before running the process
+ try {
+ AuthenticationSessionStoreage.storeSession(moasession);
+ } catch (MOADatabaseException e) {
+ Logger.error("Database Error! MOASession is not stored!");
+ throw new MOAIDException("init.04", new Object[] {
+ moasession.getSessionID()});
+ }
+
+ // start process
+ processEngine.start(processInstanceId);
+
+ } else {
+ //load Parameters from OnlineApplicationConfiguration
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance()
+ .getOnlineApplicationParameter(target.getOAURL());
+
+ if (oaParam == null) {
+ throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() });
+ }
+
+ else {
+
+ //check if an MOASession exists and if not create an new MOASession
+ //moasession = getORCreateMOASession(request);
+
+ //set OnlineApplication configuration in Session
+ moasession.setOAURLRequested(target.getOAURL());
+ moasession.setAction(target.requestedAction());
+ moasession.setModul(target.requestedModule());
+ }
+
+ //Build authentication form
+
+
+ String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix();
+ String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),
+ target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID());
+
+ //store MOASession
+ try {
+ AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());
+ } catch (MOADatabaseException e) {
+ Logger.error("Database Error! MOASession is not stored!");
+ throw new MOAIDException("init.04", new Object[] {
+ moasession.getSessionID()});
+ }
+
+ //set MOAIDSession
+ //request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID());
+
+ response.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+ out.print(loginForm);
+ out.flush();
}
-
- //set MOAIDSession
- //request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID());
-
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter out = new PrintWriter(response.getOutputStream());
- out.print(loginForm);
- out.flush();
+ } catch (ProcessExecutionException e) {
+ throw new MOAIDException("process.01", new Object[] { moasession.getProcessInstanceId(), moasession }, e);
}
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java
deleted file mode 100644
index a08ef5f0c..000000000
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright 2014 Federal Chancellery Austria
- * MOA-ID has been developed in a cooperation between BRZ, the Federal
- * Chancellery Austria - ICT staff unit, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * http://www.osor.eu/eupl/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-package at.gv.egovernment.moa.id.monitoring;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.hibernate.Query;
-import org.hibernate.Session;
-
-import at.gv.egovernment.moa.id.commons.db.ConfigurationDBRead;
-import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
-import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
-import at.gv.egovernment.moa.id.commons.db.StatisticLogDBUtils;
-import at.gv.egovernment.moa.id.commons.db.dao.config.MOAIDConfiguration;
-import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore;
-import at.gv.egovernment.moa.id.commons.db.dao.statistic.StatisticLog;
-import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.MiscUtil;
-
-public class DatabaseTestModule implements TestModuleInterface{
-
- public List<String> performTests() throws Exception {
- Logger.trace("Start MOA-ID Database Test.");
-
- List<String> errors = new ArrayList<String>();
-
- AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
-
- String error = testMOAConfigurationDatabase();
- if (MiscUtil.isNotEmpty(error))
- errors.add(error);
-
- error = testMOASessionDatabase();
- if (MiscUtil.isNotEmpty(error))
- errors.add(error);
-
- if (config.isAdvancedLoggingActive()) {
- error = testMOAAdvancedLoggingDatabase();
- if (MiscUtil.isNotEmpty(error))
- errors.add(error);
- }
-
- return errors;
- }
-
-
- private String testMOASessionDatabase() throws Exception{
- Logger.trace("Start Test: MOASessionDatabase");
-
- Date expioredate = new Date(new Date().getTime() - 120);
-
- try {
- List<AssertionStore> results;
- Session session = MOASessionDBUtils.getCurrentSession();
-
- synchronized (session) {
- session.beginTransaction();
- Query query = session.getNamedQuery("getAssertionWithTimeOut");
- query.setTimestamp("timeout", expioredate);
- results = query.list();
- session.getTransaction().commit();
- }
-
- Logger.trace("Finish Test: MOASessionDatabase");
- return null;
-
- } catch (Throwable e) {
- Logger.warn("Failed Test: MOASessionDatabase", e);
- return "MOASessionDatabase: " + e.getMessage();
- }
- }
-
- private String testMOAConfigurationDatabase() throws Exception{
-
- MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();
- ConfigurationDBUtils.closeSession();
-
- if (moaidconfig == null)
- return ("MOA-ID 2.x configuration can not be loaded from Database.");
-
- return null;
- }
-
- private String testMOAAdvancedLoggingDatabase() {
-
- Date expioredate = new Date(new Date().getTime() - 120);
- try {
- Session session = StatisticLogDBUtils.getCurrentSession();
-
- List<StatisticLog> results;
-
- synchronized (session) {
- session.beginTransaction();
- Query query = session.getNamedQuery("getAllEntriesNotBeforeTimeStamp");
- query.setTimestamp("timeout", expioredate);
- results = query.list();
- session.getTransaction().commit();
- }
-
- Logger.trace("Finish Test: AdvancedLoggingDataBase");
- return null;
-
- } catch (Throwable e) {
- Logger.warn("Failed Test: AdvancedLoggingDataBase", e);
- return "AdvancedLoggingDataBase: " + e.getMessage();
- }
- }
-
-
- public String getName() {
- return "DatabaseTest";
- }
-
-
- public void initializeTest(long delayParam, String url) throws Exception {
- // TODO Auto-generated method stub
-
- }
-}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java
deleted file mode 100644
index b5220914c..000000000
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * Copyright 2014 Federal Chancellery Austria
- * MOA-ID has been developed in a cooperation between BRZ, the Federal
- * Chancellery Austria - ICT staff unit, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * http://www.osor.eu/eupl/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-package at.gv.egovernment.moa.id.monitoring;
-
-import java.io.InputStream;
-import java.net.URL;
-import java.util.List;
-
-import org.w3c.dom.Element;
-
-import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder;
-import at.gv.egovernment.moa.id.auth.data.IdentityLink;
-import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
-import at.gv.egovernment.moa.id.auth.exception.ValidateException;
-import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker;
-import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
-import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;
-import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;
-import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator;
-import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
-import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
-import at.gv.egovernment.moa.id.config.auth.data.DynamicOAAuthParameters;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.MiscUtil;
-
-public class IdentityLinkTestModule implements TestModuleInterface {
-
- private static IdentityLink identityLink = null;
-
- public void initializeTest(long delayParam, String url) throws Exception{
-
- if (MiscUtil.isNotEmpty(url)) {
-
- URL keystoreURL = new URL(url);
- InputStream idlstream = keystoreURL.openStream();
- identityLink = new IdentityLinkAssertionParser(idlstream).parseIdentityLink();
- }
-
- }
-
- public List<String> performTests() throws Exception{
- Logger.trace("Start MOA-ID IdentityLink Test");
-
- AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
-
- IdentityLinkValidator.getInstance().validate(identityLink);
- // builds a <VerifyXMLSignatureRequest> for a call of MOA-SP
- Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder()
- .build(identityLink, config
- .getMoaSpIdentityLinkTrustProfileID());
-
- // invokes the call
- Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker()
- .verifyXMLSignature(domVerifyXMLSignatureRequest);
- // parses the <VerifyXMLSignatureResponse>
- try {
- VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(
- domVerifyXMLSignatureResponse).parseData();
-
- DynamicOAAuthParameters oaParam = new DynamicOAAuthParameters();
- oaParam.setBusinessService(true);
-
- VerifyXMLSignatureResponseValidator.getInstance().validate(
- verifyXMLSignatureResponse,
- config.getIdentityLinkX509SubjectNames(),
- VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK,
- oaParam);
-
- } catch (ValidateException e) {
- //check if default Monitoring IDL is used then error is ignored
- if ("validator.07".equals(e.getMessageId())
- && e.getMessage().contains("Das Zertifikat der Personenbindung ist"))
- return null;
-
- else
- throw e;
-
- }
-
- Logger.trace("Finished MOA-ID IdentityLink Test without errors");
-
- return null;
- }
-
- public String getName() {
- return "IdentityLinkTest";
- }
-
-}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java
deleted file mode 100644
index 84581abe8..000000000
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright 2014 Federal Chancellery Austria
- * MOA-ID has been developed in a cooperation between BRZ, the Federal
- * Chancellery Austria - ICT staff unit, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * http://www.osor.eu/eupl/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-package at.gv.egovernment.moa.id.monitoring;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import at.gv.egovernment.moa.id.config.ConfigurationException;
-import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.FileUtils;
-
-public class TestManager {
-
- private static TestManager instance;
-
- private Map<String, TestModuleInterface> tests = new HashMap<String, TestModuleInterface>();
-
- public static TestManager getInstance() throws ConfigurationException {
- if (instance == null)
- instance = new TestManager();
-
- return instance;
- }
-
- private TestManager() throws ConfigurationException {
-
- AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
-
- //add Database test
- DatabaseTestModule test1 = new DatabaseTestModule();
- tests.put(test1.getName(), test1);
-
- //add IdentityLink verification test
- IdentityLinkTestModule test2 = new IdentityLinkTestModule();
- String idlurl = FileUtils.makeAbsoluteURL(config.getMonitoringTestIdentityLinkURL(), config.getRootConfigFileDir());
- try {
- test2.initializeTest(0, idlurl);
- tests.put(test2.getName(), test2);;
-
- } catch (Exception e) {
- Logger.warn("MOA-ID IdentityLink Test can not performed without IdentityLink. Insert IdentityLink file to MOA-ID configuration", e);
- }
- }
-
- public List<String> executeTests() {
- Logger.debug("Start MOA-ID-Auth testing");
-
-
- List<String> errors;
-
- for (TestModuleInterface test : tests.values()) {
- try {
- errors = test.performTests();
- if (errors != null && errors.size() > 0)
- return errors;
-
- } catch (Exception e) {
- Logger.warn("General Testing Eception during Test " + test.getClass() + ": ", e);
- return Arrays.asList(e.getMessage());
- }
- }
-
- return null;
- }
-
- public List<String> executeTest(String testname) {
-
- TestModuleInterface test = tests.get(testname);
-
- if (test != null) {
- try {
- return test.performTests();
-
- } catch (Exception e) {
- Logger.warn("General Testing Eception during Test " + test.getName() + ": ", e);
- return Arrays.asList(e.getMessage());
- }
-
- } else {
- Logger.info("TestModule with Name " + testname + " is not implemented");
- return null;
- }
- }
-
- public boolean existsModule(String modulename) {
- return tests.containsKey(modulename);
- }
-}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java
new file mode 100644
index 000000000..080990f71
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java
@@ -0,0 +1,79 @@
+package at.gv.egovernment.moa.id.process;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * ExecutionContext implementation, related to a certain process instance.
+ *
+ * @author tknall
+ *
+ */
+public class ExecutionContextImpl implements ExecutionContext {
+
+ private static final long serialVersionUID = 1L;
+
+ private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>());
+
+ private String processInstanceId;
+
+ /**
+ * Creates a new instance.
+ */
+ public ExecutionContextImpl() {
+ }
+
+ /**
+ * Creates a new instance and associated it with a certain process instance.
+ */
+ public ExecutionContextImpl(String processInstanceId) {
+ this.processInstanceId = processInstanceId;
+ }
+
+ @Override
+ public void setProcessInstanceId(String processInstanceId) {
+ this.processInstanceId = processInstanceId;
+ }
+
+ @Override
+ public String getProcessInstanceId() {
+ return processInstanceId;
+ }
+
+ @Override
+ public Serializable get(String key) {
+ return ctxData.get(key);
+ }
+
+ @Override
+ public Serializable remove(String key) {
+ return ctxData.remove(key);
+ }
+
+ @Override
+ public void put(String key, Serializable object) {
+ ctxData.put(key, object);
+ }
+
+ @Override
+ public Set<String> keySet() {
+ return Collections.unmodifiableSet(ctxData.keySet());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("ExecutionContextImpl [");
+ builder.append("id=").append(processInstanceId);
+ builder.append(", variables=");
+ builder.append(ctxData.keySet());
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java
new file mode 100644
index 000000000..f0d1c861d
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java
@@ -0,0 +1,44 @@
+package at.gv.egovernment.moa.id.process;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext;
+
+/**
+ * Context implementation used for expression evaluation only.
+ *
+ * @author tknall
+ *
+ */
+public class ExpressionEvaluationContextImpl implements ExpressionEvaluationContext {
+
+ private static final long serialVersionUID = 1L;
+
+ private Map<String, Serializable> ctxData;
+
+ /**
+ * Creates a new instance and initializes it with data from a given process instance.
+ *
+ * @param processInstance
+ * The process instance.
+ */
+ ExpressionEvaluationContextImpl(ProcessInstance processInstance) {
+ ExecutionContext executionContext = processInstance.getExecutionContext();
+ Set<String> keys = executionContext.keySet();
+ ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>(keys.size()));
+ for (String key : keys) {
+ ctxData.put(key, executionContext.get(key));
+ }
+ }
+
+ @Override
+ public Map<String, Serializable> getCtx() {
+ return Collections.unmodifiableMap(ctxData);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java
new file mode 100644
index 000000000..162ee624a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java
@@ -0,0 +1,224 @@
+package at.gv.egovernment.moa.id.process;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.stream.util.EventReaderDelegate;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.process.model.EndEvent;
+import at.gv.egovernment.moa.id.process.model.ProcessDefinition;
+import at.gv.egovernment.moa.id.process.model.ProcessNode;
+import at.gv.egovernment.moa.id.process.model.StartEvent;
+import at.gv.egovernment.moa.id.process.model.TaskInfo;
+import at.gv.egovernment.moa.id.process.model.Transition;
+
+/**
+ * Parses an XML representation of a process definition as defined by the respective XML schema.
+ * <p/
+ * The parser is thread-safe.
+ * @author tknall
+ *
+ */
+public class ProcessDefinitionParser {
+
+ private static final String NS = "http://reference.e-government.gv.at/namespace/moa/process/definition/v1";
+
+ private static Logger log = LoggerFactory.getLogger(ProcessDefinitionParser.class);
+
+ private static class LazyProcessDefinitionSchemaHolder {
+ private static final Schema PD_SCHEMA_INSTANCE;
+ static {
+ try (InputStream in = ProcessDefinitionParser.class.getResourceAsStream("ProcessDefinition.xsd")) {
+ log.trace("Compiling process definition schema.");
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ // schema is thread-safe
+ PD_SCHEMA_INSTANCE = factory.newSchema(new StreamSource(in));
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to compile process definition schema.", e);
+ }
+ }
+ }
+
+ /**
+ * Parses an XML representation of a process definition. The representation is being validated in order to suffice
+ * the related XML schema.
+ *
+ * @param processDefinitionInputStream
+ * The process definition.
+ * @return A new process definition.
+ * @throws ProcessDefinitionParserException
+ * Thrown in case of error parsing the process definition.
+ */
+ public ProcessDefinition parse(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException {
+ XMLEventReader reader = null;
+ final ProcessDefinition pd = new ProcessDefinition();
+ log.debug("Parsing and validating process definition.");
+ try {
+
+ // Standard implementation of XMLInputFactory seems not to be thread-safe
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ reader = inputFactory.createXMLEventReader(processDefinitionInputStream);
+
+ final List<StartElement> transitionElements = new ArrayList<>();
+ final List<StartEvent> startEvents = new ArrayList<>();
+
+ reader = new EventReaderDelegate(reader) {
+
+ @Override
+ public XMLEvent nextEvent() throws XMLStreamException {
+ XMLEvent event = super.nextEvent();
+
+ switch (event.getEventType()) {
+ case XMLStreamConstants.START_ELEMENT:
+ StartElement element = event.asStartElement();
+ QName qname = element.getName();
+
+ if (NS.equals(qname.getNamespaceURI())) {
+ log.trace("Found process description element '{}'.", qname.getLocalPart());
+ Attribute id = element.getAttributeByName(new QName("id"));
+
+ switch (qname.getLocalPart()) {
+ case "ProcessDefinition":
+ if (id != null) {
+ pd.setId(id.getValue());
+ }
+ break;
+ case "StartEvent":
+ StartEvent startEvent = new StartEvent();
+ if (id != null) {
+ startEvent.setId(id.getValue());
+ }
+ startEvents.add(startEvent);
+ break;
+ case "EndEvent":
+ EndEvent endEvent = new EndEvent();
+ if (id != null) {
+ endEvent.setId(id.getValue());
+ pd.getEndEvents().put(id.getValue(), endEvent);
+ }
+ break;
+ case "Transition":
+ transitionElements.add(element);
+ break;
+ case "Task":
+ TaskInfo taskInfo = new TaskInfo();
+ if (id != null) {
+ taskInfo.setId(id.getValue());
+ pd.getTaskInfos().put(id.getValue(), taskInfo);
+ }
+ Attribute async = element.getAttributeByName(new QName("async"));
+ if (async != null) {
+ taskInfo.setAsync(Boolean.valueOf(async.getValue()));
+ }
+ Attribute implementingClass = element.getAttributeByName(new QName("class"));
+ if (implementingClass != null) {
+ taskInfo.setTaskImplementingClass(implementingClass.getValue());
+ }
+ break;
+ }
+
+ }
+
+ break;
+ }
+
+ return event;
+ }
+
+ };
+
+ // validator is not thread-safe
+ Validator validator = LazyProcessDefinitionSchemaHolder.PD_SCHEMA_INSTANCE.newValidator();
+ validator.validate(new StAXSource(reader));
+ log.trace("Process definition successfully schema validated.");
+
+ // perform some basic checks
+ log.trace("Building model and performing some plausibility checks.");
+ if (startEvents.size() != 1) {
+ throw new ProcessDefinitionParserException("A ProcessDefinition must contain exactly one single StartEvent.");
+ }
+ pd.setStartEvent(startEvents.get(0));
+
+ // link transitions
+ Iterator<StartElement> transitions = transitionElements.iterator();
+ while (transitions.hasNext()) {
+ StartElement element = transitions.next();
+ Transition transition = new Transition();
+ Attribute id = element.getAttributeByName(new QName("id"));
+ if (id != null) {
+ transition.setId(id.getValue());
+ }
+ Attribute conditionExpression = element.getAttributeByName(new QName("conditionExpression"));
+ if (conditionExpression != null) {
+ transition.setConditionExpression(conditionExpression.getValue());
+ }
+ Attribute from = element.getAttributeByName(new QName("from"));
+ if (from != null) {
+ ProcessNode fromNode = pd.getProcessNode(from.getValue());
+ if (fromNode == null) {
+ throw new ProcessDefinitionParserException("Transition's 'from'-attribute refers to a non-existing event or task '" + from.getValue() + '.');
+ }
+ if (fromNode instanceof EndEvent) {
+ throw new ProcessDefinitionParserException("Transition cannot start from end event.");
+ }
+ transition.setFrom(fromNode);
+ fromNode.getOutgoingTransitions().add(transition);
+ }
+ Attribute to = element.getAttributeByName(new QName("to"));
+ if (to != null) {
+ ProcessNode toNode = pd.getProcessNode(to.getValue());
+ if (toNode == null) {
+ throw new ProcessDefinitionParserException("Transition's 'to'-attribute refers to a non-existing event or task '" + to.getValue() + '.');
+ }
+ transition.setTo(toNode);
+ toNode.getIncomingTransitions().add(transition);
+ }
+ if (transition.getConditionExpression() == null && Objects.equals(transition.getFrom(), transition.getTo())) {
+ throw new ProcessDefinitionParserException("Transition's 'from' equals its 'to'. Since no 'conditionExpression' has been set this will cause a loop.");
+ }
+ }
+ log.debug("Process definition '{}' successfully parsed.", pd.getId());
+ return pd;
+
+ } catch (ProcessDefinitionParserException e) {
+ throw e;
+ } catch (XMLStreamException|IOException e) {
+ throw new ProcessDefinitionParserException("Unable to read process definition from inputstream.", e);
+ } catch (SAXException e) {
+ throw new ProcessDefinitionParserException("Schema validation of process description failed.", e);
+ } catch (Exception e) {
+ throw new ProcessDefinitionParserException("Internal error creating process definition from inputstream.", e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (XMLStreamException e) {
+ // error freeing resources
+ }
+ }
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java
new file mode 100644
index 000000000..0c214750d
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java
@@ -0,0 +1,35 @@
+package at.gv.egovernment.moa.id.process;
+
+/**
+ * Exception thrown in case of error parsing a process definition.
+ *
+ * @author tknall
+ *
+ */
+public class ProcessDefinitionParserException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new parser exception providing a {@code message} describing the reason and the {@code cause}.
+ *
+ * @param message
+ * The message.
+ * @param cause
+ * The cause.
+ */
+ public ProcessDefinitionParserException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new parser exception providing a {@code message} describing the reason.
+ *
+ * @param message
+ * The message.
+ */
+ public ProcessDefinitionParserException(String message) {
+ super(message);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java
new file mode 100644
index 000000000..5cf84abed
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java
@@ -0,0 +1,98 @@
+package at.gv.egovernment.moa.id.process;
+
+
+import java.io.InputStream;
+
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.model.ProcessDefinition;
+
+/**
+ * Process engine providing means for starting and resuming processes.
+ *
+ * @author tknall
+ */
+public interface ProcessEngine {
+
+ /**
+ * Registers a new process definition. Note that existing definitions with the same identifier will be replaced.
+ *
+ * @param processDefinition
+ * The process definition to be registered.
+ */
+ void registerProcessDefinition(ProcessDefinition processDefinition);
+
+ /**
+ * Registers a new process definition given as {@link InputStream}. Note that existing definitions with the same identifier will be replaced.
+ *
+ * @param processDefinitionInputStream The input stream to the definition to be registered.
+ * @throws ProcessDefinitionParserException Thrown in case of an error parsing the process definition.
+ * @return The process definition's identifier.
+ */
+ String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException;
+
+ /**
+ * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier.
+ * <p/>
+ * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue
+ * process execution after asynchronous task execution (refer to {@link #start(String)} and
+ * {@link #signal(String)} for further information).
+ *
+ * @param processDefinitionId
+ * The identifier of the respective process definition.
+ * @param executionContext The execution context (may be {@code null}).
+ * @return The id of the newly created process instance (never {@code null}).
+ * @throws ProcessExecutionException
+ * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist.
+ */
+ String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException;
+
+ /**
+ * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier.
+ * <p/>
+ * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue
+ * process execution after asynchronous task execution (refer to {@link #start(String)} and
+ * {@link #signal(String)} for further information).
+ *
+ * @param processDefinitionId
+ * The identifier of the respective process definition.
+ * @return The id of the newly created process instance (never {@code null}).
+ * @throws ProcessExecutionException
+ * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist.
+ */
+ String createProcessInstance(String processDefinitionId) throws ProcessExecutionException;
+
+ /**
+ * Returns the process instance with a given {@code processInstanceId}.
+ *
+ * @param processInstanceId
+ * The process instance id.
+ * @return The process instance (never {@code null}).
+ * @throws IllegalArgumentException
+ * In case the process instance does not/no longer exist.
+ * @throws RuntimeException
+ * In case the process instance could not be retrieved from persistence.
+ */
+ ProcessInstance getProcessInstance(String processInstanceId);
+
+ /**
+ * Starts the process using the given {@code processInstanceId}.
+ *
+ * @param processInstanceId
+ * The process instance id.
+ * @throws ProcessExecutionException
+ * Thrown in case of error.
+ */
+ void start(String processInstanceId) throws ProcessExecutionException;
+
+
+ /**
+ * Resumes process execution after an asynchronous task has been executed.
+ *
+ * @param processInstanceId
+ * The process instance id.
+ * @throws ProcessExecutionException
+ * Thrown in case of error.
+ */
+ void signal(String processInstanceId) throws ProcessExecutionException;
+
+} \ No newline at end of file
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java
new file mode 100644
index 000000000..096e5ee9e
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java
@@ -0,0 +1,356 @@
+package at.gv.egovernment.moa.id.process;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext;
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator;
+import at.gv.egovernment.moa.id.process.api.Task;
+import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore;
+import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO;
+import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl;
+import at.gv.egovernment.moa.id.process.model.EndEvent;
+import at.gv.egovernment.moa.id.process.model.ProcessDefinition;
+import at.gv.egovernment.moa.id.process.model.ProcessNode;
+import at.gv.egovernment.moa.id.process.model.StartEvent;
+import at.gv.egovernment.moa.id.process.model.TaskInfo;
+import at.gv.egovernment.moa.id.process.model.Transition;
+
+/**
+ * Process engine implementation allowing starting and continuing processes as well as providing means for cleanup actions.
+ */
+public class ProcessEngineImpl implements ProcessEngine {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ private ProcessDefinitionParser pdp = new ProcessDefinitionParser();
+
+ ProcessInstanceStoreDAO piStoreDao = ProcessInstanceStoreDAOImpl.getInstance();
+
+ private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>();
+
+ private final static String MDC_CTX_PI_NAME = "processInstanceId";
+ private final static String MDC_CTX_TASK_NAME = "taskId";
+
+ private ExpressionEvaluator transitionConditionExpressionEvaluator;
+
+ @Override
+ public void registerProcessDefinition(ProcessDefinition processDefinition) {
+ log.info("Registering process definition '{}'.", processDefinition.getId());
+ processDefinitions.put(processDefinition.getId(), processDefinition);
+ }
+
+ @Override
+ public String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException{
+ ProcessDefinition pd = pdp.parse(processDefinitionInputStream);
+ registerProcessDefinition(pd);
+ return pd.getId();
+ }
+
+ /**
+ * Sets the process definitions.
+ *
+ * @param processDefinitions
+ * The process definitions.
+ * @throws IllegalArgumentException
+ * In case the process definitions contain definitions with the same identifier.
+ */
+ public void setProcessDefinitions(Iterable<ProcessDefinition> processDefinitions) {
+ this.processDefinitions.clear();
+ for (ProcessDefinition pd : processDefinitions) {
+ if (this.processDefinitions.containsKey(pd.getId())) {
+ throw new IllegalArgumentException("Duplicate process definition identifier '" + pd.getId() + "'.");
+ }
+ registerProcessDefinition(pd);
+ }
+ }
+
+ /**
+ * Sets an expression evaluator that should be used to process transition condition expressions.
+ * @param transitionConditionExpressionEvaluator The expression evaluator.
+ */
+ public void setTransitionConditionExpressionEvaluator(
+ ExpressionEvaluator transitionConditionExpressionEvaluator) {
+ this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator;
+ }
+
+
+ @Override
+ public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException {
+ // look for respective process definition
+ ProcessDefinition pd = processDefinitions.get(processDefinitionId);
+ if (pd == null) {
+ throw new ProcessExecutionException("Unable to find process definition for process '" + processDefinitionId + "'.");
+ }
+ // create and keep process instance
+ ProcessInstance pi = new ProcessInstance(pd, executionContext);
+ log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId());
+
+ try {
+ saveOrUpdateProcessInstance(pi);
+ } catch (MOADatabaseException e) {
+ throw new ProcessExecutionException("Unable to persist process instance.", e);
+ }
+
+ return pi.getId();
+ }
+
+ @Override
+ public String createProcessInstance(String processDefinitionId) throws ProcessExecutionException {
+ return createProcessInstance(processDefinitionId, null);
+ }
+
+ @Override
+ public void start(String processInstanceId) throws ProcessExecutionException {
+
+ try {
+ ProcessInstance pi = loadProcessInstance(processInstanceId);
+
+ MDC.put(MDC_CTX_PI_NAME, pi.getId());
+
+ if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) {
+ throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has already been started (current state is " + pi.getState() + ").");
+ }
+ log.info("Starting process instance '{}'.", pi.getId());
+ // execute process
+ pi.setState(ProcessInstanceState.STARTED);
+ execute(pi);
+
+ saveOrUpdateProcessInstance(pi);
+ } catch (MOADatabaseException e) {
+ throw new ProcessExecutionException("Unable to load/save process instance.", e);
+
+ } finally {
+ MDC.remove(MDC_CTX_PI_NAME);
+ }
+ }
+
+ @Override
+ public void signal(String processInstanceId) throws ProcessExecutionException {
+
+ try {
+ ProcessInstance pi = loadProcessInstance(processInstanceId);
+
+ MDC.put(MDC_CTX_PI_NAME, pi.getId());
+
+ if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) {
+ throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has not been suspended (current state is " + pi.getState() + ").");
+ }
+
+ log.info("Waking up process instance '{}'.", pi.getId());
+ pi.setState(ProcessInstanceState.STARTED);
+ execute(pi);
+
+ saveOrUpdateProcessInstance(pi);
+ } catch (MOADatabaseException e) {
+ throw new ProcessExecutionException("Unable to load/save process instance.", e);
+
+ } finally {
+ MDC.remove(MDC_CTX_PI_NAME);
+ }
+ }
+
+
+ /**
+ * Instantiates a task implementation given by a {@link TaskInfo}.
+ * @param ti The task info.
+ * @return A Task implementation or {@code null} if the task info does not reference any task implementing classes.
+ * @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance).
+ */
+ private Task createTaskInstance(TaskInfo ti) throws ProcessExecutionException {
+ String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass());
+ Task task = null;
+
+ if (clazz != null) {
+ log.debug("Instantiating task implementing class '{}'.", clazz);
+ Class<?> instanceClass = null;
+ try {
+ instanceClass = Class.forName(clazz, true, Thread.currentThread().getContextClassLoader());
+ } catch (Exception e) {
+ throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e);
+ }
+ if (!Task.class.isAssignableFrom(instanceClass)) {
+ throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + ti.getId() + "' is not assignable to " + Task.class.getName() + ".");
+ }
+ try {
+ task = (Task) instanceClass.newInstance();
+ } catch (Exception e) {
+ throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e);
+ }
+ }
+
+ return task;
+ }
+
+ /**
+ * Starts/executes a given process instance.
+ * @param pi The process instance.
+ * @throws ProcessExecutionException Thrown in case of error.
+ */
+ private void execute(final ProcessInstance pi) throws ProcessExecutionException {
+ if (ProcessInstanceState.ENDED.equals(pi.getState())) {
+ throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended.");
+ }
+ ProcessDefinition pd = pi.getProcessDefinition();
+ ProcessNode processNode = pd.getProcessNode(pi.getNextId());
+ log.debug("Processing node '{}'.", processNode.getId());
+
+ // distinguish process node types StartEvent, TaskInfo and EndEvent
+
+ if (processNode instanceof TaskInfo) {
+ // TaskInfo types need to be executed
+ TaskInfo ti = (TaskInfo) processNode;
+ MDC.put(MDC_CTX_TASK_NAME, ti.getId());
+ try {
+ log.info("Processing task '{}'.", ti.getId());
+ Task task = createTaskInstance(ti);
+ if (task != null) {
+ try {
+ log.info("Executing task implementation for task '{}'.", ti.getId());
+ log.debug("Execution context before task execution: {}", pi.getExecutionContext().keySet());
+ task.execute(pi.getExecutionContext());
+ log.info("Returned from execution of task '{}'.", ti.getId());
+ log.debug("Execution context after task execution: {}", pi.getExecutionContext().keySet());
+ } catch (Throwable t) {
+ throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t);
+ }
+ } else {
+ log.debug("No task implementing class set.");
+ }
+ } finally {
+ MDC.remove(MDC_CTX_TASK_NAME);
+ }
+
+ } else if (processNode instanceof EndEvent) {
+ log.info("Finishing process instance '{}'.", pi.getId());
+
+ try {
+ piStoreDao.remove(pi.getId());
+ } catch (MOADatabaseException e) {
+ throw new ProcessExecutionException("Unable to remove process instance.", e);
+ }
+ pi.setState(ProcessInstanceState.ENDED);
+ log.debug("Final process context: {}", pi.getExecutionContext().keySet());
+ return;
+ }
+
+ final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi);
+
+ // traverse pointer
+ Transition t = CollectionUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() {
+ @Override
+ public boolean evaluate(Transition transition) {
+ if (transitionConditionExpressionEvaluator != null && transition.getConditionExpression() != null) {
+ log.trace("Evaluating transition expression '{}'.", transition.getConditionExpression());
+ return transitionConditionExpressionEvaluator.evaluate(expressionContext, transition.getConditionExpression());
+ }
+ return true;
+ }
+ });
+ if (t == null) {
+ throw new ProcessExecutionException("No valid transition starting from process node '" + processNode.getId()+ "'.");
+ }
+ log.trace("Found suitable transition: {}", t);
+ // update pointer
+ log.trace("Shifting process token from '{}' to '{}'.", pi.getNextId(), t.getTo().getId());
+ pi.setNextId(t.getTo().getId());
+
+ // inspect current task
+ if (t.getTo() instanceof TaskInfo && (((TaskInfo) t.getTo()).isAsync())) {
+ // immediately return in case of asynchonous task
+ log.info("Suspending process instance '{}' for asynchronous task '{}'.", pi.getId(), t.getTo().getId());
+ pi.setState(ProcessInstanceState.SUSPENDED);
+ return;
+ }
+
+ // continue execution in case of StartEvent or Task
+ if (processNode instanceof StartEvent || processNode instanceof TaskInfo) {
+ execute(pi);
+ }
+ }
+
+ @Override
+ public ProcessInstance getProcessInstance(String processInstanceId) {
+
+ ProcessInstance processInstance;
+ try {
+ processInstance = loadProcessInstance(processInstanceId);
+
+ } catch (MOADatabaseException e) {
+ throw new RuntimeException("The process instance '" + processInstanceId + "' could not be retrieved.", e);
+ }
+
+ if (processInstance == null) {
+ throw new IllegalArgumentException("The process instance '" + processInstanceId + "' does not/no longer exist.");
+ }
+
+ return processInstance;
+ }
+
+ /**
+ * Persists a {@link ProcessInstance} to the database.
+ * @param processInstance The object to persist.
+ * @throws MOADatabaseException Thrown if an error occurs while accessing the database.
+ */
+ private void saveOrUpdateProcessInstance(ProcessInstance processInstance) throws MOADatabaseException {
+ ProcessInstanceStore store = new ProcessInstanceStore();
+
+ ExecutionContext ctx = processInstance.getExecutionContext();
+
+ Map<String, Serializable> ctxData = new HashMap<String, Serializable>();
+ for (String key : ctx.keySet()) {
+ ctxData.put(key, ctx.get(key));
+ }
+ store.setExecutionContextData(ctxData);
+
+ store.setNextTaskId(processInstance.getNextId());
+ store.setProcessDefinitionId(processInstance.getProcessDefinition().getId());
+
+ store.setProcessInstanceId(processInstance.getId());
+ store.setProcessState(processInstance.getState());
+
+ piStoreDao.saveOrUpdate(store);
+ }
+
+ /**
+ * Load a {@link ProcessInstance} with a certain id from the database.
+ * @param processInstanceId The process instance id
+ * @return The process instance corresponding to the id or {@code null} if no such object is found.
+ * @throws MOADatabaseException Thrown if an error occurs while accessing the database.
+ */
+ private ProcessInstance loadProcessInstance(String processInstanceId) throws MOADatabaseException {
+
+ ProcessInstanceStore piStore = piStoreDao.load(processInstanceId);
+
+ if (piStore == null) {
+ return null;
+ }
+
+ ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId());
+
+ Map<String, Serializable> executionContextData = piStore.getExecutionContextData();
+ for (String key : executionContextData.keySet()) {
+ executionContext.put(key, executionContextData.get(key));
+ }
+
+ ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext);
+ pi.setNextId(piStore.getNextTaskId());
+ pi.setState(piStore.getProcessState());
+
+ return pi;
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java
new file mode 100644
index 000000000..821bbe6dc
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java
@@ -0,0 +1,36 @@
+package at.gv.egovernment.moa.id.process;
+
+/**
+ * Indicates a problem when executing a process.
+ *
+ * @author tknall
+ *
+ */
+public class ProcessExecutionException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new process execution exception providing a {@code message} describing the reason and the respective
+ * {@code cause}.
+ *
+ * @param message
+ * The message.
+ * @param cause
+ * The cause.
+ */
+ public ProcessExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new process execution exception providing a {@code message} describing the reason.
+ *
+ * @param message
+ * The message.
+ */
+ public ProcessExecutionException(String message) {
+ super(message);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java
new file mode 100644
index 000000000..a6cf3b57f
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java
@@ -0,0 +1,164 @@
+package at.gv.egovernment.moa.id.process;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.time.DurationFormatUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.model.ProcessDefinition;
+import at.gv.egovernment.moa.id.process.support.SecureRandomHolder;
+
+/**
+ * Represents a process being executed. The process instance provides information about the process and its state.
+ *
+ * @author tknall
+ *
+ */
+public class ProcessInstance implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private static final int RND_ID_LENGTH = 22;
+
+ private ProcessDefinition processDefinition;
+ private String nextId;
+ private Date lru;
+ private ExecutionContext executionContext;
+ private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED;
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * Creates a new process instance, based on a given process definition and a
+ * given execution context. If the given execution context is {@code null} a new execution context will be created.<p/>
+ * The process instance id of the execution context will be newly generated if it is {@code null} in the execution context.
+ *
+ * @param processDefinition
+ * The process definition.
+ * @param executionContext
+ * The execution context (may be {@code null}). If {@code null} a new execution context will be created internally.
+ */
+ ProcessInstance(ProcessDefinition processDefinition, ExecutionContext executionContext) {
+ this.processDefinition = processDefinition;
+ nextId = processDefinition.getStartEvent().getId();
+ if (executionContext == null) {
+ executionContext = new ExecutionContextImpl();
+ }
+ if (executionContext.getProcessInstanceId() == null) {
+ String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null,
+ SecureRandomHolder.getInstance());
+ executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart);
+ } else {
+ log.debug("Using process instance id from execution context.");
+ }
+ log.debug("Creating process instance with id '{}'.", executionContext.getProcessInstanceId());
+ this.executionContext = executionContext;
+ touch();
+ }
+
+ /**
+ * Returns the underlying process definition.
+ *
+ * @return The underlying process definition.
+ */
+ ProcessDefinition getProcessDefinition() {
+ touch();
+ return processDefinition;
+ }
+
+ /**
+ * Returns the id of the process node to be executed next.
+ *
+ * @return The process node pointer indicating the process node to be executed next.
+ */
+ public String getNextId() {
+ touch();
+ return nextId;
+ }
+
+ /**
+ * Sets the internal pointer to the process node to be executed next.
+ *
+ * @param nextId
+ * The process node id to be executed next.
+ */
+ void setNextId(String nextId) {
+ touch();
+ this.nextId = nextId;
+ }
+
+ /**
+ * Returns the current state of the process instance.
+ *
+ * @return The current state.
+ */
+ public ProcessInstanceState getState() {
+ touch();
+ return state;
+ }
+
+ /**
+ * Sets the current state of the process instance.
+ *
+ * @param state
+ * The current state.
+ */
+ void setState(ProcessInstanceState state) {
+ touch();
+ this.state = state;
+ }
+
+ public String getId() {
+ touch();
+ return executionContext.getProcessInstanceId();
+ }
+
+ /**
+ * Updates the last recently used date of the process instance.
+ */
+ private void touch() {
+ lru = new Date();
+ }
+
+ /**
+ * Returns the date the process instance has been accessed last.
+ *
+ * @return The last recently used date.
+ */
+ Date getLru() {
+ return lru;
+ }
+
+ /**
+ * Returns the associated execution context.
+ * @return The execution context (never {@code null}).
+ */
+ public ExecutionContext getExecutionContext() {
+ touch();
+ return executionContext;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("ProcessInstance [");
+ builder.append("id=").append(executionContext.getProcessInstanceId());
+ builder.append(", idle since=").append(
+ DurationFormatUtils.formatDurationWords(new Date().getTime() - this.lru.getTime(), true, true));
+ if (processDefinition != null) {
+ builder.append(", processDefinition.id=");
+ builder.append(processDefinition.getId());
+ }
+ if (nextId != null) {
+ builder.append(", nextId=");
+ builder.append(nextId);
+ }
+ builder.append(", executionContext=").append(executionContext);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java
new file mode 100644
index 000000000..2765283a0
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java
@@ -0,0 +1,30 @@
+package at.gv.egovernment.moa.id.process;
+
+/**
+ * Represents a certain process instance state.
+ * @author tknall
+ *
+ */
+public enum ProcessInstanceState {
+
+ /**
+ * Indicates that the process with this process instance has not yet been started.
+ */
+ NOT_STARTED,
+
+ /**
+ * Indicates that the process is currently running.
+ */
+ STARTED,
+
+ /**
+ * Indicates that the process has been suspended until being waken up by someonce calling {@code signal}.
+ */
+ SUSPENDED,
+
+ /**
+ * Indicates that the process has been completed.
+ */
+ ENDED
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java
new file mode 100644
index 000000000..4a9dfc336
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java
@@ -0,0 +1,63 @@
+package at.gv.egovernment.moa.id.process.api;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * Encapsulates data needed for or provided by task execution.
+ *
+ * @author tknall
+ *
+ */
+public interface ExecutionContext extends Serializable {
+
+ /**
+ * Returns the identifier of underlying process instance.
+ *
+ * @return The identifier of the process instance.
+ */
+ String getProcessInstanceId();
+
+ /**
+ * Sets the identifier of underlying process instance.
+ *
+ * @param processInstanceId
+ * The identifier of the process instance.
+ */
+ void setProcessInstanceId(String processInstanceId);
+
+ /**
+ * Stores a serializable object using {@code key}.
+ *
+ * @param key
+ * The key under that the {@code object} should be stored.
+ * @param object The object to be stored.
+ */
+ void put(String key, Serializable object);
+
+ /**
+ * Returns an serializable object stored within this process context using {@code key}.
+ *
+ * @param key
+ * The key that has been used to store the serializable object (may be {@code null}).
+ * @return The object or {@code null} in case the key does not relate to a stored object or the stored object itself
+ * was {@code null}.
+ */
+ Serializable get(String key);
+
+ /**
+ * Removes the object stored using {@code key}.
+ * @param key
+ * The key that has been used to store the serializable object (may be {@code null}).
+ * @return The object that has been removed or {@code null} there was no object stored using {@code key}.
+ */
+ Serializable remove(String key);
+
+ /**
+ * Returns an unmodifiable set containing the stored keys.
+ *
+ * @return The keyset (never {@code null}).
+ */
+ Set<String> keySet();
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java
new file mode 100644
index 000000000..94854dcad
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java
@@ -0,0 +1,23 @@
+package at.gv.egovernment.moa.id.process.api;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.process.model.Transition;
+
+/**
+ * Context used for evaluation of condition expressions set for {@linkplain Transition Transitions}.
+ *
+ * @author tknall
+ *
+ */
+public interface ExpressionEvaluationContext extends Serializable {
+
+ /**
+ * Returns the context data map used for expression evaluation.
+ *
+ * @return An unmodifiable map (never {@code null}).
+ */
+ Map<String, Serializable> getCtx();
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java
new file mode 100644
index 000000000..fe0743201
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java
@@ -0,0 +1,25 @@
+package at.gv.egovernment.moa.id.process.api;
+
+/**
+ * Evaluates a given {@code expression} returning a boolean value.
+ *
+ * @author tknall
+ */
+public interface ExpressionEvaluator {
+
+ /**
+ * Evaluates a given {@code expression} returning a boolean value.
+ *
+ * @param expressionContext
+ * The context which can be used for evaluation of the expression.
+ * @param expression
+ * The expression resulting in a boolean (must not be {@code null}).
+ * @return A boolean value.
+ * @throws IllegalArgumentException
+ * In case of an invalid {@code expression}.
+ * @throws NullPointerException
+ * In case of a {@code null} expression.
+ */
+ boolean evaluate(ExpressionEvaluationContext expressionContext, String expression);
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java
new file mode 100644
index 000000000..343b8fe0c
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java
@@ -0,0 +1,23 @@
+package at.gv.egovernment.moa.id.process.api;
+
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+
+
+/**
+ * Represents a single task to be performed upon process execution.
+ *
+ * @author tknall
+ *
+ */
+public interface Task {
+
+ /**
+ * Executes this task.
+ *
+ * @param executionContext
+ * Provides execution related information.
+ * @throws Exception An exception upon task execution.
+ */
+ void execute(ExecutionContext executionContext) throws TaskExecutionException;
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java
new file mode 100644
index 000000000..d690c37bf
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java
@@ -0,0 +1,89 @@
+package at.gv.egovernment.moa.id.process.dao;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+
+import org.hibernate.internal.util.SerializationHelper;
+
+import at.gv.egovernment.moa.id.process.ProcessInstanceState;
+
+@Entity
+@Table(name = "processinstance")
+public class ProcessInstanceStore {
+
+ /**
+ * A process instance identifier qualifies as natural primary key by satisfying these requirements
+ * ("unique, constant, required"):
+ * <ul>
+ * <li>unique value</li>
+ * <li>never changes (immutable)</li>
+ * <li>never {@code null}</li>
+ * </ul>
+ */
+ @Id
+ private String processInstanceId;
+
+ @Column(name = "processDefinitionId", nullable = false)
+ private String processDefinitionId;
+
+ @Column(name = "nextTaskId", nullable = false)
+ private String nextTaskId;
+
+ @Column(name = "processState", nullable = false)
+ @Enumerated(value = EnumType.STRING)
+ private ProcessInstanceState processState;
+
+ @Column(name = "executionContextData", nullable = false)
+ @Lob
+ private byte[] executionContextData;
+
+ public String getProcessInstanceId() {
+ return processInstanceId;
+ }
+
+ public String getProcessDefinitionId() {
+ return processDefinitionId;
+ }
+
+ public String getNextTaskId() {
+ return nextTaskId;
+ }
+
+ public ProcessInstanceState getProcessState() {
+ return processState;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, Serializable> getExecutionContextData() {
+ return (Map<String, Serializable>) SerializationHelper.deserialize(executionContextData);
+ }
+
+ public void setProcessInstanceId(String processInstanceId) {
+ this.processInstanceId = processInstanceId;
+ }
+
+ public void setProcessDefinitionId(String processDefinitionId) {
+ this.processDefinitionId = processDefinitionId;
+ }
+
+ public void setNextTaskId(String nextTaskId) {
+ this.nextTaskId = nextTaskId;
+ }
+
+ public void setProcessState(ProcessInstanceState processState) {
+ this.processState = processState;
+ }
+
+ public void setExecutionContextData(Map<String, Serializable> executionContextData) {
+ this.executionContextData = SerializationHelper.serialize((Serializable) executionContextData);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java
new file mode 100644
index 000000000..57ce70c08
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java
@@ -0,0 +1,43 @@
+package at.gv.egovernment.moa.id.process.dao;
+
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.ProcessInstance;
+
+public interface ProcessInstanceStoreDAO {
+
+ /**
+ * Stores a {@link ProcessInstance} defined by {@code pIStore} in the
+ * database.
+ *
+ * @param pIStore
+ * the {@link ProcessInstanceStore} to persist.
+ * @throws MOADatabaseException
+ * is thrown if a problem occurs while accessing the database.
+ */
+ void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException;
+
+ /**
+ * Returns a {@link ProcessInstanceStore}, defined by
+ * {@code processInstanceID} from the database, or {@code null} if the
+ * object could not be found.
+ *
+ * @param processInstanceId
+ * the id of the {@code ProcessInstanceStore} to retrieve.
+ * @return a ProcessInstanceStore, or {@code null}.
+ * @throws MOADatabaseException
+ * is thrown if a problem occurs while accessing the database.
+ */
+ ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException;
+
+ /**
+ * Deletes the {@link ProcessInstance} corresponding with the
+ * {@code processInstanceId}.
+ *
+ * @param processInstanceId
+ * the id of the {@code ProcessInstance} to be deleted.
+ * @throws MOADatabaseException
+ * is thrown if a problem occurs while accessing the database.
+ */
+ void remove(String processInstanceId) throws MOADatabaseException;
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java
new file mode 100644
index 000000000..012dfe90b
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java
@@ -0,0 +1,90 @@
+package at.gv.egovernment.moa.id.process.dao;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+
+/**
+ * Database backed implementation of the {@link ProcessInstanceStoreDAO}
+ * interface.
+ */
+public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ private static ProcessInstanceStoreDAO instance = new ProcessInstanceStoreDAOImpl();
+
+ public static ProcessInstanceStoreDAO getInstance() {
+ return instance;
+ }
+
+ @Override
+ public void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException {
+ try {
+ MOASessionDBUtils.saveOrUpdate(pIStore);
+ log.debug("Store process instance with='{}' in the database.", pIStore.getProcessInstanceId());
+ } catch (MOADatabaseException e) {
+ log.warn("ProcessInstanceStore could not be persisted to the database.");
+ throw e;
+ }
+ }
+
+ @Override
+ public ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException {
+
+ log.debug("Retrieve the ProcessInstanceStore for id='{}' from the database.", processInstanceId);
+ Session session = MOASessionDBUtils.getCurrentSession();
+
+ ProcessInstanceStore result = null;
+ Transaction tx = null;
+ synchronized (session) {
+ try {
+
+ tx = session.beginTransaction();
+ // select all where processInstanceId equals processInstanceId
+ Criteria criteria = session.createCriteria(ProcessInstanceStore.class);
+ criteria.add(Restrictions.eq("processInstanceId", processInstanceId));
+ result = (ProcessInstanceStore) criteria.uniqueResult();
+ tx.commit();
+
+ } catch (Exception e) {
+ log.error("There are multiple persisted processes with the same process instance id '{}'",
+ processInstanceId);
+ if (tx != null) {
+ tx.rollback();
+ }
+ throw e;
+ } finally {
+ MOASessionDBUtils.closeSession();
+ }
+ }
+ if (result != null) {
+ log.debug("Found process instance store for instance '{}'.", processInstanceId);
+ } else {
+ log.debug("Unable to find process instance store for instance '{}'.", processInstanceId);
+ }
+ return result;
+ }
+
+ @Override
+ public void remove(String processInstanceId) throws MOADatabaseException {
+
+ log.debug("Delete the ProcessInstanceStore for id='{}' from the database.", processInstanceId);
+ ProcessInstanceStore toBeDeleted = load(processInstanceId);
+ if (toBeDeleted != null) {
+ if (!MOASessionDBUtils.delete(toBeDeleted)) {
+ log.warn("Could not delete the ProcessInstanceStore with process instance id '{}'", processInstanceId);
+ throw new MOADatabaseException("Could not delete the ProcessInstanceStore with process instance id '"
+ + processInstanceId + "'.");
+ }
+ } else
+ log.trace("ProcessInstanceStore for id='{}' was not found and could therefore not be deleted.", processInstanceId);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java
new file mode 100644
index 000000000..49fb082ea
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java
@@ -0,0 +1,42 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.io.Serializable;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+/**
+ * Represents an end event. Process execution terminates when an end event is reached.
+ *
+ * @author tknall
+ */
+public class EndEvent extends ProcessNode implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("EndEvent [");
+ if (getId() != null) {
+ builder.append("id=");
+ builder.append(getId());
+ }
+ if (CollectionUtils.isNotEmpty(getIncomingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("incomingTransitions=");
+ builder.append(getIncomingTransitions());
+ }
+ if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("outgoingTransitions=");
+ builder.append(getOutgoingTransitions());
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java
new file mode 100644
index 000000000..518409ecf
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java
@@ -0,0 +1,158 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import at.gv.egovernment.moa.id.process.ProcessDefinitionParser;
+
+/**
+ * Represents a single process definition containing
+ * <ul>
+ * <li>a {@link StartEvent},</li>
+ * <li>one or more {@linkplain TaskInfo Tasks},</li>
+ * <li>one or more {@linkplain EndEvent EndEvents} and</li>
+ * <li>some {@linkplain Transition Transitions} linking StartEvents, Tasks and EndEvents.
+ * </ul>
+ *
+ * @author tknall
+ *
+ */
+public class ProcessDefinition {
+
+ private String id;
+ private StartEvent startEvent;
+ private Map<String, TaskInfo> taskInfos = new LinkedHashMap<>();
+ private Map<String, EndEvent> endEvents = new LinkedHashMap<>();
+
+ /**
+ * Returns the unique identifier of the process definition.
+ *
+ * @return The unique identifier (never {@code null} if process definition comes from
+ * {@link ProcessDefinitionParser}).
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the unique identifier of the process definition.
+ *
+ * @param id
+ * The unique identifier.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the start event of the process definition.
+ *
+ * @return The start event (never {@code null} if process definition comes from {@link ProcessDefinitionParser}).
+ */
+ public StartEvent getStartEvent() {
+ return startEvent;
+ }
+
+ /**
+ * Sets the start event of the process definition.
+ *
+ * @param startEvent
+ * The start event.
+ */
+ public void setStartEvent(StartEvent startEvent) {
+ this.startEvent = startEvent;
+ }
+
+ /**
+ * Returns a map containing the tasks of the process definition.
+ *
+ * @return The tasks (map is never {@code null} if process definition comes from {@link ProcessDefinitionParser}).
+ */
+ public Map<String, TaskInfo> getTaskInfos() {
+ return taskInfos;
+ }
+
+ /**
+ * Sets the map containing the tasks.
+ *
+ * @param taskInfos
+ * The map containing the tasks.
+ */
+ public void setTaskInfos(Map<String, TaskInfo> taskInfos) {
+ this.taskInfos = taskInfos;
+ }
+
+ /**
+ * Returns a map containing the end events of the process description.
+ *
+ * @return The map containing the end events (map is never {@code null} if process definition comes from
+ * {@link ProcessDefinitionParser}).
+ */
+ public Map<String, EndEvent> getEndEvents() {
+ return endEvents;
+ }
+
+ /**
+ * Sets a map containing the end events of the process description.
+ *
+ * @param endEvents
+ * The map containing the end events.
+ */
+ public void setEndEvents(Map<String, EndEvent> endEvents) {
+ this.endEvents = endEvents;
+ }
+
+ /**
+ * Returns the process node associated with the given {@code id}.
+ *
+ * @param id
+ * The identifier of the process node.
+ * @return The process node (may be {code null} when no process node with the given {@code id} exists).
+ */
+ public ProcessNode getProcessNode(String id) {
+ Objects.requireNonNull(id, "Identifier must not be null.");
+ if (startEvent != null && id.equals(startEvent.getId())) {
+ return startEvent;
+ }
+ TaskInfo task = taskInfos.get(id);
+ if (task != null) {
+ return task;
+ }
+ return endEvents.get(id);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ if (id != null) {
+ builder.append("id=");
+ builder.append(id);
+ }
+ if (startEvent != null) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("startEvent=");
+ builder.append(startEvent);
+ }
+ if (taskInfos != null && !taskInfos.isEmpty()) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("tasksInfos=");
+ builder.append(taskInfos.values());
+ }
+ if (endEvents != null && !endEvents.isEmpty()) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("endEvents=");
+ builder.append(endEvents.values());
+ }
+ builder.insert(0, "ProcessDefinition [");
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java
new file mode 100644
index 000000000..42f2e3cc2
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java
@@ -0,0 +1,69 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import at.gv.egovernment.moa.id.process.ProcessDefinitionParser;
+
+/**
+ * Represents a {@link StartEvent}, an {@link EndEvent} or a {@linkplain TaskInfo Task}.
+ * @author tknall
+ *
+ */
+public abstract class ProcessNode {
+
+ private String id;
+ private List<Transition> outgoingTransitions = new ArrayList<>();
+ private List<Transition> incomingTransitions = new ArrayList<>();
+
+ /**
+ * Returns the unique identifier of the process node.
+ *
+ * @return The unique identifier (never {@code null} if process node comes from a process definition from
+ * {@link ProcessDefinitionParser}).
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the unique identifier of the process node.
+ * @param id The unique identifier.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns a list of transitions pointing from this process node to another one.
+ * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}).
+ */
+ public List<Transition> getOutgoingTransitions() {
+ return outgoingTransitions;
+ }
+
+ /**
+ * Sets the list of transitions pointing from this process node to another one.
+ * @param outgoingTransitions The list of transitions originating from this process node.
+ */
+ public void setOutgoingTransitions(List<Transition> outgoingTransitions) {
+ this.outgoingTransitions = outgoingTransitions;
+ }
+
+ /**
+ * Returns a list of transitions pointing from another process node to this one.
+ * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}).
+ */
+ public List<Transition> getIncomingTransitions() {
+ return incomingTransitions;
+ }
+
+ /**
+ * Sets the list of transitions pointing from another process node to this one.
+ * @param incomingTransitions A list of transitions pointing to this process node.
+ */
+ public void setIncomingTransitions(List<Transition> incomingTransitions) {
+ this.incomingTransitions = incomingTransitions;
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java
new file mode 100644
index 000000000..60175e09c
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java
@@ -0,0 +1,45 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.io.Serializable;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+/**
+ * Represents a start event. Each process description contains a single start event. Process execution starts with a
+ * start event.
+ *
+ * @author tknall
+ *
+ */
+public class StartEvent extends ProcessNode implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("StartEvent [");
+ if (getId() != null) {
+ builder.append("id=");
+ builder.append(getId());
+ }
+ if (CollectionUtils.isNotEmpty(getIncomingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("incomingTransitions=");
+ builder.append(getIncomingTransitions());
+ }
+ if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("outgoingTransitions=");
+
+ builder.append(getOutgoingTransitions());
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java
new file mode 100644
index 000000000..78a9d6a0a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java
@@ -0,0 +1,94 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.io.Serializable;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import at.gv.egovernment.moa.id.process.api.Task;
+
+/**
+ * Represents information about a single task to be performed upon process execution.
+ * @author tknall
+ *
+ */
+public class TaskInfo extends ProcessNode implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private static final boolean DEFAULT_ASYNC = false;
+
+ private String taskImplementingClass;
+ private boolean async = DEFAULT_ASYNC;
+
+ /**
+ * Determines if the task is marked asynchronous ({@code true}) or synchronous ({@code false}).
+ * @return A flag indicating if the task should be executed asynchronously or synchronously. (Default: {@code false})
+ */
+ public boolean isAsync() {
+ return async;
+ }
+
+ /**
+ * Marks a task to executed asynchronously ({@code true}) or synchronously ({@code false}).
+ * @param async The flag.
+ */
+ public void setAsync(boolean async) {
+ this.async = async;
+ }
+
+ /**
+ * Returns the class that implements the actual task (must implement {@link Task}).
+ * @return The task implementing class.
+ */
+ public String getTaskImplementingClass() {
+ return taskImplementingClass;
+ }
+
+ /**
+ * Sets the class that implements the actual task (must implement {@link Task}).
+ * @param taskImplementingClass The task implementing class.
+ */
+ public void setTaskImplementingClass(String taskImplementingClass) {
+ this.taskImplementingClass = taskImplementingClass;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ if (getId() != null) {
+ builder.append("id=");
+ builder.append(getId());
+ }
+ if (async != DEFAULT_ASYNC) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("async=");
+ builder.append(async);
+ }
+ if (taskImplementingClass != null) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("taskImplementingClass=");
+ builder.append(taskImplementingClass);
+ }
+ if (CollectionUtils.isNotEmpty(getIncomingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("incomingTransitions=");
+ builder.append(getIncomingTransitions());
+ }
+ if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("outgoingTransitions=");
+ builder.append(getOutgoingTransitions());
+ }
+ builder.insert(0, "TaskInfo [");
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java
new file mode 100644
index 000000000..bc3005534
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java
@@ -0,0 +1,136 @@
+package at.gv.egovernment.moa.id.process.model;
+
+import java.io.Serializable;
+
+import at.gv.egovernment.moa.id.process.ProcessDefinitionParser;
+
+/**
+ * Represents a single transition from a {@link StartEvent} or {@linkplain TaskInfo Task} to another
+ * {@linkplain TaskInfo Task} or {@link EndEvent}.
+ *
+ * @author tknall
+ *
+ */
+public class Transition implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String id;
+ private String conditionExpression;
+ private ProcessNode from;
+ private ProcessNode to;
+
+ /**
+ * Returns the process node (effectively a {@link StartEvent} or {@linkplain TaskInfo Task}) the transition is
+ * pointing from.
+ *
+ * @return The transition's source process node (never {@code null} if transition comes from a process definition
+ * from {@link ProcessDefinitionParser}).
+ */
+ public ProcessNode getFrom() {
+ return from;
+ }
+
+ /**
+ * Sets the process node the transition is pointing from.
+ *
+ * @param from
+ * The transition's source process node.
+ */
+ public void setFrom(ProcessNode from) {
+ this.from = from;
+ }
+
+ /**
+ * Returns the process node (effectively a {@linkplain TaskInfo Task} or {@link EndEvent}) the transition is
+ * pointing to.
+ *
+ * @return The transition's destination process node (never {@code null} if transition comes from a process
+ * definition from {@link ProcessDefinitionParser}).
+ */
+ public ProcessNode getTo() {
+ return to;
+ }
+
+ /**
+ * Sets the process node the transition is pointing to.
+ *
+ * @param to
+ * The transition's destination process node.
+ */
+ public void setTo(ProcessNode to) {
+ this.to = to;
+ }
+
+ /**
+ * Returns the unique identifier of the transition.
+ *
+ * @return The unique identifier (may be {@code null}).
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the unique identifier of the transition.
+ *
+ * @param id
+ * The unique identifier.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the condition expression for this transition.
+ *
+ * @return The condition expression (may be {@code null}).
+ */
+ public String getConditionExpression() {
+ return conditionExpression;
+ }
+
+ /**
+ * Sets the condition expression for this transition.
+ *
+ * @param conditionExpression
+ * The condition expression.
+ */
+ public void setConditionExpression(String conditionExpression) {
+ this.conditionExpression = conditionExpression;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ if (id != null) {
+ builder.append("id=");
+ builder.append(id);
+ }
+ if (from != null) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("from.id=");
+ builder.append(from.getId());
+ }
+ if (to != null) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("to.id=");
+ builder.append(to.getId());
+ }
+ if (conditionExpression != null) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("conditionExpression=");
+ builder.append(conditionExpression);
+ }
+ builder.insert(0, "Transition [");
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java
new file mode 100644
index 000000000..5b30c7172
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java
@@ -0,0 +1,61 @@
+package at.gv.egovernment.moa.id.process.spring;
+
+import java.util.Objects;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext;
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator;
+import at.gv.egovernment.moa.id.process.model.Transition;
+
+/**
+ * Expression evaluator for processing {@link Transition} conditions allowing to reference Spring beans from the
+ * application context.
+ *
+ * @author tknall
+ *
+ */
+public class SpringExpressionEvaluator implements ExpressionEvaluator {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+ private ExpressionParser parser = new SpelExpressionParser();
+ private StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
+
+ @Autowired(required = false)
+ private ApplicationContext ctx;
+
+ @PostConstruct
+ private void init() {
+ if (ctx != null) {
+ evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx));
+ }
+ }
+
+ @Override
+ public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) {
+ Objects.requireNonNull(expression, "Expression must not be null.");
+ log.trace("Evaluating '{}'.", expression);
+
+ Expression expr = parser.parseExpression(expression);
+ Boolean result = expr.getValue(evaluationContext, expressionContext, Boolean.class);
+ if (result == null) {
+ log.warn("Evaluation of '{}' results in null-value.", expression);
+ } else {
+ log.debug("Expression '{}' -> {}", expression, result);
+ }
+
+ return BooleanUtils.isTrue(result);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java
new file mode 100644
index 000000000..738b58834
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java
@@ -0,0 +1,116 @@
+package at.gv.egovernment.moa.id.process.springweb;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import at.gv.egovernment.moa.id.process.ProcessEngine;
+import at.gv.egovernment.moa.id.process.ProcessInstance;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * Abstract HttpServlet that provides means for retrieving the process engine (Spring Web required) as well as
+ * retrieving the underlying process instance and execution context evaluating a certain request parameter.
+ *
+ * @author tknall
+ *
+ */
+public abstract class AbstractAuthSourceServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ private ProcessEngine processEngine;
+
+ /**
+ * Returns the name of the request parameter representing the respective instance id.
+ * <p/>Default is {@code processInstanceId}.
+ * @return The request parameter name.
+ */
+ public String getProcessInstanceIdParameterName() {
+ return "processInstanceId";
+ }
+
+ /**
+ * Returns the underlying process engine instance.
+ *
+ * @return The process engine (never {@code null}).
+ * @throws NoSuchBeanDefinitionException
+ * if no {@link ProcessEngine} bean was found.
+ * @throws NoUniqueBeanDefinitionException
+ * if more than one {@link ProcessEngine} bean was found.
+ * @throws BeansException
+ * if a problem getting the {@link ProcessEngine} bean occurred.
+ * @throws IllegalStateException
+ * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a
+ * Spring web environment.
+ */
+ public synchronized ProcessEngine getProcessEngine() {
+ if (processEngine == null) {
+ WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
+ if (ctx == null) {
+ throw new IllegalStateException(
+ "Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment.");
+ }
+ processEngine = ctx.getBean(ProcessEngine.class);
+ }
+ return processEngine;
+ }
+
+ /**
+ * Retrieves the process instance referenced by the request parameter {@link #getProcessInstanceIdParameterName()}.
+ *
+ * @param request
+ * The HttpServletRequest.
+ * @return The process instance (never {@code null}).
+ * @throws NoSuchBeanDefinitionException
+ * if no {@link ProcessEngine} bean was found.
+ * @throws NoUniqueBeanDefinitionException
+ * if more than one {@link ProcessEngine} bean was found.
+ * @throws BeansException
+ * if a problem getting the {@link ProcessEngine} bean occurred.
+ * @throws IllegalStateException
+ * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a
+ * Spring web environment.
+ * @throws IllegalArgumentException
+ * in case the process instance id referenced by the request parameter
+ * {@link #getProcessInstanceIdParameterName()} does not exist.
+ */
+ public ProcessInstance getProcessInstance(HttpServletRequest request) {
+ String processInstanceId = StringUtils.trimToNull(request.getParameter(getProcessInstanceIdParameterName()));
+ if (processInstanceId == null) {
+ throw new IllegalArgumentException("Missing request parameter '" + getProcessInstanceIdParameterName() + "'.");
+ }
+ return getProcessEngine().getProcessInstance(processInstanceId);
+ }
+
+ /**
+ * Retrieves the execution context for the respective process instance referenced by the request parameter
+ * {@link #getProcessInstanceIdParameterName()}.
+ *
+ * @param request
+ * The HttpServletRequest.
+ * @return The execution context (never {@code null}).
+ * @throws NoSuchBeanDefinitionException
+ * if no {@link ProcessEngine} bean was found.
+ * @throws NoUniqueBeanDefinitionException
+ * if more than one {@link ProcessEngine} bean was found.
+ * @throws BeansException
+ * if a problem getting the {@link ProcessEngine} bean occurred.
+ * @throws IllegalStateException
+ * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a
+ * Spring web environment.
+ * @throws IllegalArgumentException
+ * in case the process instance id referenced by the request parameter
+ * {@link #getProcessInstanceIdParameterName()} does not exist.
+ */
+ public ExecutionContext getExecutionContext(HttpServletRequest request) {
+ return getProcessInstance(request).getExecutionContext();
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java
new file mode 100644
index 000000000..fb75fc8d7
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java
@@ -0,0 +1,74 @@
+package at.gv.egovernment.moa.id.process.springweb;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.filter.RequestContextFilter;
+
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.process.api.Task;
+
+/**
+ * Abstract task implementation providing {@link HttpServletRequest} and {@link HttpServletResponse}.
+ * <p/>
+ * Note that this abstract task requires the Spring (web) framework including a {@link RequestContextFilter} to be set
+ * within {@code web.xml}.
+ *
+ * <pre>
+ * ...
+ * &lt;filter&gt;
+ * &lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
+ * &lt;filter-class&gt;org.springframework.web.filter.RequestContextFilter&lt;/filter-class&gt;
+ * &lt;/filter&gt;
+ * &lt;filter-mapping&gt;
+ * &lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
+ * &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ * &lt;/filter-mapping&gt;
+ * ...
+ * </pre>
+ *
+ * @author tknall
+ *
+ */
+public abstract class MoaIdTask implements Task {
+
+ /**
+ * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} as well as the
+ * respective {@link HttpServletRequest} and {@link HttpServletResponse}.
+ *
+ * @param executionContext
+ * The execution context (never {@code null}).
+ * @param request
+ * The HttpServletRequest (never {@code null}).
+ * @param response
+ * The HttpServletResponse (never {@code null}).
+ * @throws IllegalStateException
+ * Thrown in case the task is nur being run within the required environment. Refer to javadoc for
+ * further information.
+ * @throws Exception
+ * Thrown in case of error executing the task.
+ */
+ public abstract void execute(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) throws TaskExecutionException;
+
+ @Override
+ public void execute(ExecutionContext executionContext) throws TaskExecutionException {
+ RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+ if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) {
+ HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
+ HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();
+ if (request == null || response == null) {
+ throw new IllegalStateException(
+ "Spring's RequestContextHolder did not provide HttpServletResponse. Did you forget to set the required org.springframework.web.filter.RequestContextFilter in your web.xml.");
+ }
+ execute(executionContext, request, response);
+ } else {
+ throw new IllegalStateException("Task needs to be executed within a Spring web environment.");
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java
new file mode 100644
index 000000000..af6822ba6
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java
@@ -0,0 +1,143 @@
+package at.gv.egovernment.moa.id.process.springweb;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.expression.Expression;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext;
+import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator;
+import at.gv.egovernment.moa.id.process.model.Transition;
+
+/**
+ * Expression evaluator for processing {@link Transition} conditions allowing to
+ * <ul>
+ * <li>reference Spring beans from the application context using {@code @myBeanName...},</li>
+ * <li>{@link ExecutionContext} properties using {@code ctx['property']},</li>
+ * <li>Multi valued {@link HttpServletRequest} parameters using {@code requestParameters['foo']} (keep in mind that this
+ * expression returns an array of String values) and</li>
+ * <li>Single valued {@link HttpServletRequest} parameters using {@code requestParameter['foo']}</li>
+ * </ul>
+ *
+ * @author tknall
+ *
+ */
+public class SpringWebExpressionEvaluator implements ExpressionEvaluator {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+ private ExpressionParser parser = new SpelExpressionParser();
+ private StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
+
+ @Autowired(required = false)
+ private ApplicationContext ctx;
+
+ @Autowired(required = false)
+ private HttpServletRequest request;
+
+ @PostConstruct
+ private void init() {
+ if (ctx != null) {
+ evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx));
+ }
+ }
+
+ /**
+ * Evaluation context that provides access to {@link HttpServletRequest} parameters using
+ * {@code requestParameter['foo']} for single value parameters or {@code requestParameters['foo']} for multi value
+ * parameters. Basic calls to {@code ctx} will be delegated.
+ *
+ * @author tknall
+ *
+ */
+ private class SpringWebExpressionEvaluationContext implements ExpressionEvaluationContext {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new expression evaluation context, providing access to HttpServletRequest parameter(s).
+ *
+ * @param delegate
+ * The original {@link ExpressionEvaluationContext} to be delegated to for {@code ctx['foo']}
+ * expressions.
+ */
+ public SpringWebExpressionEvaluationContext(ExpressionEvaluationContext delegate) {
+ this.delegate = delegate;
+ }
+
+ private ExpressionEvaluationContext delegate;
+
+ @Override
+ public Map<String, Serializable> getCtx() {
+ return delegate.getCtx();
+ }
+
+ @SuppressWarnings("unused")
+ public Map<String, String> getRequestParameter() {
+ if (request != null) {
+ Map<String, String> singleValueMap = new HashMap<String, String>();
+ Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, String[]> entry = it.next();
+ if (ArrayUtils.isNotEmpty(entry.getValue())) {
+ singleValueMap.put(entry.getKey(), entry.getValue()[0]);
+ }
+ }
+ return singleValueMap;
+ } else {
+ return Collections.<String, String> emptyMap();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public Map<String, String[]> getRequestParameters() {
+ if (request != null) {
+ return request.getParameterMap();
+ } else {
+ return Collections.<String, String[]> emptyMap();
+ }
+ }
+
+ }
+
+ @Override
+ public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) {
+ Objects.requireNonNull(expression, "Expression must not be null.");
+ log.trace("Evaluating '{}'.", expression);
+
+ Expression expr = parser.parseExpression(expression);
+ Boolean result = null;
+ try {
+ result = expr.getValue(evaluationContext, new SpringWebExpressionEvaluationContext(expressionContext),
+ Boolean.class);
+ if (result == null) {
+ log.warn("Evaluation of '{}' results in null-value.", expression);
+ } else {
+ log.debug("Expression '{}' -> {}", expression, result);
+ }
+ } catch (Exception e) {
+ log.warn("Expression '{}' could not be processed.", expression, e);
+ }
+
+ return BooleanUtils.isTrue(result);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java
new file mode 100644
index 000000000..72677739a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java
@@ -0,0 +1,35 @@
+package at.gv.egovernment.moa.id.process.support;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+/**
+ * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random
+ * instance is a singleton that is initialized on first usage.
+ *
+ * @author tknall
+ *
+ */
+public class SecureRandomHolder {
+
+ private SecureRandomHolder() {
+ }
+
+ private static final SecureRandom SRND_INSTANCE;
+ static {
+ try {
+ SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Unable to instantiate SHA1PRNG.", e);
+ }
+ }
+
+ /**
+ * Returns a secure random generator instance.
+ * @return The secure random instance.
+ */
+ public static SecureRandom getInstance() {
+ return SecureRandomHolder.SRND_INSTANCE;
+ }
+
+} \ No newline at end of file
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java
index 1f3e86ff6..168f2362a 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java
@@ -237,12 +237,12 @@ public interface PVPConstants {
public static final String MANDATE_PROF_REP_OID_OID = "1.2.40.0.10.2.1.1.261.86";
public static final String MANDATE_PROF_REP_OID_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_OID_OID;
- public static final String MANDATE_PROF_REP_OID_FRIENDLY_NAME = "MANDATOR-PROF-REP-OID";
+ public static final String MANDATE_PROF_REP_OID_FRIENDLY_NAME = "MANDATE-PROF-REP-OID";
public static final int MANDATE_PROF_REP_OID_MAX_LENGTH = 256;
public static final String MANDATE_PROF_REP_DESC_OID = "1.2.40.0.10.2.1.1.261.88";
public static final String MANDATE_PROF_REP_DESC_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_DESC_OID;
- public static final String MANDATE_PROF_REP_DESC_FRIENDLY_NAME = "MANDATOR-PROF-REP-DESCRIPTION";
+ public static final String MANDATE_PROF_REP_DESC_FRIENDLY_NAME = "MANDATE-PROF-REP-DESCRIPTION";
public static final int MANDATE_PROF_REP_DESC_MAX_LENGTH = 1024;
public static final String MANDATE_REFERENCE_VALUE_OID = "1.2.40.0.10.2.1.1.261.90";
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
index b22941216..aa154b84b 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
@@ -135,8 +135,10 @@ public class SingleLogOutAction implements IAction {
if (MiscUtil.isEmpty(ssoID)) {
Logger.warn("Can not find active Session. Single LogOut not possible!");
SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
- LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
- SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
+ //LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
+ LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null);
+ Logger.info("Sending SLO success message to requester ...");
+ SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
return null;
} else {
@@ -147,7 +149,9 @@ public class SingleLogOutAction implements IAction {
} catch (MOADatabaseException e) {
Logger.warn("Can not find active Session. Single LogOut not possible!");
SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
- LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
+ //LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI);
+ LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null);
+ Logger.info("Sending SLO success message to requester ...");
SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
return null;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
index 01139d95c..50f42d928 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
@@ -43,6 +43,7 @@ import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusMessage;
import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.SSODescriptor;
import org.opensaml.saml2.metadata.SingleLogoutService;
@@ -348,17 +349,29 @@ public class SingleLogOutBuilder {
public static SingleLogoutService getResponseSLODescriptor(PVPTargetConfiguration spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException {
MOARequest moaReq = (MOARequest) spRequest.getRequest();
EntityDescriptor metadata = moaReq.getEntityMetadata();
- SPSSODescriptor spsso = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+ SSODescriptor ssodesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+
+ if (ssodesc == null) {
+ Logger.debug("No PVP SPSSO descriptor found --> search IDPSSO descriptor");
+ ssodesc = metadata.getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
+
+ }
+
+ if (ssodesc == null) {
+ Logger.error("Found no SLO ServiceDescriptor in Metadata");
+ throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null);
+ }
+
SingleLogoutService sloService = null;
- for (SingleLogoutService el : spsso.getSingleLogoutServices()) {
+ for (SingleLogoutService el : ssodesc.getSingleLogoutServices()) {
if (el.getBinding().equals(spRequest.getBinding()))
sloService = el;
}
if (sloService == null) {
- if (spsso.getSingleLogoutServices().size() != 0)
- sloService = spsso.getSingleLogoutServices().get(0);
+ if (ssodesc.getSingleLogoutServices().size() != 0)
+ sloService = ssodesc.getSingleLogoutServices().get(0);
else {
Logger.error("Found no SLO ServiceDescriptor in Metadata");
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java
index 4c981cb24..e7ba26158 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java
@@ -22,10 +22,14 @@
*******************************************************************************/
package at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes;
+import org.w3c.dom.Element;
+
+import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.NoMandateDataAttributeException;
+import at.gv.egovernment.moa.id.util.MandateBuilder;
import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -37,23 +41,36 @@ public class MandateProfRepDescAttributeBuilder implements IPVPAttributeBuilder
public <ATT> ATT build(OAAuthParameter oaParam, IAuthData authData,
IAttributeGenerator<ATT> g) throws AttributeException {
- if(authData.isUseMandate()) {
- MISMandate mandate = authData.getMISMandate();
-
+ if(authData.isUseMandate()) {
+ String text = null;
- if(mandate == null) {
+ MISMandate misMandate = authData.getMISMandate();
+
+ if(misMandate == null) {
throw new NoMandateDataAttributeException();
}
+
+ text = misMandate.getTextualDescriptionOfOID();
- String text = mandate.getTextualDescriptionOfOID();
+ if (MiscUtil.isEmpty(text)) {
+ Element mandate = authData.getMandate();
+ if (mandate == null) {
+ throw new NoMandateDataAttributeException();
+ }
- if(MiscUtil.isEmpty(text)) {
- return null;
+ Mandate mandateObject = MandateBuilder.buildMandate(authData.getMandate());
+ if (mandateObject == null) {
+ throw new NoMandateDataAttributeException();
+ }
+
+ text = mandateObject.getAnnotation();
- } else
+ }
+
+ if(MiscUtil.isNotEmpty(text))
return g.buildStringAttribute(MANDATE_PROF_REP_DESC_FRIENDLY_NAME,
MANDATE_PROF_REP_DESC_NAME, text);
-
+
}
return null;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java
new file mode 100644
index 000000000..fc4ed1f28
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 Federal Chancellery Austria
+ * MOA-ID has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SchemaValidationException extends PVP2Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param messageId
+ * @param parameters
+ */
+ public SchemaValidationException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * @param messageId
+ * @param parameters
+ */
+ public SchemaValidationException(String messageId, Object[] parameters, Throwable e) {
+ super(messageId, parameters, e);
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SchemaValidationException.java
index 4e26b1ce8..8da5edeed 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SchemaValidationException.java
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*
* Copyright 2014 Federal Chancellery Austria
* MOA-ID has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
@@ -19,16 +19,25 @@
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-package at.gv.egovernment.moa.id.monitoring;
+ */
+package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter;
-import java.util.List;
+import org.opensaml.saml2.metadata.provider.FilterException;
-public interface TestModuleInterface {
+/**
+ * @author tlenz
+ *
+ */
+public class SchemaValidationException extends FilterException {
+
+ /**
+ * @param string
+ */
+ public SchemaValidationException(String string) {
+ super(string);
+
+ }
+
+ private static final long serialVersionUID = 1L;
- public List<String> performTests() throws Exception;
-
- public void initializeTest(long delayParam, String url) throws Exception;
-
- public String getName();
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java
new file mode 100644
index 000000000..86a6a777b
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Federal Chancellery Austria
+ * MOA-ID has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter;
+
+import org.opensaml.saml2.metadata.provider.FilterException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SignatureValidationException extends FilterException {
+
+ /**
+ * @param string
+ */
+ public SignatureValidationException(String string) {
+ super(string);
+
+ }
+
+ /**
+ * @param e
+ */
+ public SignatureValidationException(Exception e) {
+ super(e);
+ }
+
+ /**
+ * @param string
+ * @param object
+ */
+ public SignatureValidationException(String string, Exception e) {
+ super(string, e);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html
index 3eff06daf..5ae76ed96 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html
@@ -842,7 +842,7 @@ input {
src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />
</a> <a href="http://jigsaw.w3.org/css-validator/"> <img
style="border: 0; width: 88px; height: 31px"
- src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
+ src="https://jigsaw.w3.org/css-validator/images/vcss-blue"
alt="CSS ist valide!" />
</a>
</div>
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java
index cba64e080..d493ef9e0 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java
@@ -55,8 +55,11 @@ import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException
import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.InterfederatedIDPPublicServiceFilter;
import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MetadataFilterChain;
+import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.SchemaValidationFilter;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -324,6 +327,7 @@ public class MOAMetadataProvider implements MetadataProvider {
private MetadataFilterChain buildMetadataFilterChain(OnlineApplication oa, String metadataURL, byte[] certificate) throws CertificateException {
MetadataFilterChain filterChain = new MetadataFilterChain(metadataURL, certificate);
+ filterChain.getFilters().add(new SchemaValidationFilter());
if (oa.isIsInterfederationIDP() != null && oa.isIsInterfederationIDP()) {
Logger.info("Online-Application is an interfederated IDP. Add addional Metadata policies");
@@ -374,12 +378,22 @@ public class MOAMetadataProvider implements MetadataProvider {
httpProvider.setMetadataFilter(filter);
httpProvider.initialize();
+ httpProvider.setRequireValidMetadata(true);
+
return httpProvider;
- } catch (Throwable e) {
+ } catch (Throwable e) {
if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) {
Logger.warn("SSL-Server certificate for metadata "
- + metadataURL + " not trusted.", e);
+ + metadataURL + " not trusted.", e);
+
+ } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) {
+ Logger.warn("Signature verification for metadata"
+ + metadataURL + " FAILED.", e);
+
+ } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) {
+ Logger.warn("Schema validation for metadata "
+ + metadataURL + " FAILED.", e);
}
Logger.error(
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
index f0373e214..26b3bfbd1 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
@@ -54,8 +54,7 @@ public class AssertionAttributeExtractor {
private final List<String> minimalAttributeNameList = Arrays.asList(
PVPConstants.PRINCIPAL_NAME_NAME,
- PVPConstants.GIVEN_NAME_NAME,
- PVPConstants.BIRTHDATE_NAME);
+ PVPConstants.GIVEN_NAME_NAME);
public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption {
@@ -119,16 +118,21 @@ public class AssertionAttributeExtractor {
//first check if a bPK or an encrypted bPK is available
if (attributs.containsKey(PVPConstants.ENC_BPK_LIST_NAME) ||
- (attributs.containsKey(PVPConstants.BPK_NAME) && attributs.containsKey(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME))) {
+ (attributs.containsKey(PVPConstants.BPK_NAME))) {
boolean flag = true;
for (String attr : attributeNameList) {
- if (!attributs.containsKey(attr))
+ if (!attributs.containsKey(attr)) {
flag = false;
+ Logger.debug("Assertion contains no Attribute " + attr);
+
+ }
+
}
return flag;
- }
+ }
+ Logger.debug("Assertion contains no bPK or encryptedbPK.");
return false;
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
index 4ba93f8fe..257f9dac4 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
@@ -25,14 +25,20 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.verification;
import java.util.ArrayList;
import java.util.List;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+
import org.joda.time.DateTime;
import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.common.xml.SAMLSchemaBuilder;
import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusResponseType;
+import org.opensaml.saml2.core.validator.AuthnRequestSchemaValidator;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
@@ -51,11 +57,14 @@ import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;
import org.opensaml.xml.security.x509.X509Credential;
import org.opensaml.xml.signature.SignatureTrustEngine;
import org.opensaml.xml.validation.ValidationException;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException;
import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SchemaValidationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;
@@ -81,9 +90,15 @@ public class SAMLVerificationEngine {
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
try {
profileValidator.validate(samlObj.getSignature());
+ performSchemaValidation(samlObj.getDOM());
+
} catch (ValidationException e) {
- // Indicates signature did not conform to SAML Signature profile
- e.printStackTrace();
+ Logger.warn("Signature is not conform to SAML signature profile", e);
+ throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+ } catch (SchemaValidationException e) {
+ throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
+
}
CriteriaSet criteriaSet = new CriteriaSet();
@@ -103,12 +118,17 @@ public class SAMLVerificationEngine {
public void verifyRequest(RequestAbstractType samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
-
try {
- profileValidator.validate(samlObj.getSignature());
+ profileValidator.validate(samlObj.getSignature());
+ performSchemaValidation(samlObj.getDOM());
+
} catch (ValidationException e) {
- // Indicates signature did not conform to SAML Signature profile
- e.printStackTrace();
+ Logger.warn("Signature is not conform to SAML signature profile", e);
+ throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+ } catch (SchemaValidationException e) {
+ throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
+
}
CriteriaSet criteriaSet = new CriteriaSet();
@@ -173,16 +193,27 @@ public class SAMLVerificationEngine {
List<org.opensaml.saml2.core.Assertion> validatedassertions = new ArrayList<org.opensaml.saml2.core.Assertion>();
for (org.opensaml.saml2.core.Assertion saml2assertion : saml2assertions) {
- Conditions conditions = saml2assertion.getConditions();
- DateTime notbefore = conditions.getNotBefore();
+ try {
+ performSchemaValidation(saml2assertion.getDOM());
+
+ Conditions conditions = saml2assertion.getConditions();
+ DateTime notbefore = conditions.getNotBefore().minusMinutes(5);
DateTime notafter = conditions.getNotOnOrAfter();
if ( notbefore.isAfterNow() || notafter.isBeforeNow() ) {
- Logger.warn("PVP2 Assertion is out of Date");
+ Logger.warn("PVP2 Assertion is out of Date. "
+ + "{ Current : " + new DateTime()
+ + " NotBefore: " + notbefore
+ + " NotAfter : " + notafter
+ + " }");;
- } else {
- validatedassertions.add(saml2assertion);
+ } else {
+ validatedassertions.add(saml2assertion);
+
+ }
+
+ } catch (SchemaValidationException e) {
- }
+ }
}
if (validatedassertions.isEmpty()) {
@@ -213,4 +244,35 @@ public class SAMLVerificationEngine {
throw new AssertionValidationExeption("pvp.12", null, e);
}
}
+
+ private static void performSchemaValidation(Element source) throws SchemaValidationException {
+
+ String err = null;
+ try {
+ Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ Validator val = test.newValidator();
+ val.validate(new DOMSource(source));
+ Logger.debug("Schema validation check done OK");
+ return;
+
+ } catch (SAXException e) {
+ err = e.getMessage();
+ if (Logger.isDebugEnabled() || Logger.isTraceEnabled())
+ Logger.warn("Schema validation FAILED with exception:", e);
+ else
+ Logger.warn("Schema validation FAILED with message: "+ e.getMessage());
+
+ } catch (Exception e) {
+ err = e.getMessage();
+ if (Logger.isDebugEnabled() || Logger.isTraceEnabled())
+ Logger.warn("Schema validation FAILED with exception:", e);
+ else
+ Logger.warn("Schema validation FAILED with message: "+ e.getMessage());
+
+ }
+
+ throw new SchemaValidationException("pvp2.22", new Object[]{err});
+
+ }
+
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java
index 3d608fd6d..4d9b97a52 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java
@@ -26,7 +26,6 @@ import org.opensaml.saml2.metadata.provider.FilterException;
import org.opensaml.saml2.metadata.provider.MetadataFilter;
import org.opensaml.xml.XMLObject;
-import at.gv.egovernment.moa.id.commons.db.dao.config.InterfederationIDPType;
import at.gv.egovernment.moa.id.commons.validation.ValidationHelper;
import at.gv.egovernment.moa.logging.Logger;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java
index 0405fa114..6dac4bba1 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java
@@ -39,6 +39,7 @@ import org.opensaml.xml.security.x509.BasicX509Credential;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoCredentialsException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.verification.EntityVerifier;
import at.gv.egovernment.moa.logging.Logger;
@@ -126,7 +127,7 @@ public class MetadataSignatureFilter implements MetadataFilter {
desc.getEntityDescriptors().addAll(verifiedEntIT);
}
- public void doFilter(XMLObject metadata) throws FilterException {
+ public void doFilter(XMLObject metadata) throws SignatureValidationException {
try {
if (metadata instanceof EntitiesDescriptor) {
EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata;
@@ -155,7 +156,7 @@ public class MetadataSignatureFilter implements MetadataFilter {
Logger.info("Metadata signature policy check done OK");
} catch (MOAIDException e) {
Logger.warn("Metadata signature policy check FAILED.", e);
- throw new FilterException(e);
+ throw new SignatureValidationException(e);
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java
new file mode 100644
index 000000000..f73b541bf
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014 Federal Chancellery Austria
+ * MOA-ID has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata;
+
+import org.opensaml.saml2.metadata.provider.FilterException;
+import org.opensaml.saml2.metadata.provider.MetadataFilter;
+import org.opensaml.xml.XMLObject;
+
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+
+import org.opensaml.common.xml.SAMLSchemaBuilder;
+
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SchemaValidationFilter implements MetadataFilter {
+
+ private boolean isActive = true;
+
+ public SchemaValidationFilter() {
+ try {
+ isActive = AuthConfigurationProvider.getInstance().isPVPSchemaValidationActive();
+
+ } catch (ConfigurationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public SchemaValidationFilter(boolean useSchemaValidation) {
+ this.isActive = useSchemaValidation;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
+ */
+ @Override
+ public void doFilter(XMLObject arg0) throws SchemaValidationException {
+
+ String errString = null;
+
+ if (isActive) {
+ try {
+ Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ Validator val = test.newValidator();
+ DOMSource source = new DOMSource(arg0.getDOM());
+ val.validate(source);
+ Logger.info("Metadata Schema validation check done OK");
+ return;
+
+ } catch (SAXException e) {
+ if (Logger.isDebugEnabled() || Logger.isTraceEnabled())
+ Logger.warn("Metadata Schema validation FAILED with exception:", e);
+ else
+ Logger.warn("Metadata Schema validation FAILED with message: "+ e.getMessage());
+
+ errString = e.getMessage();
+
+ } catch (Exception e) {
+ if (Logger.isDebugEnabled() || Logger.isTraceEnabled())
+ Logger.warn("Metadata Schema validation FAILED with exception:", e);
+ else
+ Logger.warn("Metadata Schema validation FAILED with message: "+ e.getMessage());
+
+ errString = e.getMessage();
+
+ }
+
+ throw new SchemaValidationException("Metadata Schema validation FAILED with message: "+ errString);
+
+ } else
+ Logger.info("Metadata Schema validation check is DEACTIVATED!");
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java
index 67f780b3a..4cdd1db01 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java
@@ -83,7 +83,7 @@ public class GetArtifactAction implements IAction {
String url = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/RedirectServlet";
url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(oaURL, "UTF-8"));
if (!oaParam.getBusinessService())
- url = addURLParameter(url, PARAM_TARGET, URLEncoder.encode(oaParam.getTarget(), "UTF-8"));
+ url = addURLParameter(url, PARAM_TARGET, URLEncoder.encode(req.getTarget(), "UTF-8"));
url = addURLParameter(url, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8"));
url = httpResp.encodeRedirectURL(url);
@@ -95,7 +95,7 @@ public class GetArtifactAction implements IAction {
String redirectURL = oaURL;
if (!oaParam.getBusinessService()) {
redirectURL = addURLParameter(redirectURL, PARAM_TARGET,
- URLEncoder.encode(oaParam.getTarget(), "UTF-8"));
+ URLEncoder.encode(req.getTarget(), "UTF-8"));
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
index 65e520cc3..c8a480cac 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
@@ -64,6 +64,7 @@ import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.MiscUtil;
import at.gv.egovernment.moa.util.StringUtils;
import at.gv.util.xsd.persondata.IdentificationType;
import at.gv.util.xsd.persondata.IdentificationType.Value;
@@ -222,8 +223,14 @@ public class SAML1AuthenticationServer extends AuthenticationServer {
Value value = new Value();
id.setValue(value );
- id.setType(Constants.URN_PREFIX_BASEID);
- value.setValue("");
+ id.setType(authData.getIdentificationType());
+ //add baseID if it is requested and available
+ if ( MiscUtil.isNotEmpty(authData.getIdentificationValue()) &&
+ saml1parameter.isProvideIdentityLink() )
+ value.setValue(authData.getIdentificationValue());
+ else
+ value.setValue("");
+
familyName.setValue(authData.getFamilyName());
familyName.setPrimary("undefined");
name.getGivenName().add(authData.getGivenName());
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java
index 8f7f17e2e..9934c339d 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java
@@ -132,7 +132,7 @@ public class SAML1Protocol implements IModulInfo, MOAIDAuthConstants {
if (!ParamValidatorUtils.isValidOA(oaURL))
throw new WrongParametersException("StartAuthentication", PARAM_OA,
"auth.12");
-
+
config.setOAURL(oaURL);
Logger.info("Dispatch SAML1 Request: OAURL=" + oaURL);
@@ -156,8 +156,13 @@ public class SAML1Protocol implements IModulInfo, MOAIDAuthConstants {
new Object[] { null });
}
- config.setSourceID(sourceID);
- config.setTarget(oaParam.getTarget());
+ config.setSourceID(sourceID);
+ if (MiscUtil.isNotEmpty(target))
+ config.setTarget(target);
+
+ else
+ config.setTarget(oaParam.getTarget());
+
return config;
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java
index 8322f0cea..42e9bf25d 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java
@@ -26,12 +26,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-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.commons.db.dao.config.AttributeProviderPlugin;
-import at.gv.egovernment.moa.id.commons.db.dao.config.OAStorkAttribute;
-import at.gv.egovernment.moa.id.commons.db.dao.config.StorkAttribute;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
@@ -54,7 +50,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
- * the AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins.
+ * The AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins.
* The class is called whenever the {@link AuthenticationRequest} Action is invoked and checks for missing attributes.
* Furthermore, the class can handle direct posts. That is when the class triggers an attribute query which needs user
* interaction, redirect to another portal, etc. The redirect will hit here and the class can continue to fetch attributes.
@@ -84,8 +80,6 @@ public class AttributeCollector implements IAction {
}
- // TODO extract attribute response and check if it corresponds to the container
-
if (httpReq.getParameter("SAMLResponse") != null) {
Logger.info("Got SAML response from external attribute provider.");
@@ -110,7 +104,7 @@ public class AttributeCollector implements IAction {
STORKAuthnResponse authnResponse = null;
- // check if valid authn request is contained
+ // check if valid authn response is contained
try {
authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, httpReq.getRemoteAddr());
} catch (STORKSAMLEngineException ex) {
@@ -119,9 +113,25 @@ public class AttributeCollector implements IAction {
STORK2Response.setSTORKAuthnResponseToken(decSamlToken);
+ // check if the attributes are provided for the same person from request
+ // requires presence of eIdentifier for unambigious correlation
+ Logger.debug("Checking if the attribute relates to the correct person..");
+ try {
+ String remoteEIdentifier= authnResponse.getPersonalAttributeList().get("eIdentifier").getValue().get(0);
+ String localEidentifier= container.getResponse().getStorkAuthnResponse().getPersonalAttributeList().get("eIdentifier").getValue().get(0);
+ if (!remoteEIdentifier.equals(localEidentifier)) {
+ Logger.error("The attribute is not provided for the same person!");
+ throw new MOAIDException("stork.25", null);
+ }
+ } catch (NullPointerException ex) {
+ Logger.warn("Could not check the correlation of attributes from external provider. Ignoring the check.");
+ //Logger.debug(ex);
+ //throw new MOAIDException("stork.04", null); // TODO revise message, raise exception when ehvd checked
+ }
+
if (authnResponse.getPersonalAttributeList().size() > 0) {
Logger.info("Response from external attribute provider contains " + authnResponse.getPersonalAttributeList().size() + " attributes.");
- addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList());
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList()));
}
}
@@ -157,7 +167,7 @@ public class AttributeCollector implements IAction {
// - insert the embedded attribute(s) into the container
if (null != newAttributes)
- addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes);
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes));
// see if we need some more attributes
SLOInformationImpl sloInfo = (SLOInformationImpl) processRequest(container, httpReq, httpResp, authData, oaParam);
@@ -184,9 +194,21 @@ public class AttributeCollector implements IAction {
IPersonalAttributeList requestAttributeList = container.getRequest().getPersonalAttributeList();
IPersonalAttributeList responseAttributeList = container.getResponse().getPersonalAttributeList();
List<PersonalAttribute> missingAttributes = new ArrayList<PersonalAttribute>();
+ Logger.debug("aquire list of missing attributes");
for (PersonalAttribute current : requestAttributeList)
- if (!responseAttributeList.containsKey(current.getName()))
- missingAttributes.add(current);
+ if (!responseAttributeList.containsKey(current.getName())) {
+ if(null == current.getStatus() || (null != current.getStatus() && !current.getStatus().equals(AttributeStatusType.WITHHELD.value()))) {
+ // add the ones we need
+ missingAttributes.add(current);
+ Logger.debug("add " + current.getName() + " to the list of missing attributes");
+ }
+ } else {
+ // remove the ones we do not want to share from the response list
+ if(null != current.getStatus() && current.getStatus().equals(AttributeStatusType.WITHHELD.value())) {
+ responseAttributeList.remove(current.getName());
+ Logger.debug("remove " + current.getName() + " from the list of resulting attributes because the user does not want to disclose the data");
+ }
+ }
Logger.info("collecting attributes...");
Logger.debug("found " + missingAttributes.size() + " missing attributes");
@@ -203,7 +225,8 @@ public class AttributeCollector implements IAction {
IPersonalAttributeList aquiredAttributes = new PersonalAttributeList();
currentAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value());
aquiredAttributes.add((PersonalAttribute) currentAttribute.clone());
- addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes);
+ container.getResponse().setPersonalAttributeList(
+ addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));
// - check if we can find a suitable AttributeProvider Plugin
Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs());
@@ -247,15 +270,12 @@ public class AttributeCollector implements IAction {
Logger.error("We have no suitable plugin for obtaining the attribute '" + currentAttribute.getName() + "'");
} else
// else, update any existing attributes
- addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes);
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));
}
Logger.info("collecting attributes done");
// ask for consent if necessary
- if(oaParam.isRequireConsentForStorkAttributes())
- new ConsentEvaluator().requestConsent(container, response, oaParam);
- else
- new ConsentEvaluator().generateSTORKResponse(response, container);
+ new ConsentEvaluator().generateSTORKResponse(response, container);
return null; // AssertionId
// TODO
@@ -296,15 +316,21 @@ public class AttributeCollector implements IAction {
*
* @param target the target
* @param source the source
+ * @return
* @throws MOAIDException
*/
- private void addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException {
+ private PersonalAttributeList addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException {
+
+ PersonalAttributeList updatedList = new PersonalAttributeList();
+ for (PersonalAttribute el : target)
+ updatedList.add(el);
+
Logger.debug("Updating " + source.size() + " attributes...");
for (PersonalAttribute current : source) {
Logger.debug("treating " + current.getName());
// check if we need to update the current pa
- if (target.containsKey(current.getName())) {
+ if (updatedList.containsKey(current.getName())) {
PersonalAttribute existing = target.get(current.getName());
if(!(existing.isEmptyValue() && existing.isEmptyComplexValue()))
if(!(existing.getValue().equals(current.getValue()) || existing.getComplexValue().equals(current.getComplexValue()))) {
@@ -312,14 +338,16 @@ public class AttributeCollector implements IAction {
throw new MOAIDException("stork.16", new Object[] {existing.getName()});
}
- target.get(current.getName()).setStatus(current.getStatus());
- target.get(current.getName()).setValue(current.getValue());
- target.get(current.getName()).setComplexValue(current.getComplexValue());
+ updatedList.get(current.getName()).setStatus(current.getStatus());
+ updatedList.get(current.getName()).setValue(current.getValue());
+ updatedList.get(current.getName()).setComplexValue(current.getComplexValue());
} else
- target.add(current);
+ updatedList.add(current);
- Logger.debug("...successfully treated " + current.getName());
+ Logger.debug("...successfully treated " + current.getName());
}
+
+ return updatedList;
}
/* (non-Javadoc)
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java
index 859f4900b..01f84125f 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java
@@ -163,7 +163,12 @@ public class AuthenticationRequest implements IAction {
Logger.debug("Data container prepared");
- return (new AttributeCollector()).processRequest(container, httpReq, httpResp, authData, oaParam);
+ if(oaParam.isRequireConsentForStorkAttributes())
+ new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam);
+ else
+ new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam);
+
+ return null;
}
// // check if we are getting request for citizen of some other country
// else if (req instanceof MOASTORKRequest) {
@@ -494,11 +499,11 @@ public class AuthenticationRequest implements IAction {
Logger.debug("Personal attribute found in request: " + personalAttribute.getName() + " isRequired: " + personalAttribute.isRequired());
moaAttributeProvider.populateAttribute(attributeList, personalAttribute);
} catch (Exception e) {
- Logger.error("Exception, attributes: " + e.getMessage());
+ Logger.error("Exception, attributes: " + e.getMessage(), e);
}
}
} catch (Exception e) {
- Logger.error("Exception, attributes: " + e.getMessage());
+ Logger.error("Exception, attributes: " + e.getMessage(), e);
}
Logger.trace("AUTHBLOCK " + authData.getAuthBlock());
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java
index 2c5728798..3acd1039f 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java
@@ -23,13 +23,17 @@
package at.gv.egovernment.moa.id.protocols.stork2;
import java.io.StringWriter;
+
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+
import java.util.ArrayList;
import java.util.HashMap;
-import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import java.util.Map.Entry;
+
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
-import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.data.SLOInformationInterface;
import at.gv.egovernment.moa.id.moduls.IAction;
@@ -39,14 +43,13 @@ import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
import eu.stork.peps.auth.commons.PEPSUtil;
import eu.stork.peps.auth.commons.PersonalAttribute;
-import eu.stork.peps.auth.commons.STORKAuthnResponse;
import eu.stork.peps.auth.engine.STORKSAMLEngine;
import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
-import org.joda.time.DateTime;
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import javax.servlet.http.HttpServletRequest;
@@ -72,23 +75,28 @@ public class ConsentEvaluator implements IAction {
DataContainer container;
try {
container = AssertionStorage.getInstance().get(artifactId, DataContainer.class);
+ req = container.getRequest();
} catch (MOADatabaseException e) {
Logger.error("Error fetching incomplete Stork response from temporary storage. Most likely a timeout occured.", e);
throw new MOAIDException("stork.17", null);
}
// evaluate response
- for(PersonalAttribute current : container.getResponse().getPersonalAttributeList()) {
+ for(PersonalAttribute current : container.getRequest().getPersonalAttributeList()) {
if(null == httpReq.getParameter(current.getName())) {
- current.setStatus(AttributeStatusType.NOT_AVAILABLE.value());
+ current.setStatus(AttributeStatusType.WITHHELD.value());
current.setValue(new ArrayList<String>());
current.setComplexValue(new HashMap<String, String>());
}
}
- // build and send response
- generateSTORKResponse(httpResp, container);
-
+ //TODO: CHECK: req.getOAURL() should return the unique OA identifier
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(req.getOAURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{req.getOAURL()});
+
+ new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam);
+
return null; // AssertionId
}
@@ -96,12 +104,19 @@ public class ConsentEvaluator implements IAction {
* Fills the given HttpResponse with the required web page.
*
* @param container the container
+ * @param authData
* @param response the response
* @param oaParam the oa param
* @return the string
* @throws MOAIDException the mOAID exception
*/
- public String requestConsent(DataContainer container, HttpServletResponse response, IOAAuthParameters oaParam) throws MOAIDException {
+ public String requestConsent(DataContainer container, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData, OAAuthParameter oaParam) throws MOAIDException {
+ //check if we need to collect consent
+ if(!oaParam.isRequireConsentForStorkAttributes()) {
+ (new AttributeCollector()).processRequest(container, httpReq, httpResp, authData, oaParam);
+ return "";
+ }
+
// prepare redirect
String newArtifactId;
try {
@@ -130,19 +145,20 @@ public class ConsentEvaluator implements IAction {
Template template = velocityEngine.getTemplate("/resources/templates/stork2_consent.html");
VelocityContext context = new VelocityContext();
- context.put("action", AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/stork2/CompleteAuthentication?" + ARTIFACT_ID + "=" + newArtifactId);
+ context.put("action", AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/stork2/GetConsent?" + ARTIFACT_ID + "=" + newArtifactId);
// assemble table
String table = "";
- for (PersonalAttribute current : container.getResponse().getPersonalAttributeList())
- if ("Available".equals(current.getStatus()))
- table += "<tr><td><input type=\"checkbox\" checked=\"yes\" name=\"" + current.getName() + "\"></td><td>" + current.getName() + "</td></tr>\n";
+ for (PersonalAttribute current : container.getRequest().getPersonalAttributeList())
+ table += "<tr><td><input type=\"checkbox\" checked=\"yes\" name=\"" + current.getName() + "\"></td><td>" + current.getName() + (current.isRequired() ? "" : " (optional)") + "</td></tr>\n";
context.put("tablecontent", table);
+ for(Entry<String, String> current : oaParam.getFormCustomizaten().entrySet())
+ context.put(current.getKey().replace("#", ""), current.getValue());
StringWriter writer = new StringWriter();
template.merge(context, writer);
- response.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
} catch (Exception e) {
Logger.error("Velocity error: " + e.getMessage());
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java
index 136200ed0..2c7e5b539 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java
@@ -26,21 +26,20 @@ import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
import at.gv.egovernment.moa.id.auth.exception.BuildException;
import at.gv.egovernment.moa.id.data.AuthenticationRole;
import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
import eu.stork.peps.auth.commons.PersonalAttribute;
import eu.stork.peps.auth.commons.PersonalAttributeList;
import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+import org.joda.time.Period;
+
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* @author bsuzic
@@ -55,63 +54,116 @@ public class MOAAttributeProvider {
private static final Map<String, String> storkAttributeFunctionMapping;
private final MOASTORKRequest moastorkRequest;
+ // mappings for attribute population methods
+ // based on mapping of moa authndata and executing functions to extract attributes
static {
Map<String, String> tempSimpleMap = new HashMap<String, String>();
tempSimpleMap.put("givenName", "getGivenName");
- tempSimpleMap.put("surname", "getFamilyName");
+ tempSimpleMap.put("surname", "getFamilyName");
+ tempSimpleMap.put("MSOrganization", "getPvpAttribute_OU");
storkAttributeSimpleMapping = Collections.unmodifiableMap(tempSimpleMap);
+
Map<String, String> tempFunctionMap = new HashMap<String, String>();
tempFunctionMap.put("eIdentifier", "geteIdentifier");
tempFunctionMap.put("ECApplicationRole","getECApplicationRole");
tempFunctionMap.put("dateOfBirth", "getFormatedDateOfBirth");
+ tempFunctionMap.put("MSOrganization", "getMSOrganization");
+ tempFunctionMap.put("age", "getAge");
+ tempFunctionMap.put("isAgeOver", "getIsAgeOver");
+ tempFunctionMap.put("citizenQAALevel", "getQAALevel");
storkAttributeFunctionMapping = Collections.unmodifiableMap(tempFunctionMap);
+
}
public MOAAttributeProvider(IAuthData authData, MOASTORKRequest moastorkRequest) {
this.authData = authData;
this.moastorkRequest = moastorkRequest;
- Logger.debug("identity " + authData.getIdentificationType() + " " + authData.getIdentificationValue());
+
}
public void populateAttribute(PersonalAttributeList attributeList, PersonalAttribute requestedAttribute ) {
String storkAttribute = requestedAttribute.getName();
- if (storkAttributeSimpleMapping.containsKey(storkAttribute)) {
+
+ // TODO: check if authData gets populated with stork attributtes during previous steps; it seems it is not
+ if (null != authData && null != authData.getStorkAttributes() && authData.getStorkAttributes().containsKey(requestedAttribute.getName())) {
+ Logger.debug("Trying to get value for attribute directly from STORK2 response [" + storkAttribute + "]");
+ try {
+ PersonalAttribute tmp = authData.getStorkAttributes().get(requestedAttribute.getName());
+ attributeList.add((PersonalAttribute) tmp.clone());
+ } catch(Exception e) {
+ Logger.error("Could not retrieve attribute from STORK2 response: " + storkAttribute);
+ Logger.debug(e);
+ }
+ } else if (storkAttributeSimpleMapping.containsKey(storkAttribute)) {
Logger.debug("Trying to get value for attribute using simple mapping [" + storkAttribute + "]");
try {
Method method = authData.getClass().getDeclaredMethod(storkAttributeSimpleMapping.get(storkAttribute));
- populateAttributeWithMethod(method, authData, attributeList, storkAttribute, requestedAttribute.isRequired());
+ populateAttributeWithMethod(method, authData, attributeList, storkAttribute, requestedAttribute);
} catch (NoSuchMethodException e) {
Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute);
- e.printStackTrace();
+ Logger.debug(e);
+ } catch (NullPointerException e) {
+ Logger.error("Error getting MOA extraction method while getting attribute: " + storkAttribute);
+ Logger.debug(e);
}
} else if (storkAttributeFunctionMapping.containsKey(storkAttribute)) {
Logger.debug("Trying to get value for attribute using function mapping [" + storkAttribute + "]");
try {
- Method method = this.getClass().getDeclaredMethod(storkAttributeFunctionMapping.get(storkAttribute));
- populateAttributeWithMethod(method, this, attributeList, storkAttribute, requestedAttribute.isRequired());
+ Method method = this.getClass().getDeclaredMethod(storkAttributeFunctionMapping.get(storkAttribute), PersonalAttribute.class);
+ populateAttributeWithMethod(method, this, attributeList, storkAttribute, requestedAttribute);
} catch (NoSuchMethodException e) {
Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute);
- e.printStackTrace();
}
} else {
Logger.debug("MOA method for extraction of attribute " + storkAttribute + " not defined.");
}
}
- private String geteIdentifier() {
+ private String getAge(PersonalAttribute personalAttribute) {
+ if (authData.getDateOfBirth() != null) {
+ Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears();
+ return age >= 0 ? age.toString() : null;
+ }
+ return null; // WP4 D4.2, Table 12:age, description - considerations
+ }
+
+ private String getIsAgeOver(PersonalAttribute personalAttribute)
+ {
+ try {
+ if ((authData.getDateOfBirth() != null) && (personalAttribute.getValue() != null) && (personalAttribute.getValue().size() > 0)) {
+ Integer ageOver = Integer.parseInt(personalAttribute.getValue().get(0));
+ Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears();
+ return age >= ageOver ? ageOver.toString() : "";
+ }
+ } catch (Exception ex) {
+ Logger.error("Error encountered when determining isAgeOver");
+ Logger.debug(ex);
+ }
+ return null;
+ }
+
+ public String getQAALevel(PersonalAttribute personalAttribute) {
+ if (authData.getQAALevel().startsWith(PVPConstants.STORK_QAA_PREFIX))
+ return authData.getQAALevel().substring(PVPConstants.STORK_QAA_PREFIX.length());
+ else
+ return null;
+ }
+
+
+ private String geteIdentifier(PersonalAttribute personalAttribute) {
Logger.debug("Using base urn for identification value: " + authData.getIdentificationType() + " and target country: " + moastorkRequest.getStorkAuthnRequest().getSpCountry());
try {
- return new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(),
- moastorkRequest.getStorkAuthnRequest().getSpCountry());
+ return new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(),
+ moastorkRequest.getStorkAuthnRequest().getSpCountry());
} catch (BuildException be) {
Logger.error("Stork eid could not be constructed; " + be.getMessage());
return null; // TODO error
}
}
- private List<String> getECApplicationRole() {
+ private List<String> getECApplicationRole(PersonalAttribute personalAttribute) {
List<String> storkRoles = null;
if (authData.getAuthenticationRoles() != null
@@ -123,29 +175,32 @@ public class MOAAttributeProvider {
String storkRole = mapper.map(el);
if (MiscUtil.isNotEmpty(storkRole))
storkRoles.add(storkRole);
-
}
}
return storkRoles;
}
-
- private String getFormatedDateOfBirth() {
+
+ private String getFormatedDateOfBirth(PersonalAttribute personalAttribute) {
if (authData.getDateOfBirth() != null) {
DateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(authData.getDateOfBirth());
}
else
return null;
-
}
- private void populateAttributeWithMethod(Method method, Object object, PersonalAttributeList attributeList, String storkAttribute, Boolean isRequired) {
+ private void populateAttributeWithMethod(Method method, Object object, PersonalAttributeList attributeList, String storkAttribute, PersonalAttribute requestedAttribute) {
try {
- Object attributeValue = method.invoke(object, new Class[]{}); // (Object[])
-
+ Object attributeValue;
+ if (storkAttributeSimpleMapping.containsValue(method.getName())) {
+ attributeValue = method.invoke(object, new Class[]{});
+ } else {
+ attributeValue = method.invoke(object, requestedAttribute);
+ }
+
PersonalAttribute newAttribute = new PersonalAttribute();
newAttribute.setName(storkAttribute);
- newAttribute.setIsRequired(isRequired);
+ newAttribute.setIsRequired(requestedAttribute.isRequired());
if (attributeValue != null) {
newAttribute.setStatus(AttributeStatusType.AVAILABLE.value());
@@ -178,10 +233,13 @@ public class MOAAttributeProvider {
} catch (InvocationTargetException e) {
Logger.error("Invocation target exception while getting attribute: " + storkAttribute);
- e.printStackTrace();
+ Logger.debug(e);
} catch (IllegalAccessException e) {
Logger.error("Illegal access exception while getting attribute: " + storkAttribute);
- e.printStackTrace();
+ Logger.debug(e);
+ } catch (NullPointerException e) {
+ Logger.error("Could not find method: " + storkAttribute);
+ Logger.debug(e);
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java
index 9207cc2dc..a3fac0f6e 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java
@@ -165,7 +165,8 @@ public abstract class MandateContainer {
}
public void setPhysicalRepresentativeBirthDate(String physicalRepresentativeBirthDate) {
- this.physicalRepresentativeBirthDate = physicalRepresentativeBirthDate;
+ // making it conform to STORK dateOfBirth specifications, removing dash
+ this.physicalRepresentativeBirthDate = physicalRepresentativeBirthDate.replaceAll("-","");
}
public String getAnnotation() {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java
index e6fff76ab..c529a8465 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java
@@ -41,7 +41,6 @@ import eu.stork.peps.auth.commons.PersonalAttribute;
import eu.stork.peps.auth.commons.PersonalAttributeList;
import eu.stork.peps.auth.commons.STORKAttrQueryResponse;
import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.*;
-import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import javax.servlet.http.HttpServletRequest;
@@ -54,14 +53,14 @@ import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import java.io.StringWriter;
-import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.regex.Pattern;
/**
- *
+ * Entry point for mandate retrieval. Processes MIS data and transforms into STORK mandate attribute.
+ * Additionally provides eIdentifier attribute (if requested) in order to enable identity correlation
*/
public class MandateRetrievalRequest implements IAction {
@@ -78,8 +77,13 @@ public class MandateRetrievalRequest implements IAction {
this.QAALevel = translateQAALevel(authData.getQAALevel());
// preparing original content and removing sensitive data from it
- this.originalContent = authData.getMISMandate().getMandate(); // TODO ERROR
- //Logger.debug("Original content " + StringUtils.newStringUtf8(authData.getMISMandate().getMandate()));
+ try {
+ this.originalContent = authData.getMISMandate().getMandate();
+ } catch (Exception e) {
+ Logger.error("Could not extract mandate");
+ Logger.debug(e);
+ throw new MOAIDException("stork.26", new Object[]{});
+ }
String originalMandate = StringUtils.newStringUtf8(authData.getMISMandate().getMandate()).replaceAll("<pd:Value>.*?==</pd:Value><pd:Type>urn:publicid:gv.at:baseid</pd:Type>","<pd:Value></pd:Value><pd:Type></pd:Type>");;
Logger.debug("Removing personal identification value and type from original mandate ");
originalContent = StringUtils.getBytesUtf8(originalMandate);
@@ -97,13 +101,13 @@ public class MandateRetrievalRequest implements IAction {
this.moaStorkRequest = (MOASTORKRequest) req;
} else {
Logger.error("Internal error - did not receive MOASTORKRequest as expected");
- throw new MOAIDException("stork.16", new Object[]{}); // TODO
+ throw new MOAIDException("stork.27", new Object[]{});
}
if (!(moaStorkRequest.isAttrRequest() || moaStorkRequest.getStorkAttrQueryRequest() == null)) {
Logger.error("Did not receive attribute request as expected");
- throw new MOAIDException("stork.16", new Object[]{}); // TODO
+ throw new MOAIDException("stork.27", new Object[]{});
}
MandateContainer mandateContainer = null;
@@ -115,7 +119,7 @@ public class MandateRetrievalRequest implements IAction {
mandateContainer = new PhyPersonMandateContainer(new String(authData.getMISMandate().getMandate(), "UTF-8"));
} catch (Exception ex2) {
Logger.error("Could not extract data and create mandate container.");
- throw new MOAIDException("stork.16", new Object[]{}); // TODO
+ throw new MOAIDException("stork.27", new Object[]{});
}
}
@@ -123,26 +127,21 @@ public class MandateRetrievalRequest implements IAction {
IPersonalAttributeList attributeList = new PersonalAttributeList();
+ // according to new mapping, only mandate attribute is directly relevant
for (PersonalAttribute currentAttribute : sourceAttributeList) {
- Logger.debug("Evaluating currentattribute " + currentAttribute.getName());
- if (currentAttribute.getName().equals("mandateContent")) {
+ Logger.debug("Evaluating attributes, current attribute: " + currentAttribute.getName());
+ if (currentAttribute.getName().equals("mandateContent")) { // deprecated
MandateContentType mandateContent = getMandateContent(mandateContainer, currentAttribute);
attributeList.add(marshallComplexAttribute(currentAttribute, mandateContent));
- } else if (currentAttribute.getName().equals("representative")) { // TODO CHECK IN DETAIL
+ } else if (currentAttribute.getName().equals("representative")) { // deprecated
RepresentationPersonType representative = getRepresentative(mandateContainer, currentAttribute);
attributeList.add(marshallComplexAttribute(currentAttribute, representative));
-
- //attributeList.add(getRepresentative(mandateContainer, currentAttribute));
} else if (currentAttribute.getName().equals("represented")) {
- //attributeList.add(getRepresented(mandateContainer, currentAttribute));
RepresentationPersonType represented = getRepresented(mandateContainer, currentAttribute);
attributeList.add(marshallComplexAttribute(currentAttribute, represented));
-
} else if (currentAttribute.getName().equals("mandate")) {
- //attributeList.add(getMandateType(mandateContainer, currentAttribute));
MandateType mandateType = getMandateType(mandateContainer, currentAttribute);
attributeList.add(marshallComplexAttribute(currentAttribute, mandateType));
-
} else if (currentAttribute.getName().equals("legalName")) {
String legalName = getLegalName(mandateContainer, currentAttribute);
if (legalName.length() > 0) {
@@ -180,6 +179,11 @@ public class MandateRetrievalRequest implements IAction {
}
}
+ if (currentAttribute.getName().equals("eIdentifier")) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(geteIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), moaStorkRequest.getStorkAttrQueryRequest().getSpCountry())), AttributeStatusType.AVAILABLE.value()));
+ Logger.info("Adding eIdentifier for mandate holder using SP country: " + moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
+ }
+
}
@@ -211,7 +215,7 @@ public class MandateRetrievalRequest implements IAction {
// ask for consent if necessary
if (oaParam.isRequireConsentForStorkAttributes())
- new ConsentEvaluator().requestConsent(container, httpResp, oaParam);
+ new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam);
else
new ConsentEvaluator().generateSTORKResponse(httpResp, container);
@@ -228,7 +232,7 @@ public class MandateRetrievalRequest implements IAction {
if (qaaLevel.equals(PVPConstants.STORK_QAA_1_4))
return 4;
Logger.error("Wrong QAA Number format");
- throw new MOAIDException("stork.16", new Object[]{});
+ throw new MOAIDException("stork.28", new Object[]{});
}
private String geteLPIdentifier(MandateContainer mandateContainer, PersonalAttribute currentAttribute) throws MOAIDException {
@@ -237,11 +241,20 @@ public class MandateRetrievalRequest implements IAction {
return represented.getELPIdentifier();
} else if (currentAttribute.isRequired()) {
Logger.error("Cannot provide eLPIdentifier for natural person.");
- throw new MOAIDException("stork.19", new Object[]{currentAttribute.getName()}); // TODO
+ throw new MOAIDException("stork.29", new Object[]{currentAttribute.getName()});
}
return "";
}
+ private String geteIdentifier(String identificationType, String identificationValue, String destinationCountry) throws MOAIDException {
+ BPKBuilder bpkBuilder = new BPKBuilder();
+ try {
+ return bpkBuilder.buildStorkeIdentifier(identificationType, identificationValue, destinationCountry);
+ } catch (BuildException be) {
+ Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");
+ throw new MOAIDException("stork.29", new Object[]{});
+ }
+ }
private PersonalAttribute marshallComplexAttribute(PersonalAttribute currentAttribute, Object obj) { // TODO refactor
StringWriter stringWriter = new StringWriter();
@@ -456,7 +469,6 @@ public class MandateRetrievalRequest implements IAction {
private String getRepresentedStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException {
- //String identificationType, String identificationValue
if (!(mandateContainer instanceof PhyPersonMandateContainer)) {
Logger.error("Physical person mandate container missing");
throw new MOAIDException("stork.20", new Object[]{}); // TODO
@@ -479,13 +491,7 @@ public class MandateRetrievalRequest implements IAction {
throw new MOAIDException("stork.20", new Object[]{}); // TODO
}
- BPKBuilder bpkBuilder = new BPKBuilder();
- try {
- return bpkBuilder.buildStorkeIdentifier(phyPersonMandateContainer.getPhyPersMandatorIdentificationType(), phyPersonMandateContainer.getPhyPersMandatorIdentificationValue(), this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
- } catch (BuildException be) {
- Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");
- throw new MOAIDException("stork.20", new Object[]{}); // TODO
- }
+ return geteIdentifier(phyPersonMandateContainer.getPhyPersMandatorIdentificationType(), phyPersonMandateContainer.getPhyPersMandatorIdentificationValue(), this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
}
private String getRepresentingStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException {
@@ -522,6 +528,7 @@ public class MandateRetrievalRequest implements IAction {
Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");
throw new MOAIDException("stork.20", new Object[]{}); // TODO
}
+
}
private RepresentationPersonType getRepresentative(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java
index ba89663ab..c715b65eb 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java
@@ -109,7 +109,8 @@ public class PhyPersonMandateContainer extends MandateContainer {
}
public void setPhyPersMandatorBirthDate(String phyPersMandatorBirthDate) {
- this.phyPersMandatorBirthDate = phyPersMandatorBirthDate;
+ // making it conform to STORK dateOfBirth specifications, removing dash
+ this.phyPersMandatorBirthDate = phyPersMandatorBirthDate.replaceAll("-","");
}
public String getPhyPersMandatorIdentificationValue() {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java
index d923eccde..123d32af4 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java
@@ -32,7 +32,7 @@ import java.util.List;
public class STORKPVPUtilits {
public static final List<String> attributesRequirePVPAuthentication =
- Arrays.asList("ECApplicationRole");
+ Arrays.asList("ECApplicationRole", "MSOrganization");
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java
index f4d963645..f671f0807 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java
@@ -73,6 +73,7 @@ public class MandateAttributeRequestProvider extends AttributeProvider {
return "MandateAttributeRequestProvider";
}
+ // TODO check if used
@Override
protected IPersonalAttributeList acquire(PersonalAttribute attribute, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException {
Logger.info("Acquiring attribute: " + attribute.getName() + ", by: " + getAttrProviderName());
@@ -85,10 +86,14 @@ public class MandateAttributeRequestProvider extends AttributeProvider {
Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName());
throw new UnsupportedAttributeException();
}
- PersonalAttributeList result = new PersonalAttributeList();
- //return result;
-
+ // check if there is eIdentifier included and add if necessary
+// if (!requestedAttributes.containsKey("eIdentifier")) {
+// PersonalAttribute eIdentifier = new PersonalAttribute();
+ // eIdentifier.setName("eIdentifier");
+// eIdentifier.setIsRequired(true);
+// requestedAttributes.add(eIdentifier);
+// }
Logger.info("Thrown external request by: " + getAttrProviderName());
throw new ExternalAttributeRequestRequiredException(this);
@@ -111,10 +116,12 @@ public class MandateAttributeRequestProvider extends AttributeProvider {
// continue with other attribute providers if there are no attributes current provider is able to handle
if (requestedAttributes.size() == 0) {
- Logger.info("Attribute(s) " + attributes.toString() + " not supported by the provider: " + getAttrProviderName());
+ Logger.info("Attribute(s) " + attributes.toString() + " not supported by the provider: " + getAttrProviderName());
throw new UnsupportedAttributeException();
}
+
+
Logger.info("Thrown external request by: " + getAttrProviderName());
throw new ExternalAttributeRequestRequiredException(this);
}
@@ -144,7 +151,14 @@ public class MandateAttributeRequestProvider extends AttributeProvider {
}
-
+ // TODO ensure that other providers request eidentifier
+ // check if there is eIdentifier included and add if necessary
+ if (!requestedAttributes.containsKey("eIdentifier")) {
+ PersonalAttribute eIdentifier = new PersonalAttribute();
+ eIdentifier.setName("eIdentifier");
+ eIdentifier.setIsRequired(true);
+ requestedAttributes.add(eIdentifier);
+ }
//generate AttrQueryRequest
STORKAttrQueryRequest attributeRequest = new STORKAttrQueryRequest();
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java
index 96aa55bcf..7f06c604b 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java
@@ -80,7 +80,7 @@ public class PVPAuthenticationProvider extends AttributeProvider {
this.moastorkRequest = moastorkRequest;
// break if we cannot handle the requested attribute
- if (!attributes.contains(attribute.getName())) {
+ if (!getSupportedAttributeNames().contains(attribute.getName())) {
Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName());
throw new UnsupportedAttributeException();
@@ -193,33 +193,34 @@ public class PVPAuthenticationProvider extends AttributeProvider {
public IPersonalAttributeList parse(HttpServletRequest httpReq)
throws UnsupportedAttributeException, MOAIDException {
- Logger.info(this.getClass().getSimpleName() + " tries to extract SAMLResponse out of HTTP Request");
+ throw new UnsupportedAttributeException();
- //extract STORK Response from HTTP Request
- //Decodes SAML Response
- byte[] decSamlToken;
- try {
- decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse"));
- } catch(NullPointerException e) {
- throw new UnsupportedAttributeException();
- }
-
- //Get SAMLEngine instance
- STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
-
- STORKAuthnResponse authnResponse = null;
- try {
- //validate SAML Token
- Logger.debug("Starting validation of SAML response");
- authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) httpReq.getRemoteHost());
- Logger.info("SAML response successfully verified!");
-
- }catch(STORKSAMLEngineException e){
- Logger.error("Failed to verify STORK SAML Response", e);
- throw new MOAIDException("stork.05", null);
- }
-
- return authnResponse.getPersonalAttributeList();
+// Logger.info(this.getClass().getSimpleName() + " tries to extract SAMLResponse out of HTTP Request");
+// //extract STORK Response from HTTP Request
+// //Decodes SAML Response
+// byte[] decSamlToken;
+// try {
+// decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse"));
+// } catch(NullPointerException e) {
+// throw new UnsupportedAttributeException();
+// }
+//
+// //Get SAMLEngine instance
+// STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+//
+// STORKAuthnResponse authnResponse = null;
+// try {
+// //validate SAML Token
+// Logger.debug("Starting validation of SAML response");
+// authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) httpReq.getRemoteHost());
+// Logger.info("SAML response successfully verified!");
+//
+// }catch(STORKSAMLEngineException e){
+// Logger.error("Failed to verify STORK SAML Response", e);
+// throw new MOAIDException("stork.05", null);
+// }
+//
+// return authnResponse.getPersonalAttributeList();
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java
index bb3d8b1fd..2c77db94e 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java
@@ -189,6 +189,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {
IOUtils.copy(istr, writer, "UTF-8");
signResponseString = writer.toString();
Logger.info("SignResponse with error (unmodified):"+signResponseString);
+ istr.close();
}
else
{
@@ -198,6 +199,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(dataSource.getInputStream(), baos);
byte[] data = baos.toByteArray();
+ baos.close();
//update doc in DTL
String docId, dssId = "";
@@ -255,7 +257,8 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {
StringWriter writer = new StringWriter();
IOUtils.copy(istr, writer, "UTF-8");
signResponseString = writer.toString();
- Logger.info("SignResponse overwritten:"+signResponseString);
+ Logger.info("SignResponse overwritten:"+signResponseString);
+ istr.close();
}
else
{
@@ -304,6 +307,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {
IOUtils.copy(istr, writer, "UTF-8");
signResponseString = writer.toString();
Logger.info("SignResponse overwritten:"+signResponseString);
+ istr.close();
}
}
else
@@ -424,6 +428,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {
signRequestString = writer.toString();
Logger.info("Signrequest overwritten");
Logger.debug("Signrequest overwritten:"+signRequestString);
+ istr.close();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Could not marshall sign request", e);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
index a9f5ed60a..4288f48ad 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
@@ -48,6 +48,7 @@ import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.data.EncryptedData;
import at.gv.egovernment.moa.id.data.SLOInformationInterface;
import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;
import at.gv.egovernment.moa.id.util.Random;
@@ -912,19 +913,28 @@ public class AuthenticationSessionStoreage {
}
- private static void cleanDelete(AuthenticatedSessionStore result) {
+ private static void cleanDelete(AuthenticatedSessionStore result) {
+
+ try {
+ AuthenticationSession session = getSession(result.getSessionid());
+ if (session.getProcessInstanceId() != null) {
+ ProcessInstanceStoreDAOImpl.getInstance().remove(session.getProcessInstanceId());
+ }
+
+ } catch (MOADatabaseException e) {
+ Logger.warn("Removing process associated with moa session " + result.getSessionid() + " FAILED.", e);
+ }
+
try {
result.setSession("blank".getBytes());
MOASessionDBUtils.saveOrUpdate(result);
-
+
} catch (MOADatabaseException e) {
Logger.warn("Blank authenticated session with sessionID=" + result.getSessionid() + " FAILED.", e);
-
+
} finally {
if (!MOASessionDBUtils.delete(result))
- Logger.error("Authenticated session with sessionID=" + result.getSessionid()
- + " not removed! (Error during Database communication)");
-
+ Logger.error("Authenticated session with sessionID=" + result.getSessionid() + " not removed! (Error during Database communication)");
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java
index 090bea486..520b81b17 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java
@@ -71,13 +71,9 @@ public class IdentityLinkReSigner {
return instance;
}
- public Element resignIdentityLink(Element idl) throws MOAIDException {
+ public Element resignIdentityLink(Element idl, String keyGroupId) throws MOAIDException {
try {
- AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
-
- if (config.isIdentityLinkResigning()) {
-
if (idl == null) {
Logger.warn("IdentityLink is empty");
return null;
@@ -91,7 +87,6 @@ public class IdentityLinkReSigner {
SPSSFactory spssFac = SPSSFactory.getInstance();
- String keyGroupId = config.getIdentityLinkResigningKey();
if (MiscUtil.isEmpty(keyGroupId)) {
Logger.warn("No IdentityLink reSigning-Key definded");
throw new MOAIDException("config.19", new Object[]{});
@@ -166,9 +161,6 @@ public class IdentityLinkReSigner {
Logger.warn("Allgemeiner Fehler beim Aufruf von MOA-SS: Unbekannter ResponseType von MOA-SS");
throw new MOAIDException("builder.05", new Object[]{});
}
-
- } else
- return idl;
} catch (ConfigurationException e) {
Logger.warn("Configuration can not be loaded", e);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java
index 0ea03e29d..5ef9494f4 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java
@@ -36,6 +36,7 @@ import at.gv.egovernment.moa.util.MiscUtil;
public class PVPtoSTORKMapper {
private static final String PVP_SECCLASS_PREFIX = "http://www.ref.gv.at/ns/names/agiz/pvp/";
+ private static final String STORK_QAA_PREFIX = "http://www.stork.gov.eu/1.0/";
private static final String MAPPING_RESOURCE =
"resources/properties/pvp-stork_mapping.properties";
@@ -67,12 +68,31 @@ public class PVPtoSTORKMapper {
}
+ /**Map a STORK QAA level to PVP SecClass
+ *
+ * @param STORK-QAA level
+ * @return PVP SecClass pvpQAALevel
+ */
+ public String mapToSecClass(String storkQAALevel) {
+ if (mapping != null) {
+ String input = storkQAALevel.substring(STORK_QAA_PREFIX.length());
+ String mappedQAA = mapping.getProperty(input);
+ if (MiscUtil.isNotEmpty(mappedQAA)) {
+ Logger.info("Map STORK-QAA " + storkQAALevel + " to PVP SecClass " + mappedQAA);
+ return mappedQAA;
+
+ }
+ }
+ Logger.warn("No mapping for STORK-QAA " + storkQAALevel +" !");
+ return null;
+ }
+
/**Map a PVP SecClass to STORK QAA level
*
* @param PVP SecClass pvpQAALevel
* @return STORK-QAA level
*/
- public String mapQAALevel(String pvpQAALevel) {
+ public String mapToQAALevel(String pvpQAALevel) {
if (mapping != null) {
String input = pvpQAALevel.substring(PVP_SECCLASS_PREFIX.length());
String mappedQAA = mapping.getProperty(input);
@@ -93,13 +113,16 @@ public class PVPtoSTORKMapper {
*/
public String map(AuthenticationRole el) {
if (mapping != null) {
- String ecRole = mapping.getProperty(el.getRawRoleString());
+ //String ecRole = mapping.getProperty(el.getRawRoleString());
+ String ecRole = mapping.getProperty(el.getRoleName());
if (MiscUtil.isNotEmpty(ecRole)) {
- Logger.info("Map PVPRole " + el.getRawRoleString() + " to ECRole " + ecRole);
+ //Logger.info("Map PVPRole " + el.getRawRoleString() + " to ECRole " + ecRole);
+ Logger.info("Map PVPRole " + el.getRoleName() + " to ECRole " + ecRole);
return ecRole;
}
}
- Logger.warn("NO mapping for PVPRole "+ el.getRawRoleString() + " !");
+ //Logger.warn("NO mapping for PVPRole "+ el.getRawRoleString() + " !");
+ Logger.warn("NO mapping for PVPRole "+ el.getRoleName() + " !");
return null;
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java
index 56e59a4aa..3dbc0ab7b 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java
@@ -113,14 +113,13 @@ public class ServletUtils {
* depending on the requests starting text.
*
* @param resp The httpServletResponse
- * @param session The current AuthenticationSession
* @param createXMLSignatureRequestOrRedirect The request
* @param servletGoal The servlet to which the redirect should happen
* @param servletName The servlet name for debug purposes
* @throws MOAIDException
* @throws IOException
*/
- public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, AuthenticationSession session, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL)
+ public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL)
throws MOAIDException,
IOException
{
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java
index 20cabaf4d..1edb8d1f3 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java
@@ -66,6 +66,9 @@ public class MISMandate implements Serializable{
final static public String OID_ORGANWALTER = "1.2.40.0.10.3.4";
final static private String TEXT_ORGANWALTER = "Organwalter";
+ final static public String OID_ELGA_OMBUTSSTELLE = "1.2.40.0.34.3.1.3";
+ final static public String OID_ELGA_OMBUTSSTELLE_TEST = "1.2.40.0.34.3.1.2.99.9";
+ final static private String TEXT_ELGA_OMBUTSSTELLE = "ELGA-Ombudsstelle";
private String oid = null;
private byte[] mandate = null;
@@ -102,7 +105,10 @@ public class MISMandate implements Serializable{
return TEXT_ZIVILTECHNIKER;
if (this.oid.equalsIgnoreCase(OID_ORGANWALTER))
return TEXT_ORGANWALTER;
-
+ if (this.oid.equalsIgnoreCase(OID_ELGA_OMBUTSSTELLE)
+ || this.oid.equalsIgnoreCase(OID_ELGA_OMBUTSSTELLE_TEST))
+ return TEXT_ELGA_OMBUTSSTELLE;
+
return "Keine textuelle Beschreibung für OID " + oid;
} else {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java
index 15b2a89b5..24c96a78f 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java
@@ -56,6 +56,7 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
@@ -70,6 +71,7 @@ import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;
import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWSecureSocketFactory;
+import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.StringUtils;
@@ -300,7 +302,7 @@ public class MISSimpleClient {
throw new NullPointerException("Argument request must not be null.");
}
try {
- HttpClient httpclient = new HttpClient();
+ HttpClient httpclient = HttpClientWithProxySupport.getHttpClient();
PostMethod post = new PostMethod(webServiceURL);
StringRequestEntity re = new StringRequestEntity(DOMUtils.serializeNode(packIntoSOAP(request)),"text/xml", "UTF-8");
post.setRequestEntity(re);
diff --git a/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java
new file mode 100644
index 000000000..968d3491d
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java
@@ -0,0 +1,18 @@
+package iaik;
+
+/**
+ * Adapter class providing {@code iaik.RuntimeException} for libraries that have not been updated in order to consider
+ * the fact that the class {@code IAIKRuntimeException} has been moved.
+ *
+ * @author tknall
+ *
+ */
+public class IAIKRuntimeException extends iaik.server.modules.IAIKRuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public IAIKRuntimeException(String reason, Throwable wrapped, String uniqueIdentifier) {
+ super(reason, wrapped, uniqueIdentifier);
+ }
+
+}