aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java178
1 files changed, 133 insertions, 45 deletions
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;