aboutsummaryrefslogtreecommitdiff
path: root/id/server
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2016-12-15 09:50:18 +0100
committerThomas Lenz <tlenz@iaik.tugraz.at>2016-12-15 09:50:18 +0100
commit3573f8ea5a4b269834723da4708bf0bace50fa65 (patch)
tree8fb47341f59a7bef99cb0c7370d16db0210b2e95 /id/server
parent0f4c4e1e8c897d06a4ba4aeea9657e4036ead50d (diff)
parentf03d5eb61c46186cf9d9e5a27f67fd8ac070a296 (diff)
downloadmoa-id-spss-3573f8ea5a4b269834723da4708bf0bace50fa65.tar.gz
moa-id-spss-3573f8ea5a4b269834723da4708bf0bace50fa65.tar.bz2
moa-id-spss-3573f8ea5a4b269834723da4708bf0bace50fa65.zip
Merge branch 'eIDAS_node_implementation' into development_preview
Diffstat (limited to 'id/server')
-rw-r--r--id/server/doc/handbook/protocol/protocol.html10
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java2
-rw-r--r--id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/velocity/VelocityProvider.java6
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java2
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java67
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java178
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java96
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java57
-rw-r--r--id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/ELGAMandatesAuthModuleImpl.java6
-rw-r--r--id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java9
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java15
11 files changed, 367 insertions, 81 deletions
diff --git a/id/server/doc/handbook/protocol/protocol.html b/id/server/doc/handbook/protocol/protocol.html
index 5a578a5aa..7d3f8d627 100644
--- a/id/server/doc/handbook/protocol/protocol.html
+++ b/id/server/doc/handbook/protocol/protocol.html
@@ -1295,8 +1295,8 @@ https://&lt;host&gt;:&lt;port&gt;/moa-id-auth/pvp2/metadata
<p>Dieser Abschnitt beschreibt die einzelnen OpenID Connect spezifischen Nachrichten, welche zwischen der Online-Applikation und dem Modul MOA-ID-Auth während eines Authentifizierungsvorgangs ausgetauscht werden. Hierbei wird auch auf das Sequenzdiagramm aus <a href="#openid_sequenzdiagramm">Abschnitt 3.1</a> Bezug genommen.</p>
<h4><a name="openid_req_authnreq"></a>3.2.1 AuthCode Request</h4>
-<p>Der AuthCode Request ist die Authentifizierungsanfrage einer Online-Applikation für eine Benutzerin oder einen Benutzer.
-Folgende Parameter müssen mit dem AuthCode-Request mitgesendet werden, wobei für die Übertragung der Parameter sowohl http GET als auch http POST verwendet werden kann.</p>
+<p>Der AuthCode Request ist die Authentifizierungsanfrage einer Online-Applikation f&uuml;r eine Benutzerin oder einen Benutzer.
+Folgende Parameter m&uuml;ssen mit dem AuthCode-Request mitgesendet werden, wobei f&uuml;r die &Uuml;bertragung der Parameter sowohl http GET als auch http POST verwendet werden kann.</p>
<table class="configtable">
<tr>
<th>Name</th>
@@ -1498,6 +1498,12 @@ Folgende Parameter müssen mit dem AuthCode-Request mitgesendet werden, wobei fÃ
<td>https://demo.egiz.gv.at/demoportal_moaid-2.0/moa_errorcodes.html#1000</td>
<td>URL auf eine Seite mit zus&auml;tzlicher Fehlerbeschreibung</td>
</tr>
+ <tr>
+ <td>state</td>
+ <td>1425782214234</td>
+ <td><p>Der von der Online-Applikation generierte und im AuthCode Request &uuml;bergebene CSRF Token.</p>
+ <p><strong>Hinweis:</strong> Dieser Parameter wird nur dann returniert wenn dieser auch im vorrangegangenen Request (z.B. AuthCode Request) angegeben wurde.</p></td>
+ </tr>
</table>
<p>&nbsp;</p>
<h2><a name="saml1"></a>3 SAML 1</h2>
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java
index 77cc7228b..df4866c30 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java
@@ -41,7 +41,7 @@ import at.gv.egovernment.moa.util.MiscUtil;
public abstract class AbstractCredentialProvider {
- private static KeyStore keyStore = null;
+ private KeyStore keyStore = null;
/**
* Get a friendlyName for this keyStore implementation
diff --git a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/velocity/VelocityProvider.java b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/velocity/VelocityProvider.java
index 022c144f0..21fe110ca 100644
--- a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/velocity/VelocityProvider.java
+++ b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/velocity/VelocityProvider.java
@@ -50,6 +50,7 @@
*/
package at.gv.egovernment.moa.id.auth.frontend.velocity;
+import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
@@ -104,8 +105,9 @@ public class VelocityProvider {
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8");
velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
- velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
- "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
+// velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
+// "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
+ velocityEngine.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new VelocityLogAdapter() );
return velocityEngine;
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
index f45b6ffa5..02c9a8f5d 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
@@ -45,7 +45,7 @@ public class Constants {
public static final String eIDAS_SAML_ENGINE_NAME_ID_CLASS = "class";
//default implementations for eIDAS SAML-engine functionality
- public static final String SAML_SIGNING_IMPLENTATION = "eu.eidas.auth.engine.core.impl.SignSW";
+ public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner";
public static final String SAML_ENCRYPTION_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.ModifiedEncryptionSW";
//configuration property keys
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java
index 302c12aaa..5cf5e83ec 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java
@@ -22,12 +22,22 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.config;
+import java.util.Locale;
import java.util.Map;
+import org.apache.commons.lang.StringUtils;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.xml.signature.SignatureConstants;
+
+import com.google.common.collect.ImmutableSet;
+
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAWhiteListConfigurator;
+import at.gv.egovernment.moaspss.logging.Logger;
import eu.eidas.auth.engine.configuration.SamlEngineConfigurationException;
import eu.eidas.auth.engine.configuration.dom.ConfigurationAdapter;
import eu.eidas.auth.engine.configuration.dom.ConfigurationKey;
+import eu.eidas.auth.engine.configuration.dom.KeyStoreSignatureConfigurator;
import eu.eidas.auth.engine.core.impl.KeyStoreProtocolSigner;
import eu.eidas.samlengineconfig.CertificateConfigurationManager;
@@ -37,20 +47,71 @@ import eu.eidas.samlengineconfig.CertificateConfigurationManager;
*/
public class MOASWSigner extends KeyStoreProtocolSigner {
+ private static Map<String, String> props;
+ private ImmutableSet<String> sigAlgWhiteList = null;
+
+ private static final ImmutableSet<String> ALLOWED_ALGORITHMS_FOR_VERIFYING =
+ ImmutableSet.of(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512,
+ // RIPEMD is allowed to verify
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_RIPEMD160,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512,
+
+ //Set other algorithms which are not supported by openSAML in default
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1_MGF1, Locale.ENGLISH),
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224_MGF1, Locale.ENGLISH),
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, Locale.ENGLISH),
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1, Locale.ENGLISH),
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, Locale.ENGLISH));
+
+ private static final ImmutableSet<String> DEFAULT_ALGORITHM_WHITE_LIST =
+ ImmutableSet.of(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512,
+ // RIPEMD is not allowed to sign
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512,
+
+ //Set other algorithms which are not supported by openSAML in default
+ StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, Locale.ENGLISH));
+
public MOASWSigner(Map<String, String> properties) throws SamlEngineConfigurationException {
super(properties);
-
+ props = properties;
+
}
/**
* @param configManager
* @throws SamlEngineConfigurationException
*/
- public MOASWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException {
- super(ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters());
+ public MOASWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException {
+ super(props = ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters());
}
+ @Override
+ protected ImmutableSet<String> getSignatureAlgorithmWhiteList() {
+ try {
+ if (sigAlgWhiteList == null) {
+ sigAlgWhiteList = MOAWhiteListConfigurator.getAllowedAlgorithms(DEFAULT_ALGORITHM_WHITE_LIST,
+ ALLOWED_ALGORITHMS_FOR_VERIFYING,
+ (new KeyStoreSignatureConfigurator().getSignatureConfiguration(props)).getSignatureAlgorithmWhiteList());
+
+ }
+
+ return sigAlgWhiteList;
+
+ } catch (SamlEngineConfigurationException e) {
+ Logger.warn("Can not parse eIDAS signing configuration." , e);
+ return DEFAULT_ALGORITHM_WHITE_LIST;
+
+ }
+ }
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
index 3522a16fd..a9c4d5d3a 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
@@ -22,10 +22,13 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.tasks;
+import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -39,6 +42,7 @@ import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.xml.util.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -55,10 +59,12 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineExcepti
import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
import at.gv.egovernment.moa.id.commons.api.data.CPEPS;
import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
import eu.eidas.auth.commons.EidasStringUtil;
@@ -111,15 +117,15 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
// select SingleSignOnService Endpoint from eIDAS-node metadata
- String destination = null;
+ SingleSignOnService authnReqEndpoint = null;
String metadataUrl = cpeps.getPepsURL().toString().split(";")[0].trim();
try {
EntityDescriptor eIDASNodeMetadata = eIDASMetadataProvider.getEntityDescriptor(metadataUrl);
if (eIDASNodeMetadata != null) {
SingleSignOnService ssoDescr = selectSingleSignOnServiceFromMetadata(eIDASNodeMetadata);
if (ssoDescr != null) {
- destination = ssoDescr.getLocation();
- Logger.debug("Use destination URL:" + destination + " from eIDAS metadata:" + metadataUrl);
+ authnReqEndpoint = ssoDescr;
+ Logger.debug("Use destination URL:" + authnReqEndpoint.getLocation() + " from eIDAS metadata:" + metadataUrl);
} else
Logger.warn("eIDAS metadata for node:" + metadataUrl + " has no IDPSSODescriptor or no SingleSignOnService information.");
@@ -134,13 +140,21 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
// load SingleSignOnService Endpoint from configuration, if Metadata contains no information
// FIXME convenience function for not standard conform metadata
- if (MiscUtil.isEmpty(destination)) {
+ if (authnReqEndpoint == null) {
+ String destination = null;
String[] splitString = cpeps.getPepsURL().toString().split(";");
if (splitString.length > 1)
destination = cpeps.getPepsURL().toString().split(";")[1].trim();
- if (MiscUtil.isNotEmpty(destination))
+ if (MiscUtil.isNotEmpty(destination)) {
Logger.debug("Use eIDAS node destination URL:" + destination + " from configuration");
+
+ //set POST binding as default binding, if Authn. request endpoint from config is used
+ authnReqEndpoint = SAML2Utils.createSAMLObject(SingleSignOnService.class);
+ authnReqEndpoint.setLocation(destination);
+ authnReqEndpoint.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+
+ }
else {
Logger.error("No eIDAS-node destination URL FOUND. Request eIDAS node not possible.");
@@ -193,7 +207,7 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
authnRequestBuilder.providerName(pendingReq.getAuthURL());
String issur = pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
authnRequestBuilder.issuer(issur);
- authnRequestBuilder.destination(destination);
+ authnRequestBuilder.destination(authnReqEndpoint.getLocation());
authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
@@ -226,45 +240,21 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
String SAMLRequest = EidasStringUtil.encodeToBase64(token);
- //send
- try {
- VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
- VelocityContext context = new VelocityContext();
-
- String actionType = "SAMLRequest";
- context.put(actionType, SAMLRequest);
- Logger.debug("Encoded " + actionType + " original: " + SAMLRequest);
-
- context.put("RelayState", pendingReq.getRequestID());
-
- Logger.debug("Using assertion consumer url as action: " + destination);
- context.put("action", destination);
-
- Logger.debug("Starting template merge");
- StringWriter writer = new StringWriter();
-
- Logger.debug("Doing template merge");
- template.merge(context, writer);
- Logger.debug("Template merge done");
-
- Logger.debug("Sending html content: " + writer.getBuffer().toString());
-
-
- byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- response.setContentType(MediaType.HTML_UTF_8.toString());
- response.setContentLength(content.length);
- response.getOutputStream().write(content);
+ if (SAMLConstants.SAML2_POST_BINDING_URI.equals(authnReqEndpoint.getBinding()))
+ buildPostBindingRequest(pendingReq, authnReqEndpoint, SAMLRequest, authnRequest, response);
+
+ //TODO: redirect Binding is not completely implemented
+ //else if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(authnReqEndpoint.getBinding()))
+ //buildRedirecttBindingRequest(pendingReq, authnReqEndpoint, token, authnRequest, response);
+
+ else {
+ Logger.error("eIDAS-node use an unsupported binding ("
+ + authnReqEndpoint.getBinding() + "). Request eIDAS node not possible.");
+ throw new MOAIDException("eIDAS.02", new Object[]{"eIDAS-node use an unsupported binding"});
+
+ }
+
- revisionsLogger.logEvent(oaConfig, pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED,
- authnRequest.getRequest().getId());
-
- } catch (Exception e) {
- Logger.error("Velocity general error: " + e.getMessage());
- throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
-
- }
}catch (EIDASSAMLEngineException e){
throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.",
@@ -280,6 +270,102 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
}
}
+ /**
+ * Encode the eIDAS request with Redirect binding
+ *
+ * @param pendingReq
+ * @param authnReqEndpoint
+ * @param token
+ * @param authnRequest
+ * @param response
+ * @throws MOAIDException
+ */
+ private void buildRedirecttBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
+ byte[] token, IRequestMessage authnRequest, HttpServletResponse response)
+ throws MOAIDException {
+
+ //FIXME: implement correct deflat encoding accodring to SAML2 Redirect Binding specification
+
+ try {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ Deflater deflater = new Deflater(Deflater.DEFLATED, true);
+ DeflaterOutputStream deflaterStream = new DeflaterOutputStream(bytesOut, deflater);
+ deflaterStream.write(token);
+ deflaterStream.finish();
+ String samlReqBase64 = Base64.encodeBytes(bytesOut.toByteArray(), Base64.DONT_BREAK_LINES);
+
+
+
+ } catch (Exception e) {
+ Logger.error("eIDAS Redirect-Binding request encoding error: " + e.getMessage());
+ throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Encode the eIDAS request with POST binding
+ *
+ * @param pendingReq
+ * @param authnReqEndpoint
+ * @param SAMLRequest
+ * @param authnRequest
+ * @param response
+ * @throws MOAIDException
+ */
+ private void buildPostBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
+ String SAMLRequest, IRequestMessage authnRequest, HttpServletResponse response)
+ throws MOAIDException {
+ //send
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
+ VelocityContext context = new VelocityContext();
+
+ String actionType = "SAMLRequest";
+ context.put(actionType, SAMLRequest);
+ Logger.debug("Encoded " + actionType + " original: " + SAMLRequest);
+
+ context.put("RelayState", pendingReq.getRequestID());
+
+ Logger.debug("Using assertion consumer url as action: " + authnReqEndpoint.getLocation());
+ context.put("action", authnReqEndpoint.getLocation());
+
+ Logger.debug("Starting template merge");
+ StringWriter writer = new StringWriter();
+
+ Logger.debug("Doing template merge");
+ template.merge(context, writer);
+ Logger.debug("Template merge done");
+
+ Logger.debug("Sending html content: " + writer.getBuffer().toString());
+
+
+ byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
+ response.setContentType(MediaType.HTML_UTF_8.toString());
+ response.setContentLength(content.length);
+ response.getOutputStream().write(content);
+
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED,
+ authnRequest.getRequest().getId());
+
+ } catch (Exception e) {
+ Logger.error("Velocity general error: " + e.getMessage());
+ throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Select a SingleSignOnService endPoint from eIDAS node metadata.
+ * This endPoint receives the Authn. request
+ *
+ * @param idpEntity
+ * @return
+ */
private SingleSignOnService selectSingleSignOnServiceFromMetadata(EntityDescriptor idpEntity) {
//select SingleSignOn Service endpoint from IDP metadata
SingleSignOnService endpoint = null;
@@ -294,7 +380,9 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
// use POST binding as default if it exists
if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))
endpoint = sss;
-
+
+ //TODO: redirect Binding is not completely implemented
+ // use Redirect binding as backup
// else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)
// && endpoint == null )
// endpoint = sss;
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
new file mode 100644
index 000000000..7d647ff15
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
@@ -0,0 +1,96 @@
+/*
+ * 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.eidas.utils;
+
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+
+import com.google.common.collect.ImmutableSet;
+
+import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAWhiteListConfigurator {
+ private static final Pattern WHITE_LIST_SPLITTER = Pattern.compile("[;,]");
+
+
+ public static ImmutableSet<String> getAllowedAlgorithms( ImmutableSet<String> defaultWhiteList,
+ ImmutableSet<String> allowedValues,
+ String algorithmWhiteListValue) {
+ if (StringUtils.isBlank(algorithmWhiteListValue)) {
+ return defaultWhiteList;
+ }
+ ImmutableSet.Builder<String> allowed = ImmutableSet.builder();
+ String[] wlAlgorithms = WHITE_LIST_SPLITTER.split(algorithmWhiteListValue);
+ if (null != wlAlgorithms && wlAlgorithms.length > 0) {
+ return getAllowedAlgorithms(defaultWhiteList, allowedValues, ImmutableSet.<String>copyOf(wlAlgorithms));
+ }
+ return defaultWhiteList;
+ }
+
+
+ public static ImmutableSet<String> getAllowedAlgorithms( ImmutableSet<String> defaultWhiteList,
+ ImmutableSet<String> allowedValues,
+ ImmutableSet<String> candidateValues) {
+ if (CollectionUtils.isEmpty(candidateValues)) {
+ return defaultWhiteList;
+ }
+ ImmutableSet.Builder<String> allowed = ImmutableSet.builder();
+ boolean modified = false;
+ for (String candidateValue : candidateValues) {
+
+ /**FIX:
+ * fix problem with lowerCase and MGF1 signature algorithms
+ *
+ */
+ candidateValue = StringUtils.trimToNull(
+ KeyValueUtils.removeAllNewlineFromString(candidateValue));
+ if (StringUtils.isNotBlank(candidateValue)) {
+ String candidateAlgorithm = StringUtils.lowerCase(candidateValue, Locale.ENGLISH);
+ if (allowedValues.contains(candidateAlgorithm)) {
+ allowed.add(candidateValue);
+ if (!modified && !candidateAlgorithm.equals(candidateValue)) {
+ modified = true;
+ }
+ } else {
+ modified = true;
+ }
+ }
+ }
+ if (!modified) {
+ return candidateValues;
+ }
+ ImmutableSet<String> set = allowed.build();
+ if (set.isEmpty()) {
+ return defaultWhiteList;
+ }
+ return set;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
index 09c3dff38..dd14972e3 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
@@ -35,6 +35,7 @@ import org.joda.time.DurationFieldType;
import org.opensaml.Configuration;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.common.Extensions;
+import org.opensaml.saml2.common.impl.ExtensionsBuilder;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeValue;
import org.opensaml.saml2.metadata.AssertionConsumerService;
@@ -52,6 +53,7 @@ import org.opensaml.saml2.metadata.LocalizedString;
import org.opensaml.saml2.metadata.NameIDFormat;
import org.opensaml.saml2.metadata.Organization;
import org.opensaml.saml2.metadata.OrganizationDisplayName;
+import org.opensaml.saml2.metadata.OrganizationName;
import org.opensaml.saml2.metadata.OrganizationURL;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.SSODescriptor;
@@ -76,6 +78,7 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import eu.eidas.auth.commons.EIDASUtil;
import eu.eidas.auth.commons.EidasStringUtil;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
@@ -126,8 +129,17 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
entityDescriptor.setEntityID(params.getEntityID());
entityDescriptor.setOrganization(buildOrganization());
- entityDescriptor.getContactPersons().add(buildContact(ContactPersonTypeEnumeration.SUPPORT));
- entityDescriptor.getContactPersons().add(buildContact(ContactPersonTypeEnumeration.TECHNICAL));
+
+ /**FIXME:
+ * HOTFIX: do not add empty contactPerson elements
+ */
+ ContactPerson contactSupport = buildContact(ContactPersonTypeEnumeration.SUPPORT);
+ if (contactSupport != null)
+ entityDescriptor.getContactPersons().add(contactSupport);
+ ContactPerson contactTech = buildContact(ContactPersonTypeEnumeration.TECHNICAL);
+ if (contactTech != null)
+ entityDescriptor.getContactPersons().add(contactTech);
+
entityDescriptor.setValidUntil(getExpireDate());
X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory();
@@ -164,8 +176,15 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
//the node has SP role
spSSODescriptor.setWantAssertionsSigned(params.isWantAssertionsSigned());
spSSODescriptor.setAuthnRequestsSigned(true);
- spSSODescriptor.setID(idpSSODescriptor == null ? params.getEntityID()
- : ("SP" + params.getEntityID()));
+
+
+ /**FIXME:
+ * "SP" + params.getEntityID()) is not a valid XML ID attribute value
+ */
+ //spSSODescriptor.setID(idpSSODescriptor == null ? params.getEntityID() : ("SP" + params.getEntityID()));
+ spSSODescriptor.setID(SAML2Utils.getSecureIdentifier());
+
+
if (params.getSPSignature() != null) {
spSSODescriptor.setSignature(params.getSPSignature());
}
@@ -220,8 +239,13 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
SAMLEngineException, EIDASSAMLEngineException {
//the node has IDP role
idpSSODescriptor.setWantAuthnRequestsSigned(true);
- idpSSODescriptor.setID(spSSODescriptor == null ? params.getEntityID()
- : ("IDP" + params.getEntityID()));
+
+ /**FIXME:
+ * "IDP" + params.getEntityID()) is not a valid XML ID attribute value
+ */
+ //idpSSODescriptor.setID(spSSODescriptor == null ? params.getEntityID() : ("IDP" + params.getEntityID()));
+ idpSSODescriptor.setID(SAML2Utils.getSecureIdentifier());
+
if (params.getIDPSignature() != null) {
idpSSODescriptor.setSignature(params.getIDPSignature());
}
@@ -341,8 +365,16 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
private Organization buildOrganization() {
Organization organization = null;
- try {
+ try {
organization = BuilderFactoryUtil.buildXmlObject(Organization.class);
+
+ /**FIXME:
+ * set correct OrganizationName value if it is not fixed in next eIDAS node version
+ */
+ OrganizationName orgName = BuilderFactoryUtil.buildXmlObject(OrganizationName.class);
+ orgName.setName(new LocalizedString(params.getNodeUrl(), "en"));
+ organization.getOrganizationNames().add(orgName);
+
OrganizationDisplayName odn = BuilderFactoryUtil.buildXmlObject(OrganizationDisplayName.class);
odn.setName(new LocalizedString(params.getCountryName(), "en"));
organization.getDisplayNames().add(odn);
@@ -373,7 +405,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
contact = BuilderFactoryUtil.buildXmlObject(ContactPerson.class);
if (currentContact == null) {
LOGGER.error("ERROR: cannot retrieve contact from the configuration");
- return contact;
+ return null;
}
EmailAddress emailAddressObj = BuilderFactoryUtil.buildXmlObject(EmailAddress.class);
@@ -514,7 +546,14 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
}
private Extensions generateExtensions() throws EIDASSAMLEngineException {
- Extensions eidasExtensions = BuilderFactoryUtil.generateExtension();
+ /**FIXME: BuilderFactoryUtil.generateExtension() generates extensions from SAML2 request namespace
+ * but SAML2 metadata namespace is required
+ **/
+ //Extensions eidasExtensions = BuilderFactoryUtil.generateExtension();
+
+ ExtensionsBuilder extensionsBuilder = new ExtensionsBuilder();
+ Extensions eidasExtensions = extensionsBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:metadata", "Extensions", "md");
+
if (params.getAssuranceLevel() != null) {
generateLoA(eidasExtensions);
}
diff --git a/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/ELGAMandatesAuthModuleImpl.java b/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/ELGAMandatesAuthModuleImpl.java
index c2efe5bfc..f14ffb111 100644
--- a/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/ELGAMandatesAuthModuleImpl.java
+++ b/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/ELGAMandatesAuthModuleImpl.java
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import at.gv.egovernment.moa.id.auth.modules.internal.DefaultCitizenCardAuthModuleImpl;
import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
+import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -56,8 +57,9 @@ public class ELGAMandatesAuthModuleImpl extends DefaultCitizenCardAuthModuleImpl
//check if BKU authentication is selected and ELGA-MandateService is configurated
if (MiscUtil.isNotEmpty(selectedProcessID)) {
- if (MiscUtil.isNotEmpty(authConfig.getBasicMOAIDConfiguration(
- ELGAMandatesAuthConstants.CONFIG_PROPS_ENTITYID)))
+ if (MiscUtil.isNotEmpty(authConfig.getConfigurationWithKey(
+ MOAIDConfigurationConstants.PREFIX_MOAID_GENERAL + "."
+ + ELGAMandatesAuthConstants.CONFIG_PROPS_ENTITYID)))
return "DefaultAuthenticationWithELGAMandates";
}
diff --git a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java
index 118c53f6b..75ea41449 100644
--- a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java
+++ b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java
@@ -204,9 +204,11 @@ public class OAuth20Protocol extends AbstractAuthProtocolModulController {
OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR, errorCode);
OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_DESCRIPTION, errorDescription);
- if (MiscUtil.isNotEmpty(moaError))
- OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_URI, errorUri + "#" + moaError);
OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_STATE, state);
+ if (MiscUtil.isNotEmpty(moaError))
+ OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_URI,
+ URLEncoder.encode(errorUri + "#" + moaError, "UTF-8"));
+
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_FOUND);
@@ -220,7 +222,8 @@ public class OAuth20Protocol extends AbstractAuthProtocolModulController {
Map<String, Object> params = new HashMap<String, Object>();
params.put(OAuth20Constants.PARAM_ERROR, errorCode);
params.put(OAuth20Constants.PARAM_ERROR_DESCRIPTION, errorDescription);
- params.put(OAuth20Constants.PARAM_ERROR_URI, errorUri + "#" + moaError);
+ params.put(OAuth20Constants.PARAM_ERROR_URI,
+ URLEncoder.encode(errorUri + "#" + moaError, "UTF-8"));
// create response
JsonObject jsonObject = new JsonObject();
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
index cf4590fc1..1a216f0df 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
@@ -184,20 +184,9 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
//TODO: implement Signature validation
Logger.debug("MobileDevice is valid. --> Starting session reconstruction ...");
-
-
- //session is valid --> load MOASession object
- try {
- defaultTaskInitialization(request, executionContext);
-
- } catch (MOAIDException | MOADatabaseException e1) {
- Logger.error("Database Error! MOASession is not stored!");
- throw new TaskExecutionException(pendingReq, "Load MOASession FAILED.", e1);
-
- }
-
+
//transfer SSO Assertion into MOA-Session
- ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, attributeExtractor);
+ ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, pendingReq.getMOASession(), attributeExtractor);
// store MOASession into database
requestStoreage.storePendingRequest(pendingReq);