From 1df90d0efe126150b5e1cfa245a5ad9280068243 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 12 Jan 2016 09:46:57 +0100 Subject: update eIDAS inbound process managment implementation --- .../moa/id/auth/modules/eidas/Constants.java | 1 + .../id/auth/modules/eidas/eIDASSignalServlet.java | 44 ++++++++++++- .../eidas/tasks/GenerateAuthnRequestTask.java | 21 +++++- .../eidas/tasks/ReceiveAuthnResponseTask.java | 74 +++++++++++++++++++++- 4 files changed, 134 insertions(+), 6 deletions(-) (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment') 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 3f94ca5e5..8e38facbf 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 @@ -54,4 +54,5 @@ public class Constants { public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file"; + public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java index 0c31a87a4..556947572 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java @@ -22,14 +22,24 @@ */ package at.gv.egovernment.moa.id.auth.modules.eidas; +import java.io.ByteArrayInputStream; + import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathFactory; import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.xml.SimpleNamespaceContext; +import org.w3c.dom.Document; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; /** * @author tlenz @@ -58,9 +68,39 @@ public class eIDASSignalServlet extends ProcessEngineSignalServlet { * */ public String getMoaSessionId(HttpServletRequest request) { - //TODO: implement eIDAs specific session synchronization + String sessionId = super.getMoaSessionId(request); - return StringEscapeUtils.escapeHtml(request.getParameter(MOAIDAuthConstants.PARAM_SESSIONID)); + try { + + // use SAML2 relayState + if (sessionId == null) { + sessionId = StringEscapeUtils.escapeHtml(request.getParameter("RelayState")); + } + + // take from InResponseTo attribute of SAMLResponse + if (sessionId == null) { + String base64SamlToken = request.getParameter("SAMLResponse"); + if (base64SamlToken != null && false) { +// byte[] samlToken = Base64Utils.decode(base64SamlToken, false); +// Document samlResponse = parseDocument(new ByteArrayInputStream(samlToken)); +// +// XPath xPath = XPathFactory.newInstance().newXPath(); +// SimpleNamespaceContext nsContext = new SimpleNamespaceContext(); +// nsContext.bindNamespaceUri("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol"); +// xPath.setNamespaceContext(nsContext); +// XPathExpression expression = xPath.compile("string(/saml2p:Response/@InResponseTo)"); +// sessionId = (String) expression.evaluate(samlResponse, XPathConstants.STRING); +// sessionId = StringEscapeUtils.escapeHtml(StringUtils.trimToNull(sessionId)); + } else { + Logger.warn("No parameter 'SAMLResponse'. Unable to retrieve MOA session id."); + } + } + + } catch (Exception e) { + Logger.warn("Unable to retrieve moa session id.", e); + } + + return sessionId; } } 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 8b1dae22e..9ae61edd9 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 @@ -96,19 +96,30 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { //TODO: load required attributes from OA configuration PersonalAttribute attr = new PersonalAttribute(); attr.setName("eidas/attributes/CurrentFamilyName"); - pAttList.add(attr); + PersonalAttribute attr1 = new PersonalAttribute(); + attr1.setName("eidas/attributes/CurrentGivenName"); + pAttList.add(attr1); + + PersonalAttribute attr2 = new PersonalAttribute(); + attr2.setName("eidas/attributes/DateOfBirth"); + pAttList.add(attr2); + + PersonalAttribute attr3 = new PersonalAttribute(); + attr3.setName("eidas/attributes/PersonIdentifier"); + pAttList.add(attr3); + //build eIDAS AuthnRequest EIDASAuthnRequest authnRequest = new EIDASAuthnRequest(); String assertionConsumerURL="https://demo.a-sit.at/EidasNode/ColleagueRequest"; - authnRequest.setAssertionConsumerServiceURL(assertionConsumerURL); +// authnRequest.setAssertionConsumerServiceURL(assertionConsumerURL); String providerName = "sp3fr-moa"; authnRequest.setProviderName(providerName); // int qaaLevel = 1; // authnRequest.setQaa(qaaLevel); // not needed anymore. furthermore this may make the node think the request at hand is a stork request and we do not want that. authnRequest.setPersonalAttributeList(pAttList); - String issuer = "http://localhost:12344/moa-id-auth/eidas/metadata"; + String issuer = "http://localhost:12343/moa-id-auth/eidas/metadata"; authnRequest.setIssuer(issuer); authnRequest.setDestination(assertionConsumerURL); authnRequest.setEidasNameidFormat(EIDASAuthnRequest.NAMEID_FORMAT_UNSPECIFIED); @@ -116,6 +127,8 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { authnRequest.setEidasLoACompareType(EidasLoaCompareType.MINIMUM.stringValue()); authnRequest.setAlias(providerName); + authnRequest.setSPType("public"); + engine.initRequestedAttributes(pAttList); authnRequest = engine.generateEIDASAuthnRequest(authnRequest); @@ -134,6 +147,8 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { context.put(actionType, SAMLRequest); Logger.debug("Encoded " + actionType + " original: " + SAMLRequest); + context.put("RelayState", moasessionid); + Logger.debug("Using assertion consumer url as action: " + assertionConsumerURL); context.put("action", assertionConsumerURL); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java index 8fdb40065..e80d62535 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java @@ -3,16 +3,88 @@ package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import eu.eidas.auth.commons.EIDASAuthnResponse; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; + +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.MOAIDException; 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.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestStorage; 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; public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { @Override public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { - System.out.println(request.getContentLength()); + try{ + String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID); + String pendingRequestID = (String) executionContext.get("pendingRequestID"); + + //load pending request + IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure."); + throw new MOAIDException("auth.28", new Object[]{pendingRequestID}); + + } + + //load MOASession object and OA-configuration + AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid); + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + + //get SAML Response and decode it + String base64SamlToken = request.getParameter("SAMLResponse"); + if (MiscUtil.isEmpty(base64SamlToken)) { + Logger.warn("No eIDAS SAMLReponse found in http request."); + throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null); + + } + byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken); + + //get eIDAS SAML-engine + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //validate SAML token + EIDASAuthnResponse samlResp = engine.validateEIDASAuthnResponse(decSamlToken, + request.getRemoteHost(), Constants.CONFIG_PROPS_SKEWTIME); + + boolean encryptedResponse=engine.isEncryptedSamlResponse(decSamlToken); + if (encryptedResponse) { + Logger.info("Received encrypted eIDAS SAML-Response."); + //TODO: check if additional decryption operation is required + + } + + + + + System.out.println(new String(decSamlToken)); + + + }catch (EIDASSAMLEngineException e) { + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", + new EIDASEngineException("Could not generate token for Saml Request", e)); + + } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", e); + + } + } } -- cgit v1.2.3