diff options
Diffstat (limited to 'id/server/modules')
43 files changed, 3374 insertions, 396 deletions
diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java deleted file mode 100644 index 72a7d3ba1..000000000 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.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. - ******************************************************************************/ -/* - * Copyright 2003 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.invoke; - -import java.util.Vector; - -import javax.xml.namespace.QName; -import javax.xml.rpc.Call; -import javax.xml.rpc.Service; -import javax.xml.rpc.ServiceFactory; - -import org.apache.axis.message.SOAPBodyElement; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import at.gv.egovernment.moa.id.auth.exception.ServiceException; -import at.gv.egovernment.moa.id.config.ConnectionParameter; -import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.spss.api.SignatureVerificationService; -import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureRequestParser; -import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureResponseBuilder; -import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest; -import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; -import at.gv.egovernment.moa.util.MiscUtil; - -/** - * Invoker of the <code>SignatureVerification</code> web service of MOA-SPSS.<br> - * Either invokes the web service, or calls the corresponding API, depending on configuration data. - * - * @author Stefan Knirsch - * @version $Id$ - */ -public class SignatureVerificationInvoker { - /** This QName Object identifies the SignatureVerification endpoint of the web service */ - private static final QName SERVICE_QNAME = new QName("SignatureVerification"); - - /** - * Method verifyXMLSignature. - * @param request to be sent - * @return Element with the answer - * @throws ServiceException if an error occurs - */ - public Element verifyXMLSignature(Element request) throws ServiceException { - return doCall(SERVICE_QNAME, request); - } - - /** - * Method doCall. - * @param serviceName the name of the service - * @param request the request to be sent - * @return Element the answer - * @throws ServiceException if an error occurs - */ - protected Element doCall(QName serviceName, Element request) throws ServiceException { - ConnectionParameter authConnParam = null; - try { - Service service = ServiceFactory.newInstance().createService(serviceName); - Call call = service.createCall(); - SOAPBodyElement body = new SOAPBodyElement(request); - SOAPBodyElement[] params = new SOAPBodyElement[] { body }; - Vector responses; - SOAPBodyElement response; - - String endPoint; - AuthConfiguration authConfigProvider = AuthConfigurationProviderFactory.getInstance(); - authConnParam = authConfigProvider.getMoaSpConnectionParameter(); - //If the ConnectionParameter do NOT exist, we try to get the api to work.... - if (authConnParam != null && MiscUtil.isNotEmpty(authConnParam.getUrl())) { - Logger.debug("Connecting using auth url: " + authConnParam.getUrl() + ", service " + serviceName.getNamespaceURI() + " : " + serviceName.getLocalPart() + " : "+ serviceName.getPrefix()); - endPoint = authConnParam.getUrl(); - call.setTargetEndpointAddress(endPoint); - responses = (Vector) call.invoke(serviceName, params); - Logger.debug("Got responses: " + responses.size()); // TODO handle axis 302 response when incorrect service url is used - response = (SOAPBodyElement) responses.get(0); - return response.getAsDOM(); - } - else { - SignatureVerificationService svs = SignatureVerificationService.getInstance(); - VerifyXMLSignatureRequest vsrequest = new VerifyXMLSignatureRequestParser().parse(request); - - VerifyXMLSignatureResponse vsresponse = svs.verifyXMLSignature(vsrequest); - Document result = new VerifyXMLSignatureResponseBuilder().build(vsresponse); - - //Logger.setHierarchy("moa.id.auth"); - return result.getDocumentElement(); - } - } - catch (Exception ex) { - if (authConnParam != null) { - throw new ServiceException("service.00", new Object[] { ex.toString()}, ex); - } else { - throw new ServiceException("service.03", new Object[] { ex.toString()}, ex); - } - } - } -} diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java deleted file mode 100644 index 7bce406e0..000000000 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java +++ /dev/null @@ -1,211 +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. - ******************************************************************************/ -/* - * Copyright 2003 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.parser; - -import iaik.utils.Base64InputStream; -import iaik.x509.X509Certificate; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -import org.w3c.dom.Element; - -import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; -import at.gv.egovernment.moa.id.auth.exception.ParseException; -import at.gv.egovernment.moa.util.Constants; -import at.gv.egovernment.moa.util.DOMUtils; -import at.gv.egovernment.moa.util.XPathUtils; - -/** - * Parses a <code><VerifyXMLSignatureResponse></code> returned by - * MOA-SPSS. - * This class implements the Singleton pattern - * - * @author Stefan Knirsch - * @version $Id$ - */ - - -public class VerifyXMLSignatureResponseParser { - // - // XPath namespace prefix shortcuts - // - /** Xpath prefix for reaching MOA Namespaces */ - private static final String MOA = Constants.MOA_PREFIX + ":"; - /** Xpath prefix for reaching DSIG Namespaces */ - private static final String DSIG = Constants.DSIG_PREFIX + ":"; - /** Xpath expression to the root element */ - private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/"; - - /** Xpath expression to the X509SubjectName element */ - private static final String DSIG_SUBJECT_NAME_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - DSIG + "X509SubjectName"; - /** Xpath expression to the X509Certificate element */ - private static final String DSIG_X509_CERTIFICATE_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - DSIG + "X509Certificate"; - /** Xpath expression to the PublicAuthority element */ - private static final String PUBLIC_AUTHORITY_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - MOA + "PublicAuthority"; - /** Xpath expression to the PublicAuthorityCode element */ - private static final String PUBLIC_AUTHORITY_CODE_XPATH = - PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code"; - /** Xpath expression to the QualifiedCertificate element */ - private static final String QUALIFIED_CERTIFICATE_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - MOA + "QualifiedCertificate"; - - /** Xpath expression to the SignatureCheckCode element */ - private static final String SIGNATURE_CHECK_CODE_XPATH = - ROOT + MOA + "SignatureCheck/" + MOA + "Code"; - /** Xpath expression to the XMLDSIGManifestCheckCode element */ - private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH = - ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code"; - /** Xpath expression to the SignatureManifestCheckCode element */ - private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH = - ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code"; - /** Xpath expression to the CertificateCheckCode element */ - private static final String CERTIFICATE_CHECK_CODE_XPATH = - ROOT + MOA + "CertificateCheck/" + MOA + "Code"; - - - /** This is the root element of the XML-Document provided by the Security Layer Card*/ - private Element verifyXMLSignatureResponse; - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * A DOM-representation of the incoming String will be created - * @param xmlResponse <code><InfoboxReadResponse></code> as String - * @throws ParseException on any parsing error - */ - public VerifyXMLSignatureResponseParser(String xmlResponse) throws ParseException{ - try { - InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8")); - - verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(s); - } - catch (Throwable t) { - throw new ParseException("parser.01", new Object[] { t.toString() }, t); - } - } - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * A DOM-representation of the incoming Inputstream will be created - * @param xmlResponse <code><InfoboxReadResponse></code> as InputStream - * @throws Exception on any parsing error - */ - public VerifyXMLSignatureResponseParser(InputStream xmlResponse) throws Exception - { - try { - verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse); - } - catch (Throwable t) { - throw new ParseException("parser.01", null, t); - } - } - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * The incoming Element will be used for further operations - * @param xmlResponse <code><InfoboxReadResponse></code> as Element - */ - public VerifyXMLSignatureResponseParser(Element xmlResponse) - { - verifyXMLSignatureResponse =xmlResponse; - - } - - /** - * Parse identity link from <code><InfoboxReadResponse></code> - * @return Identity link - * @throws ParseException on any parsing error - */ - - public VerifyXMLSignatureResponse parseData() throws ParseException { - - VerifyXMLSignatureResponse respData=new VerifyXMLSignatureResponse(); - - try { - - String s = DOMUtils.serializeNode(verifyXMLSignatureResponse); - respData.setXmlDsigSubjectName(XPathUtils.getElementValue(verifyXMLSignatureResponse,DSIG_SUBJECT_NAME_XPATH,"")); - Element e = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,QUALIFIED_CERTIFICATE_XPATH); - respData.setQualifiedCertificate(e!=null); - - Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(XPathUtils.getElementValue( - verifyXMLSignatureResponse,DSIG_X509_CERTIFICATE_XPATH,"").getBytes("UTF-8")),true); - - respData.setX509certificate(new X509Certificate(in)); - Element publicAuthority = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_XPATH); - respData.setPublicAuthority(publicAuthority != null); - respData.setPublicAuthorityCode(XPathUtils.getElementValue(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH,"")); - respData.setSignatureCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_CHECK_CODE_XPATH,"")).intValue()); - - String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,XMLDSIG_MANIFEST_CHECK_CODE_XPATH,null); - if (xmlDsigCheckCode!=null) { - respData.setXmlDSIGManigest(true); - respData.setXmlDSIGManifestCheckCode(new Integer(xmlDsigCheckCode).intValue()); - } else { - respData.setXmlDSIGManigest(false); - } - String signatureManifestCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_MANIFEST_CHECK_CODE_XPATH,null); - if (signatureManifestCheckCode != null) { - respData.setSignatureManifestCheckCode(new Integer(signatureManifestCheckCode).intValue()); - } - respData.setCertificateCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,CERTIFICATE_CHECK_CODE_XPATH,"")).intValue()); - } - catch (Throwable t) { - throw new ParseException("parser.01", null, t); - } - return respData; - } - - -} diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml new file mode 100644 index 000000000..b43efac9e --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/pom.xml @@ -0,0 +1,111 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>MOA.id.server.modules</groupId> + <artifactId>moa-id-modules</artifactId> + <version>${moa-id-version}</version> + </parent> + <artifactId>moa-id-module-eIDAS</artifactId> + <name>MOA-ID eIDAS Module</name> + <description>Inbound / outbound implemention of eIDAS protocol for MOA-ID</description> + + <properties> + <repositoryPath>${basedir}/../../../../repository</repositoryPath> + + <eidas-commons.version>eidas.1.0</eidas-commons.version> + <eidas-saml-engine.version>eidas.1.0</eidas-saml-engine.version> + + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <!-- eidas Commons --> + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>eidas-commons</artifactId> + <version>${eidas-commons.version}</version> + <!--scope>provided</scope--> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + <exclusion> + <artifactId>log4j-over-slf4j</artifactId> + <groupId>org.slf4j</groupId> + </exclusion> + </exclusions> + </dependency> + + <!-- eidas SAML Engine --> + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>saml-engine</artifactId> + <version>${eidas-saml-engine.version}</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>xalan</groupId> + <artifactId>serializer</artifactId> + </exclusion> + <exclusion> + <groupId>xalan</groupId> + <artifactId>xalan</artifactId> + </exclusion> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>xml-resolver</groupId> + <artifactId>xml-resolver</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.52</version> + <!-- <scope>provided</scope> --> + </dependency> + + + </dependencies> + +</project>
\ No newline at end of file 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 new file mode 100644 index 000000000..5166f090d --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -0,0 +1,75 @@ +/* + * 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; + +/** + * @author tlenz + * + */ +public class Constants { + + public static final String eIDAS_SAML_ENGINE_NAME = "default"; + public static final String SSLSOCKETFACTORYNAME = "eIDASMetadataSSLSocketFactory"; + + //default keys for eIDAS SAML-engine configuration + public static final String eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG = "SamlEngineConf"; + public static final String eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG = "SignatureConf"; + public static final String eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG = "EncryptionConf"; + 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_ENCRYPTION_IMPLENTATION = "eu.eidas.auth.engine.core.impl.EncryptionSW"; + + //configuration property keys + public static final String CONIG_PROPS_EIDAS_PREFIX="moa.id.protocols.eIDAS"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE="samlengine"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX=CONIG_PROPS_EIDAS_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".config.file"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN="sign"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT="enc"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." + + CONIG_PROPS_EIDAS_SAMLENGINE_SIGN + ".config.file"; + 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 String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore"; + + //timeouts and clock skews + public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation + public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout + public static final long CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT = 7 * 24 * 60 * 60 * 1000; //remove unused eIDAS metadata after 7 days + + //eIDAS attribute names + public static final String eIDAS_ATTR_PERSONALIDENTIFIER = "PersonIdentifier"; + public static final String eIDAS_ATTR_DATEOFBIRTH = "DateOfBirth"; + public static final String eIDAS_ATTR_CURRENTGIVENNAME = "CurrentGivenName"; + public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "CurrentFamilyName"; + + //http endpoint descriptions + public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/sp/post"; + public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/sp/redirect"; + public static final String eIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/idp/post"; + public static final String eIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/idp/redirect"; + public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/metadata"; + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java new file mode 100644 index 000000000..9b634ff4d --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java @@ -0,0 +1,118 @@ +/* + * 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.config; + +import java.util.HashMap; +import java.util.Map; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.config.ConfigurationException; +import eu.eidas.samlengineconfig.AbstractCertificateConfigurationManager; +import eu.eidas.samlengineconfig.EngineInstance; +import eu.eidas.samlengineconfig.SamlEngineConfiguration; +import eu.eidas.samlengineconfig.impl.SamlEngineConfigurationImpl; + +/** + * @author tlenz + * + */ +public class MOAIDCertificateManagerConfigurationImpl extends + AbstractCertificateConfigurationManager { + + private SamlEngineConfiguration samlEngineConfiguration =null; + + @Override + public boolean isActive() { + return true; + } + + /** + * + */ + public MOAIDCertificateManagerConfigurationImpl() { + try { + initalizeConfiguration(); + + } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) { + Logger.error("eIDAS SAML-engine initialization FAILED", e); + + } + } + + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#addConfiguration(java.lang.String, java.lang.String, java.util.Map, boolean) + */ + @Override + public void addConfiguration(String paramString1, String paramString2, + Map<String, String> paramMap, boolean paramBoolean) { + throw new ConfigurationException("","not yet implemented"); + + } + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getInstance(java.lang.String) + */ + @Override + public EngineInstance getInstance(String paramString) { + return getConfiguration().get(paramString); + + } + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getConfiguration() + */ + @Override + public Map<String, EngineInstance> getConfiguration() { + if(samlEngineConfiguration == null){ + try { + initalizeConfiguration(); + + } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) { + Logger.error("eIDAS SAML-engine initialization FAILED", e); + + } + + } + + return samlEngineConfiguration==null?new HashMap<String, EngineInstance>():((MOAeIDASSAMLEngineConfigurationImpl) samlEngineConfiguration).getInstanceMap(); + + } + + + /** + * Initialize eIDAS SAML-engine from MOA-ID configuration + * @throws at.gv.egovernment.moa.id.config.ConfigurationException + * + */ + private void initalizeConfiguration() throws at.gv.egovernment.moa.id.config.ConfigurationException { + //initialize configuration + MOAeIDASSAMLEngineConfigurationImpl tmp = new MOAeIDASSAMLEngineConfigurationImpl(); + tmp.initialize(); + + //set initialized configuration + samlEngineConfiguration = tmp; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java new file mode 100644 index 000000000..584910ea5 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java @@ -0,0 +1,268 @@ +/* + * 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.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineConfigurationException; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.FileUtils; +import at.gv.egovernment.moa.util.MiscUtil; + +import eu.eidas.samlengineconfig.BinaryParameter; +import eu.eidas.samlengineconfig.ConfigurationParameter; +import eu.eidas.samlengineconfig.EngineInstance; +import eu.eidas.samlengineconfig.InstanceConfiguration; +import eu.eidas.samlengineconfig.PropsParameter; +import eu.eidas.samlengineconfig.SamlEngineConfiguration; + +/** + * @author tlenz + * + */ +public class MOAeIDASSAMLEngineConfigurationImpl extends + SamlEngineConfiguration { + + private static final String KEYSTORE_PATH="keystorePath"; + private static final String METADATA_KEYSTORE_PATH="metadata.keystorePath"; + private static final String ENCRYPTION_ACTIVATION="encryptionActivation"; + private static final String[] BINARY_PARAMETERS={KEYSTORE_PATH, ENCRYPTION_ACTIVATION,METADATA_KEYSTORE_PATH}; + + public List<EngineInstance> getInstances(){ + return super.getInstances(); + } + + @Override + public void setInstances(List<EngineInstance> engineInstances) { + super.setInstances(engineInstances); + + } + + public Map<String, EngineInstance> getInstanceMap() { + Map<String, EngineInstance> result = new HashMap<String, EngineInstance>(); + for(EngineInstance instance:getInstances()) { + + result.put(instance.getName(), instance); + } + + return result; + } + + //initialize + public void initialize() throws ConfigurationException { + //create an eIDAS SAML-engine instance + EngineInstance engineInst = new EngineInstance(); + engineInst.setName(Constants.eIDAS_SAML_ENGINE_NAME); + List<InstanceConfiguration> engineConfigs = new ArrayList<InstanceConfiguration>(); + + + //add configurations + + //add basic eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlBaseConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlBaseConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG); + samlBaseConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE)); + engineConfigs.add(samlBaseConfig); + + //add signing eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlSignConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlSignConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG); + samlSignConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, + Constants.SAML_SIGNING_IMPLENTATION); + + //TODO: load signing keys directly from MOA-ID configuration in finale version + samlSignConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE)); + engineConfigs.add(samlSignConfig); + + //add encryption eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlEncConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlEncConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG); + samlEncConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, + Constants.SAML_ENCRYPTION_IMPLENTATION); + + //TODO: load encryption keys directly from MOA-ID configuration in finale version + samlEncConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE)); + engineConfigs.add(samlEncConfig); + + engineInst.setConfigurations(engineConfigs); + super.addInstance(engineInst); + + } + + /** + * Load an external eIDAS SAML-engine configuration file, which is referenced from MOA-ID configuration + * + * @param key Configuration key, which is used in property based MOA-ID configuration file + * @return eIDAS SAML-engine configuration object + * @throws ConfigurationException + */ + + private ConfigurationParameter loadConfigurationFromExternalFile(String key) throws ConfigurationException { + String configFile = + AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(key); + if (MiscUtil.isEmpty(configFile)) { + Logger.warn("No eIDAS SAML-engine configuration key: " + + key + " found in MOA-ID properties configuration file."); + //throw new EIDASEngineConfigurationException("No eIDAS SAML-engine configuration property.", null); + return null; + } + + Properties inputProps = loadPropsFromXml(configFile); + return buildPropsParameter(inputProps, configFile); + + } + + + private PropsParameter buildPropsParameter(Properties inputProps, String fileName) throws EIDASEngineConfigurationException { + PropsParameter outputProps = new PropsParameter(); + outputProps.setFileName(fileName); + + //original eIDAS SAML-engine use this identifier + outputProps.setName("fileConfiguration"); + + outputProps.setValue(inputProps); + + //post-process special parameters + for(String key:BINARY_PARAMETERS) { + Object keystorePath = inputProps.get(key); + if (keystorePath != null) { + if (keystorePath instanceof String && + isBinaryParameter((String)keystorePath) ) { + BinaryParameter bp = new BinaryParameter(); + bp.setValue(loadBinaryFile(keystorePath.toString())); + bp.setName(key); + bp.setUrl(keystorePath.toString()); + inputProps.put(key, bp); + + } else { + Logger.warn("eIDAS SAML-engine keyStore parameter has an unsuspected type. +" + + "(Type: " + keystorePath.toString() + ")"); + + } + } + } + + return outputProps; + } + + private boolean isBinaryParameter(String parameter) { + if (MiscUtil.isNotEmpty(parameter)) { + String absoluteConfigFile; + try { + absoluteConfigFile = FileUtils.makeAbsoluteURL( + parameter, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + File file = new File(new URL(absoluteConfigFile).toURI()); + return file.exists(); + + } catch (ConfigurationException | MalformedURLException | URISyntaxException e) { + Logger.warn("Binary eIDAS SAML-engine configuration parameter: " + + parameter + " is not loadable."); + + } + + } + + return false; + + } + + private byte[] loadBinaryFile(String fileName) throws EIDASEngineConfigurationException{ + InputStream is = null; + byte data[]=null; + try { + String absoluteConfigFile = FileUtils.makeAbsoluteURL( + fileName, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + + File file = new File(new URL(absoluteConfigFile).toURI()); + is = new FileInputStream(file); + data=new byte[is.available()]; + is.read(data); + + } catch (ConfigurationException | URISyntaxException | IOException e) { + throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); + + } finally { + if (is != null) + try { + is.close(); + + } catch (IOException e) { + Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); + + } + + } + + return data; + + } + + private Properties loadPropsFromXml(String configFile) throws EIDASEngineConfigurationException { + Properties props = new Properties(); + InputStream is = null; + try { + String absoluteConfigFile = FileUtils.makeAbsoluteURL( + configFile, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + + File file = new File(new URL(absoluteConfigFile).toURI()); + is = new FileInputStream(file); + props.loadFromXML(is); + + } catch (ConfigurationException | URISyntaxException | IOException e) { + throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); + + } finally { + if (is != null) + try { + is.close(); + + } catch (IOException e) { + Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); + + } + + } + + return props; + + } + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java new file mode 100644 index 000000000..dccd39905 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java @@ -0,0 +1,60 @@ +/* + * 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.config; + +import java.util.ArrayList; +import java.util.List; + +import eu.eidas.samlengineconfig.ConfigurationParameter; +import eu.eidas.samlengineconfig.InstanceConfiguration; +import eu.eidas.samlengineconfig.StringParameter; + +/** + * @author tlenz + * + */ +public class MOAeIDASSAMLInstanceConfigurationImpl extends + InstanceConfiguration { + + public void addParameter(ConfigurationParameter param) { + if (param != null) { + List<ConfigurationParameter> paramList = super.getParameters(); + if (paramList == null) { + paramList = new ArrayList<ConfigurationParameter>(); + super.setParameters(paramList); + + } + + paramList.add(param); + } + } + + public void addParameter(String key, String value) { + StringParameter param = new StringParameter(); + param.setName(key); + param.setValue(value); + addParameter(param); + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java new file mode 100644 index 000000000..7b044522c --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java @@ -0,0 +1,72 @@ +/* + * 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; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * @author tlenz + * + */ +public class eIDASAuthenticationModulImpl implements AuthModule { + + private int priority = 1; + + @Override + public int getPriority() { + return priority; + } + + /** + * Sets the priority of this module. Default value is {@code 0}. + * @param priority The priority. + */ + public void setPriority(int priority) { + this.priority = priority; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + if (StringUtils.isNotBlank((String) context.get("ccc")) || + StringUtils.isNotBlank((String) context.get("CCC"))) + return "eIDASAuthentication"; + else + return null; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml" }; + } + +} 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 new file mode 100644 index 000000000..49f0451cb --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java @@ -0,0 +1,95 @@ +/* + * 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; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringEscapeUtils; + +import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@WebServlet(urlPatterns = { "/eidas/sp/post", "/eidas/sp/redirect"}, loadOnStartup = 1) +public class eIDASSignalServlet extends ProcessEngineSignalServlet { + + private static final long serialVersionUID = 8215688005533754459L; + + public eIDASSignalServlet() { + super(); + Logger.debug("Registering servlet " + getClass().getName() + + " with mappings '/eidas/sp/post' and '/eidas/sp/redirect'."); + + } + + + @Override + /** + * Protocol specific implementation to get the sessionID + * from http request object + * + * @param request The http Servlet-Request object + * @return The SessionId + * + */ + public String getMoaSessionId(HttpServletRequest request) { + String sessionId = super.getMoaSessionId(request); + + 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/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java new file mode 100644 index 000000000..965abcde1 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -0,0 +1,370 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas.engine; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Timer; + +import javax.net.ssl.SSLHandshakeException; +import javax.xml.namespace.QName; + +import org.apache.commons.httpclient.MOAHttpClient; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider; +import org.opensaml.xml.XMLObject; + +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +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.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing; +import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector; +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.saml2.MetadataFilterChain; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.engine.AbstractSAMLEngine; + +public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvider, IGarbageCollectorProcessing { + + private static MOAeIDASChainingMetadataProvider instance = null; + private static Object mutex = new Object(); + + private MetadataProvider internalProvider; + private Map<String, Date> lastAccess = null; + + + public static MOAeIDASChainingMetadataProvider getInstance() { + if (instance == null) { + synchronized (mutex) { + if (instance == null) { + instance = new MOAeIDASChainingMetadataProvider(); + MOAGarbageCollector.addModulForGarbageCollection(instance); + } + } + } + return instance; + } + + + private MOAeIDASChainingMetadataProvider() { + internalProvider = new ChainingMetadataProvider(); + lastAccess = new HashMap<String, Date>(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector() + */ + @Override + public void runGarbageCollector() { + if (!lastAccess.isEmpty()) { + Date now = new Date(); + Date expioredate = new Date(now.getTime() - + Constants.CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT); + Logger.debug("Starting eIDAS Metadata garbag collection (Expioredate:" + + expioredate + ")"); + + List<String> expiredEntities = new ArrayList<String>(); + + Iterator<Entry<String, Date>> lastAccessInterator = lastAccess.entrySet().iterator(); + while(lastAccessInterator.hasNext()) { + Entry<String, Date> element = lastAccessInterator.next(); + if (element.getValue().before(expioredate)) { + Logger.debug("Remove unused eIDAS Metadate: " + element.getKey()); + expiredEntities.add(element.getKey()); + + } + } + + if (!expiredEntities.isEmpty()) { + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + + //get all actually loaded metadata providers + Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders(); + + for (String expired : expiredEntities) { + if (loadedproviders.containsKey(expired)) { + HTTPMetadataProvider provider = loadedproviders.get(expired); + + //destroy metadata provider + provider.destroy(); + + //remove from map + loadedproviders.remove(expired); + + /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) + *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ + //chainProvider.removeMetadataProvider(provider); + Logger.info("Remove not used eIDAS MetadataProvider " + expired + + " after timeout."); + + } else + Logger.warn("eIDAS metadata for EntityID: " + expired + + " is marked as unsed, but no loaded metadata provider is found."); + + } + + try { + synchronized (chainProvider) { + chainProvider.setProviders(new ArrayList<MetadataProvider>(loadedproviders.values())); + + emitChangeEvent(); + } + + } catch (MetadataProviderException e) { + Logger.warn("ReInitalize eIDASA MetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy", e); + + } + } + } + } + + + + private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL) { + HTTPMetadataProvider httpProvider = null; + Timer timer= null; + MOAHttpClient httpClient = null; + try { + AuthConfiguration authConfig = AuthConfigurationProviderFactory.getInstance(); + + httpClient = new MOAHttpClient(); + + HttpClientParams httpClientParams = new HttpClientParams(); + httpClientParams.setSoTimeout(Constants.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); + httpClient.setParams(httpClientParams); + + if (metadataURL.startsWith("https:")) { + try { + MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( + Constants.SSLSOCKETFACTORYNAME, + authConfig.getCertstoreDirectory(), + authConfig.getTrustedCACertificates(), + null, + AuthConfiguration.DEFAULT_X509_CHAININGMODE, + authConfig.isTrustmanagerrevoationchecking()); + + httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); + + } catch (MOAHttpProtocolSocketFactoryException e) { + Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore."); + + } + } + + timer = new Timer(); + httpProvider = new HTTPMetadataProvider(timer, httpClient, + metadataURL); + httpProvider.setParserPool(AbstractSAMLEngine.getNewBasicSecuredParserPool()); + httpProvider.setRequireValidMetadata(true); + httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes + httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours + //httpProvider.setRefreshDelayFactor(0.1F); + + //add Metadata filters + MetadataFilterChain filter = new MetadataFilterChain(); + filter.addFilter(new MOAeIDASMetadataSignatureFilter( + authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE))); + httpProvider.setMetadataFilter(filter); + + httpProvider.initialize(); + + return httpProvider; + + } catch (Throwable e) { + if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { + Logger.warn("SSL-Server certificate for metadata " + + 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( + "Failed to add Metadata file for " + + metadataURL + "[ " + + e.getMessage() + " ]", e); + + if (httpProvider != null) { + Logger.debug("Destroy failed Metadata provider"); + httpProvider.destroy(); + } + + if (timer != null) { + Logger.debug("Destroy Timer."); + timer.cancel(); + } + + + } + + return null; + } + + private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() { + Map<String, HTTPMetadataProvider> loadedproviders = new HashMap<String, HTTPMetadataProvider>(); + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + + //make a Map of all actually loaded HTTPMetadataProvider + List<MetadataProvider> providers = chainProvider.getProviders(); + for (MetadataProvider provider : providers) { + if (provider instanceof HTTPMetadataProvider) { + HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; + loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); + + } + } + + return loadedproviders; + } + + public boolean refreshMetadataProvider(String metadataURL) { + try { + if (MiscUtil.isNotEmpty(metadataURL)) { + Map<String, HTTPMetadataProvider> actuallyLoadedProviders = getAllActuallyLoadedProviders(); + + // check if MetadataProvider is actually loaded + if (actuallyLoadedProviders.containsKey(metadataURL)) { + actuallyLoadedProviders.get(metadataURL).refresh(); + Logger.info("eIDAS metadata for " + + metadataURL + " is refreshed."); + return true; + + } else { + //load new Metadata Provider + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + HTTPMetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL); + chainProvider.addMetadataProvider(newMetadataProvider); + + emitChangeEvent(); + Logger.info("eIDAS metadata for " + + metadataURL + " is added."); + return true; + + } + + } else + Logger.debug("Can not refresh eIDAS metadata: NO eIDAS metadata URL."); + + } catch (MetadataProviderException e) { + Logger.warn("Refresh eIDAS metadata for " + + metadataURL + " FAILED.", e); + + } + + return false; + + } + + + public boolean requireValidMetadata() { + return internalProvider.requireValidMetadata(); + } + + public void setRequireValidMetadata(boolean requireValidMetadata) { + internalProvider.setRequireValidMetadata(requireValidMetadata); + } + + public MetadataFilter getMetadataFilter() { + return internalProvider.getMetadataFilter(); + } + + public void setMetadataFilter(MetadataFilter newFilter) + throws MetadataProviderException { + internalProvider.setMetadataFilter(newFilter); + } + + public XMLObject getMetadata() throws MetadataProviderException { + return internalProvider.getMetadata(); + } + + public EntitiesDescriptor getEntitiesDescriptor(String entitiesID) + throws MetadataProviderException { + Logger.warn("eIDAS metadata not support 'EntitiesDescriptor' elements!"); + return null; + + } + + public EntityDescriptor getEntityDescriptor(String entityID) + throws MetadataProviderException { + EntityDescriptor entityDesc = null; + try { + entityDesc = internalProvider.getEntityDescriptor(entityID); + if (entityDesc == null) { + Logger.debug("Can not find eIDAS metadata for entityID: " + entityID + + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } else { + if (!entityDesc.isValid()) + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } + + + } catch (MetadataProviderException e) { + Logger.debug("Can not find eIDAS metadata for entityID: " + entityID + + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } + + if (entityDesc != null) + lastAccess.put(entityID, new Date()); + + return entityDesc; + } + + public List<RoleDescriptor> getRole(String entityID, QName roleName) + throws MetadataProviderException { + return internalProvider.getRole(entityID, roleName); + } + + public RoleDescriptor getRole(String entityID, QName roleName, + String supportedProtocol) throws MetadataProviderException { + return internalProvider.getRole(entityID, roleName, supportedProtocol); + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers() + */ + @Override + public List<Observer> getObservers() { + return ((ChainingMetadataProvider) internalProvider).getObservers(); + } + + protected void emitChangeEvent() { + if ((getObservers() == null) || (getObservers().size() == 0)) { + return; + } + + List<Observer> tempObserverList = new ArrayList<Observer>(getObservers()); + for (ObservableMetadataProvider.Observer observer : tempObserverList) + if (observer != null) + observer.onEvent(this); + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java new file mode 100644 index 000000000..e3ae5c046 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java @@ -0,0 +1,120 @@ +/* + * 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.engine; + +import java.security.KeyStore; + +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; + +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataProcessorI; +import eu.eidas.engine.exceptions.SAMLEngineException; + +/** + * @author tlenz + * + */ +public class MOAeIDASMetadataProviderDecorator implements MetadataProcessorI { + + private MetadataProvider metadataprovider = null; + + /** + * + */ + public MOAeIDASMetadataProviderDecorator(MetadataProvider metadataprovider) { + this.metadataprovider = metadataprovider; + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getEntityDescriptor(java.lang.String) + */ + @Override + public EntityDescriptor getEntityDescriptor(String url) + throws SAMLEngineException { + try { + return this.metadataprovider.getEntityDescriptor(url); + + } catch (MetadataProviderException e) { + throw new SAMLEngineException("eIDAS Metadata processing FAILED.", e); + + } + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getSPSSODescriptor(java.lang.String) + */ + @Override + public SPSSODescriptor getSPSSODescriptor(String url) + throws SAMLEngineException { + return getFirstRoleDescriptor(getEntityDescriptor(url), SPSSODescriptor.class); + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getIDPSSODescriptor(java.lang.String) + */ + @Override + public IDPSSODescriptor getIDPSSODescriptor(String url) + throws SAMLEngineException { + return getFirstRoleDescriptor(getEntityDescriptor(url), IDPSSODescriptor.class); + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, eu.eidas.auth.engine.EIDASSAMLEngine) + */ + @Override + public void checkValidMetadataSignature(String url, EIDASSAMLEngine engine) + throws SAMLEngineException { + //Do nothing, because metadata signature is already validated during + //metadata provider initialization + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, java.security.KeyStore) + */ + @Override + public void checkValidMetadataSignature(String url, KeyStore trustStore) + throws SAMLEngineException { + //Do nothing, because metadata signature is already validated during + //metadata provider initialization + + } + + protected <T extends RoleDescriptor> T getFirstRoleDescriptor(EntityDescriptor entityDescriptor, final Class<T> clazz){ + for(RoleDescriptor rd:entityDescriptor.getRoleDescriptors()){ + if(clazz.isInstance(rd)){ + return (T)rd; + } + } + return null; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java new file mode 100644 index 000000000..c9f3e5bcd --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java @@ -0,0 +1,132 @@ +/* + * 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.engine; + +import java.io.IOException; +import java.io.StringWriter; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.opensaml.saml2.metadata.EntityDescriptor; +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.auth.builder.SignatureVerificationUtils; +import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class MOAeIDASMetadataSignatureFilter implements MetadataFilter { + + private String trustProfileID = null; + + /** + * + */ + public MOAeIDASMetadataSignatureFilter(String trustProfileID) { + this.trustProfileID = trustProfileID; + + } + + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) + */ + @Override + public void doFilter(XMLObject metadata) throws FilterException { + if (metadata instanceof EntityDescriptor) { + if (((EntityDescriptor) metadata).isSigned()) { + EntityDescriptor entityDes = (EntityDescriptor) metadata; + //check signature; + try { + Transformer transformer = TransformerFactory.newInstance() + .newTransformer(); + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + DOMSource source = new DOMSource(metadata.getDOM()); + transformer.transform(source, sr); + sw.close(); + String metadataXML = sw.toString(); + + SignatureVerificationUtils sigVerify = + new SignatureVerificationUtils(); + VerifyXMLSignatureResponse result = sigVerify.verify( + metadataXML.getBytes(), trustProfileID); + + //check signature-verification result + if (result.getSignatureCheckCode() != 0) { + Logger.warn("eIDAS Metadata signature-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getSignatureCheckCode()); + throw new FilterException("eIDAS Metadata signature-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getSignatureCheckCode()); + + } + + if (result.getCertificateCheckCode() != 0) { + Logger.warn("eIDAS Metadata certificate-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getCertificateCheckCode()); + throw new FilterException("eIDAS Metadata certificate-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getCertificateCheckCode()); + + } + + + } catch (MOAIDException | TransformerFactoryConfigurationError | TransformerException | IOException e) { + Logger.error("eIDAS Metadata verification has an interal error.", e); + throw new FilterException("eIDAS Metadata verification has an interal error." + + " Message:" + e.getMessage()); + + } + + + } else { + Logger.warn("eIDAS Metadata root-element MUST be signed."); + throw new FilterException("eIDAS Metadata root-element MUST be signed.'"); + + } + + } else { + Logger.warn("eIDAS Metadata root-element is not of type 'EntityDescriptor'"); + throw new FilterException("eIDAS Metadata root-element is not of type 'EntityDescriptor'"); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java new file mode 100644 index 000000000..98bc559d2 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java @@ -0,0 +1,60 @@ +/* + * 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.exceptions; + +import at.gv.egovernment.moa.id.config.ConfigurationException; + +/** + * @author tlenz + * + */ +public class EIDASEngineConfigurationException extends ConfigurationException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param messageId + * @param parameters + * @param wrapped + */ + public EIDASEngineConfigurationException(String messageId, + Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + } + + /** + * @param string + * @param object + */ + public EIDASEngineConfigurationException(String string, Object[] object) { + super(string, object); + } + + + + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java new file mode 100644 index 000000000..95690bbeb --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java @@ -0,0 +1,45 @@ +/* + * 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.exceptions; + + +/** + * @author tlenz + * + */ +public class EIDASEngineException extends Exception { + + /** + * @param string + * @param e + */ + public EIDASEngineException(String string, Throwable e) { + super(string, e); + } + + /** + * + */ + private static final long serialVersionUID = 1559812927427153879L; + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java new file mode 100644 index 000000000..7840ae2e6 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java @@ -0,0 +1,38 @@ +/* + * 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.exceptions; + +/** + * @author tlenz + * + */ +public class eIDASAttributeException extends Exception { + + private static final long serialVersionUID = 1L; + + public eIDASAttributeException(String message) { + super(message); + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java new file mode 100644 index 000000000..f4d6c4ad4 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java @@ -0,0 +1,185 @@ +/* + * 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.tasks; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import eu.eidas.auth.commons.IPersonalAttributeList; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; +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.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.eIDASAttributeException; +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +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.id.util.IdentityLinkReSigner; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * @author tlenz + * + */ +public class CreateIdentityLinkTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + 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 eIDAS attributes from MOA-Session + IPersonalAttributeList eIDASAttributes = moasession.getGenericDataFromSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + IPersonalAttributeList.class); + + AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); + IdentityLink identityLink = null; + + //connect SZR-Gateway + //TODO: implement SZR-Gateway communication!!!! + if(true) { + + // create fake IdL + // - fetch IdL template from resources + InputStream s = CreateIdentityLinkTask.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(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)) + throw new eIDASAttributeException("PersonalIdentifier is missing"); + String eIdentifier = eIDASAttributes.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).getValue().get(0); + prIdentification.getFirstChild().setNodeValue(eIdentifier); + + // - set last name + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTFAMILYNAME)) + throw new eIDASAttributeException("currentFamilyName is missing"); + String familyName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME).getValue().get(0); + prFamilyName.getFirstChild().setNodeValue(familyName); + + // - set first name + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTGIVENNAME)) + throw new eIDASAttributeException("currentGivenName is missing"); + String givenName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME).getValue().get(0); + prGivenName.getFirstChild().setNodeValue(givenName); + + // - set date of birth + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_DATEOFBIRTH)) + throw new eIDASAttributeException("dateOfBirth is missing"); + String dateOfBirth = eIDASAttributes.get(Constants.eIDAS_ATTR_DATEOFBIRTH).getValue().get(0); + dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(dateOfBirth)); + 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"); + + //TODO:!!!!!! + + } + + Logger.debug("SZR communication was successfull"); + + if (identityLink == null) { + Logger.error("SZR Gateway did not return an identity link."); + throw new MOAIDException("stork.10", null); + } + + MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED); + moasession.setForeigner(true); + moasession.setIdentityLink(identityLink); + moasession.setBkuURL("Not applicable (eIDASAuthentication)"); + + //store MOA-session to database + AuthenticationSessionStoreage.storeSession(moasession); + + } catch (ParseException | MOAIDException | MOADatabaseException | ParserConfigurationException | SAXException | IOException e) { + throw new TaskExecutionException("IdentityLink generation for foreign person FAILED.", e); + + } catch (eIDASAttributeException e) { + throw new TaskExecutionException("Minimum required eIDAS attributeset not found.", e); + + } + + } + +} 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 new file mode 100644 index 000000000..06643ec53 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java @@ -0,0 +1,210 @@ +/* + * 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.tasks; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +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.AuthenticationException; +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.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.config.stork.CPEPS; +import at.gv.egovernment.moa.id.config.stork.StorkAttribute; +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.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.commons.EIDASAuthnRequest; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.EidasLoaCompareType; +import eu.eidas.auth.commons.EidasLoaLevels; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.PersonalAttributeList; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.core.eidas.SPType; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; + +/** + * @author tlenz + * + */ +public class GenerateAuthnRequestTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + + 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: '{}' Maybe, a transaction timeout occure.", new Object[] {pendingRequestID}); + throw new MOAIDException("auth.28", new Object[]{pendingRequestID}); + + } + + //load MOASession object, configuration and OA-configuration + AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid); + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + AuthConfiguration moaconfig = AuthConfigurationProviderFactory.getInstance(); + + // get target country + String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC); + + if (StringUtils.isEmpty(citizenCountryCode)) { + // illegal state; task should not have been executed without a selected country + throw new AuthenticationException("stork.22", new Object[] { moasessionid }); + } + + CPEPS cpeps = moaconfig.getStorkConfig().getCPEPS(citizenCountryCode); + if(null == cpeps) { + Logger.error("PEPS unknown for country", new Object[] {citizenCountryCode}); + throw new AuthenticationException("Unknown PEPS for citizen country '{}'", new Object[] {citizenCountryCode}); + } + Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode); + String destination = cpeps.getPepsURL().toString().split(";")[1].trim(); // FIXME convenience for metadata url and assertion destination + String metadataUrl = cpeps.getPepsURL().toString().split(";")[0].trim(); + + // assemble requested attributes + Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes(); + + // - prepare attribute list + IPersonalAttributeList pAttList = new PersonalAttributeList(); + + // - fill container + for (StorkAttribute current : attributesFromConfig) { + PersonalAttribute newAttribute = new PersonalAttribute(); + newAttribute.setName(current.getName()); + + boolean globallyMandatory = false; + for (StorkAttribute currentGlobalAttribute : moaconfig.getStorkConfig().getStorkAttributes()) + if (current.getName().equals(currentGlobalAttribute.getName())) { + globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory()); + break; + } + + newAttribute.setIsRequired(current.getMandatory() || globallyMandatory); + pAttList.add(newAttribute); + } + + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //build eIDAS AuthnRequest + EIDASAuthnRequest authnRequest = new EIDASAuthnRequest(); + authnRequest.setProviderName(pendingReq.getAuthURL()); + authnRequest.setPersonalAttributeList(pAttList); + + authnRequest.setIssuer(moaconfig.getPublicURLPrefix() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); + + authnRequest.setDestination(destination); + authnRequest.setEidasNameidFormat(EIDASAuthnRequest.NAMEID_FORMAT_UNSPECIFIED); + authnRequest.setEidasLoA(EidasLoaLevels.LOW.stringValue()); + authnRequest.setEidasLoACompareType(EidasLoaCompareType.MINIMUM.stringValue()); + authnRequest.setSPType(SPType.DEFAULT_VALUE); + + engine.initRequestedAttributes(pAttList); + authnRequest = engine.generateEIDASAuthnRequest(authnRequest); + + //encode AuthnRequest + byte[] token = authnRequest.getTokenSaml(); + String SAMLRequest = EIDASUtil.encodeSAMLToken(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", moasessionid); + + 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()); + + response.setContentType("text/html;charset=UTF-8"); + response.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8")); + + } catch (IOException e) { + Logger.error("Velocity IO error: " + e.getMessage()); + throw new MOAIDException("stork.15", null); // TODO + } catch (Exception e) { + Logger.error("Velocity general error: " + e.getMessage()); + throw new MOAIDException("stork.15", null); // TODO + } + + }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); + + } + + } + +} 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 new file mode 100644 index 000000000..693807d63 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java @@ -0,0 +1,109 @@ +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.data.AuthenticationSessionStorageConstants; +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.MOAPersonalAttributeList; +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.AuthConfigurationProviderFactory; +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 { + + 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 + + } + + //MOA-ID specific response validation + //TODO: implement MOA-ID specific response validation + + //update MOA-Session data with received information + Logger.debug("Store eIDAS response information into MOA-session."); + moasession.setQAALevel(samlResp.getAssuranceLevel()); + moasession.setCcc(samlResp.getCountry()); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + new MOAPersonalAttributeList(samlResp.getPersonalAttributeList())); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_RESPONSE, + decSamlToken); + + //set general information to MOA-Session + moasession.setAuthURL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/"); + + //store MOA-session to database + AuthenticationSessionStoreage.storeSession(moasession); + + }catch (EIDASSAMLEngineException e) { + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException("eIDAS Response processing FAILED.", + new EIDASEngineException("Could not validate eIDAS response", e)); + + } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException("eIDAS Response processing FAILED.", e); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java new file mode 100644 index 000000000..573163af0 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java @@ -0,0 +1,66 @@ +/* + * 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.Iterator; +import java.util.NoSuchElementException; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.PersonalAttributeList; + + +/** + * @author tlenz + * + */ +public class MOAOrderedAttributeIterator implements Iterator<PersonalAttribute> { + + private MOAPersonalAttributeList pal; + private Iterator<String> keyIterator; + + public MOAOrderedAttributeIterator(MOAPersonalAttributeList palArg) { + this.pal = palArg; + keyIterator = palArg.getInsertOrder().iterator(); + } + + @Override + public boolean hasNext() { + return keyIterator.hasNext(); + } + + @Override + public PersonalAttribute next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return pal.get(keyIterator.next()); + } + + @Override + public void remove() { + Logger.error("Not implemented"); + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java new file mode 100644 index 000000000..5cc100b70 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java @@ -0,0 +1,343 @@ +/* + * 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.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.lang.StringUtils; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.auth.commons.AttributeConstants; +import eu.eidas.auth.commons.AttributeUtil; +import eu.eidas.auth.commons.EIDASErrors; +import eu.eidas.auth.commons.EIDASParameters; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.EIDASValues; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.exceptions.InternalErrorEIDASException; + +/** + * @author tlenz + * + */ +public final class MOAPersonalAttributeList extends + ConcurrentHashMap<String, PersonalAttribute> implements IPersonalAttributeList { + + /** + * + */ + private static final long serialVersionUID = -4488124133022713089L; + + public MOAPersonalAttributeList(IPersonalAttributeList eIDASAttributeList) { + super(); + Iterator<PersonalAttribute> element = eIDASAttributeList.iterator(); + while(element.hasNext()) + add(element.next()); + + } + + /** + * Hash with the latest fetched attribute name alias. + */ + private Map<String, Integer> latestAttrAlias = + new HashMap<String, Integer>(); + + /** + * Hash with mapping number of alias or the attribute name. + */ + private Map<String, Integer> attrAliasNumber = + new HashMap<String, Integer>(); + private List<String> insertOrder = new ArrayList<String>(); + + /** + * Obtain the insertOrder Collection + * + * @return defensive copy of the collection + */ + List<String> getInsertOrder() { + return Collections.unmodifiableList(this.insertOrder); + } + + /** + * Default constructor. + */ + public MOAPersonalAttributeList() { + super(); + + } + + /** + * Constructor with initial capacity for the PersonalAttributeList size. + * + * @param capacity The initial capacity for the PersonalAttributeList. + */ + public MOAPersonalAttributeList(final int capacity) { + super(capacity); + } + + /** + * {@inheritDoc} + */ + public Iterator<PersonalAttribute> iterator() { + return new MOAOrderedAttributeIterator(this); + } + + /** + * {@inheritDoc} + */ + public PersonalAttribute get(final Object key) { + String attrName = (String) key; + + if (this.latestAttrAlias == null) + this.latestAttrAlias = new HashMap<String, Integer>(); + + if (this.attrAliasNumber == null) + this.attrAliasNumber = new HashMap<String, Integer>(); + + if (this.latestAttrAlias.containsKey(key)) { + attrName = attrName + this.latestAttrAlias.get(key); + } else { + if (this.attrAliasNumber.containsKey(key)) { + this.latestAttrAlias.put(attrName, this.attrAliasNumber.get(key)); + } + } + return super.get(attrName); + } + + /** + * {@inheritDoc} + */ + public void add(final PersonalAttribute value) { + if (value != null) { + this.put(value.getName(), value); + } + } + + /** + * {@inheritDoc} + */ + public PersonalAttribute put(final String key, final PersonalAttribute val) { + if (StringUtils.isNotEmpty(key) && val != null) { + // Validate if attribute name already exists! + String attrAlias = key; + if (this.containsKey(attrAlias)) { + if (this.attrAliasNumber == null) + this.attrAliasNumber = new HashMap<String, Integer>(); + if (!val.isEmptyValue() && StringUtils.isNumeric(val.getValue().get(0))) { + final String attrValue = val.getValue().get(0); + attrAlias = key + attrValue; + this.attrAliasNumber.put(key, Integer.valueOf(attrValue)); + } else { + final PersonalAttribute attr = super.get(key); + if (!attr.isEmptyValue() + && StringUtils.isNumeric(attr.getValue().get(0))) { + attrAlias = key + attr.getValue().get(0); + super.put(key, (PersonalAttribute) attr); + this.attrAliasNumber.put(key, null); + } + } + } else { + if (insertOrder == null) + insertOrder = new ArrayList<String>(); + + insertOrder.add(key); + } + return super.put(attrAlias, val); + } else { + return null; + } + } + + @Override + public PersonalAttribute remove(Object key) { + insertOrder.remove(key); + return super.remove(key); + } + + /** + * {@inheritDoc} + */ + public void populate(final String attrList) { + final StringTokenizer strToken = + new StringTokenizer(attrList, EIDASValues.ATTRIBUTE_SEP.toString()); + + while (strToken.hasMoreTokens()) { + final PersonalAttribute persAttr = new PersonalAttribute(); + String[] tuples = + strToken.nextToken().split(EIDASValues.ATTRIBUTE_TUPLE_SEP.toString(), + AttributeConstants.NUMBER_TUPLES.intValue()); + + // Convert to the new format if needed! + tuples = convertFormat(tuples); + + if (AttributeUtil.hasValidTuples(tuples)) { + final int attrValueIndex = + AttributeConstants.ATTR_VALUE_INDEX.intValue(); + final String tmpAttrValue = + tuples[attrValueIndex].substring(1, + tuples[attrValueIndex].length() - 1); + final String[] vals = + tmpAttrValue.split(EIDASValues.ATTRIBUTE_VALUE_SEP.toString()); + + persAttr.setName(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]); + persAttr.setIsRequired(Boolean + .valueOf(tuples[AttributeConstants.ATTR_TYPE_INDEX.intValue()])); + // check if it is a complex value + if (tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()] + .equals(EIDASParameters.COMPLEX_ADDRESS_VALUE.toString())) { + persAttr.setComplexValue(createComplexValue(vals)); + } else { + persAttr.setValue(createValues(vals)); + } + + if (tuples.length == AttributeConstants.NUMBER_TUPLES.intValue()) { + persAttr.setStatus(tuples[AttributeConstants.ATTR_STATUS_INDEX + .intValue()]); + } + this.put(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()], + persAttr); + + } else { + Logger.info("BUSINESS EXCEPTION : Invalid personal attribute list tuples"); + } + + } + } + + /** + * Returns a copy of this <tt>IPersonalAttributeList</tt> instance. + * + * @return The copy of this IPersonalAttributeList. + */ + public Object clone() { + try { + MOAPersonalAttributeList theClone= (MOAPersonalAttributeList)super.clone(); + theClone.insertOrder=new ArrayList<String>(insertOrder); + return theClone; + + } catch (CloneNotSupportedException e) { + throw new InternalErrorEIDASException( + EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorCode()), + EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorMessage()), e); + } + } + + /** + * Creates a string in the following format. + * + * attrName:attrType:[attrValue1,attrValue2=attrComplexValue]:attrStatus; + * + * @return {@inheritDoc} + */ + @Override + public String toString() { + final StringBuilder strBuilder = new StringBuilder(); + final Iterator<String> iteratorInsertOrder = insertOrder.iterator(); + while (iteratorInsertOrder.hasNext()) { + String key = iteratorInsertOrder.next(); + final PersonalAttribute attr = get(key); + strBuilder.append(attr.toString()); + if (isNumberAlias(key)) { + strBuilder.append(get(key).toString()); + } + } + return strBuilder.toString(); + } + + /** + * Validates and creates the attribute's complex values. + * + * @param values The complex values. + * @return The {@link Map} with the complex values. + * @see Map + */ + private Map<String, String> createComplexValue(final String[] values) { + final Map<String, String> complexValue = new HashMap<String, String>(); + for (final String val : values) { + final String[] tVal = val.split("="); + if (StringUtils.isNotEmpty(val) && tVal.length == 2) { + complexValue.put(tVal[0], AttributeUtil.unescape(tVal[1])); + } + } + return complexValue; + } + + /** + * Validates and creates the attribute values. + * + * @param vals The attribute values. + * @return The {@link List} with the attribute values. + * @see List + */ + private List<String> createValues(final String[] vals) { + final List<String> values = new ArrayList<String>(); + for (final String val : vals) { + if (StringUtils.isNotEmpty(val)) { + values.add(AttributeUtil.unescape(val)); + } + } + return values; + } + + ////////////////// + /** + * Converts the attribute tuple (attrName:attrType...) to the new format. + * + * @param tuples The attribute tuples to convert. + * @return The attribute tuples in the new format. + */ + private String[] convertFormat(final String[] tuples) { + final String[] newFormatTuples = + new String[AttributeConstants.NUMBER_TUPLES.intValue()]; + if (tuples != null) { + System.arraycopy(tuples, 0, newFormatTuples, 0, tuples.length); + + for (int i = tuples.length; i < newFormatTuples.length; i++) { + if (i == AttributeConstants.ATTR_VALUE_INDEX.intValue()) { + newFormatTuples[i] = "[]"; + } else { + newFormatTuples[i] = ""; + } + } + } + return newFormatTuples; + } + + public boolean isNumberAlias(String key) { + return this.attrAliasNumber.containsKey(key); + } + + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java new file mode 100644 index 000000000..8e46f0ef1 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -0,0 +1,71 @@ +/* + * 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 at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; +import eu.eidas.samlengineconfig.CertificateConfigurationManager; + +/** + * @author tlenz + * + */ +public class SAMLEngineUtils { + + private static EIDASSAMLEngine eIDASEngine = null; + + public static synchronized EIDASSAMLEngine createSAMLEngine() throws EIDASEngineException{ + + if (eIDASEngine == null) { + try { + //get eIDAS SAMLengine configuration from MOA-ID configuration + CertificateConfigurationManager configManager = new MOAIDCertificateManagerConfigurationImpl(); + + //initial eIDAS SAMLengine + EIDASSAMLEngine engine = EIDASSAMLEngine.createSAMLEngine(Constants.eIDAS_SAML_ENGINE_NAME, + configManager); + + //set Metadata managment to eIDAS SAMLengine + engine.setMetadataProcessor( + new MOAeIDASMetadataProviderDecorator( + MOAeIDASChainingMetadataProvider.getInstance())); + + eIDASEngine = engine; + + } catch (EIDASSAMLEngineException e) { + Logger.error("eIDAS SAMLengine initialization FAILED!", e); + throw new EIDASEngineException("eIDAS SAMLengine initialization FAILED!", e); + + } + } + + return eIDASEngine; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java new file mode 100644 index 000000000..c8f6bba9c --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * 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.eidas; + +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Map.Entry; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.commons.EIDASAuthnResponse; +import eu.eidas.auth.commons.EIDASStatusCode; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataUtil; + + +/** + * Second request step - after authentication of the user is done and moasession obtained, + * process request and forward the user further to PEPS and/or other entities + * + * @author bsuzic + */ + +public class AuthenticationRequest implements IAction { + + @Override + public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { + EIDASData eidasRequest; + if(req instanceof EIDASData) + eidasRequest = (EIDASData) req; + else + throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()}); + + + // gather attributes + MOAPersonalAttributeList resultingAttributeList = (MOAPersonalAttributeList) eidasRequest.getEidasRequestedAttributes().clone(); + + for(Entry<String, PersonalAttribute> current : resultingAttributeList.entrySet()) { + String newValue = ""; + + // TODO make use of proper builder + switch(current.getKey()) { + case Constants.eIDAS_ATTR_DATEOFBIRTH: newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); break; + case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: newValue = authData.getFamilyName();break; + case Constants.eIDAS_ATTR_CURRENTGIVENNAME: newValue = authData.getGivenName();break; + case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: newValue = new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), + eidasRequest.getTarget()); break; + } + + if("".equals(newValue)) + current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString()); + else { + current.getValue().getValue().clear(); + current.getValue().getValue().add(newValue); + current.getValue().setStatus(EIDASStatusCode.STATUS_AVAILABLE.toString()); + } + } + + // construct eIDaS response + EIDASAuthnResponse response = new EIDASAuthnResponse(); + response.setPersonalAttributeList(resultingAttributeList); + + // - create metadata url + AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); + String pubURLPrefix = req.getAuthURL(); + String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA; + response.setIssuer(metadata_url); + + response.setAssuranceLevel(authData.getEIDASQAALevel()); + + String token = null; + try { + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + // check if we have the destination available, supply it if not + if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { + String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( + new MOAeIDASMetadataProviderDecorator(MOAeIDASChainingMetadataProvider.getInstance()), + engine, + eidasRequest.getEidasRequest()); + eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl); + } + + response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true); + + + token = EIDASUtil.encodeSAMLToken(response.getTokenSaml()); + } catch(Exception e) { + e.printStackTrace(); + } + + // send the response + try { + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html"); + VelocityContext context = new VelocityContext(); + + context.put("SAMLResponse", token); + Logger.debug("SAMLResponse original: " + token); + + Logger.debug("Putting assertion consumer url as action: " + eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()); + context.put("action", eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()); + Logger.trace("Starting template merge"); + StringWriter writer = new StringWriter(); + + Logger.trace("Doing template merge"); + template.merge(context, writer); + Logger.trace("Template merge done"); + + Logger.trace("Sending html content: " + writer.getBuffer().toString()); + Logger.trace("Sending html content2 : " + new String(writer.getBuffer())); + + httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8")); + + } catch (Exception e) { + Logger.error("Velocity error: " + e.getMessage()); + } + + return null; + } + + @Override + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { + return true; + } + + @Override + public String getDefaultActionName() { + // TODO Auto-generated method stub + return null; + } + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java new file mode 100644 index 000000000..374c3df30 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java @@ -0,0 +1,96 @@ +package at.gv.egovernment.moa.id.protocols.eidas; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.opensaml.saml2.core.Attribute; + +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import eu.eidas.auth.commons.EIDASAuthnRequest; + +public class EIDASData extends RequestImpl { + + /** + * @param req + * @throws ConfigurationException + */ + public EIDASData(HttpServletRequest req) throws ConfigurationException { + super(req); + + } + + /** The Constant serialVersionUID. */ + private static final long serialVersionUID = 8765755670214923910L; + + /** The attributes requested by the eIDaS. */ + private MOAPersonalAttributeList attributes; + + /** The incoming eIDaS SAML2 AuthnRequest. */ + private EIDASAuthnRequest authnRequest; + + /** The ip address of the requester. */ + private String remoteIPAddress; + + @Override + public List<Attribute> getRequestedAttributes() { + // TODO Auto-generated method stub + return null; + } + + /** + * Gets the eidas requested attributes. + * + * @return the requested attributes + */ + public MOAPersonalAttributeList getEidasRequestedAttributes() { + return (MOAPersonalAttributeList) attributes.clone(); + } + + /** + * Sets the eidas requested attributes. + * + * @param personalAttributeList the requested attributes + */ + public void setEidasRequestedAttributes(MOAPersonalAttributeList personalAttributeList) { + attributes = personalAttributeList; + } + + /** + * Gets the eidas request. + * + * @return the eidas request + */ + public EIDASAuthnRequest getEidasRequest() { + return authnRequest; + } + + /** + * Sets the eidas request. + * + * @param request the new eidas request + */ + public void setEidasRequest(EIDASAuthnRequest request) { + authnRequest = request; + } + + /** + * Gets the remote address. + * + * @return the remote address + */ + public String getRemoteAddress() { + return remoteIPAddress; + } + + /** + * Sets the remote address. + * + * @param remoteIP the new remote address + */ + public void setRemoteAddress(String remoteIP) { + remoteIPAddress = remoteIP; + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java new file mode 100644 index 000000000..b652503f8 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * 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.eidas; + +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IModulInfo; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.EIDASAuthnRequest; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.engine.EIDASSAMLEngine; + +/** + * Stork 2 Protocol Support + * + * @author bsuzic + */ +public class EIDASProtocol extends MOAIDAuthConstants implements IModulInfo { + + public static final String NAME = EIDASProtocol.class.getName(); + public static final String PATH = "eidas"; + + public static final String AUTHENTICATIONREQUEST = "AuthenticationRequest"; + public static final String METADATAREQUEST = "MetadataRequest"; + + private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); + + static { + actions.put(AUTHENTICATIONREQUEST, new AuthenticationRequest()); + actions.put(METADATAREQUEST, new EidasMetaDataRequest()); + + } + + public String getName() { + return NAME; + } + + public String getPath() { + return PATH; + } + + public IAction getAction(String action) { + return actions.get(action); + } + + public EIDASProtocol() { + super(); + } + + /* + First request step - send it to BKU selection for user authentication. After the user credentials + and other info are obtained, in the second step the request will be processed and the user redirected + */ + public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action, + String sessionId, String transactionId) throws MOAIDException { + + Logger.info("received an eIDaS request"); + + //get SAML Response and decode it + String base64SamlToken = request.getParameter("SAMLRequest"); + if (MiscUtil.isEmpty(base64SamlToken)) { + Logger.warn("No eIDAS SAMLRequest found in http request."); + throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null); + } + byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken); + + try { + //get eIDAS SAML-engine + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //validate SAML token + EIDASAuthnRequest samlReq = engine.validateEIDASAuthnRequest(decSamlToken); + + // memorize important stuff + EIDASData result = new EIDASData(request); + + // - memorize remote ip + result.setRemoteAddress(request.getRemoteAddr()); + + // - memorize country code of target country + result.setTarget(samlReq.getCountry()); + + // - memorize requested attributes + result.setEidasRequestedAttributes(new MOAPersonalAttributeList(samlReq.getPersonalAttributeList())); + + // - memorize whole request + samlReq.setPersonalAttributeList(result.getEidasRequestedAttributes()); // circumvent non-serializable eidas personal attribute list + result.setEidasRequest(samlReq); + + // - memorize OA url + result.setOAURL(samlReq.getIssuer()); + + // - memorize OA config + OAAuthParameter oaConfig = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(result.getOAURL()); + if (oaConfig == null) + throw new AuthenticationException("stork.12", new Object[]{result.getOAURL()}); + result.setOnlineApplicationConfiguration(oaConfig); + + return result; + } catch(Exception e) { + Logger.error("error in preprocessing step", e); + throw new MOAIDException("error in preprocessing step", null); + } + } + + public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) { + return null; + } + + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable { + return false; + } + + public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { + return false; + } +} + + diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java new file mode 100644 index 000000000..0be291a06 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright 2015 e-SENS project + * + * 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://ec.europa.eu/idabc/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. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.eidas; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +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.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataConfigParams; +import eu.eidas.auth.engine.metadata.MetadataGenerator; +import eu.eidas.engine.exceptions.SAMLEngineException; + + +/** + * First version to provide some valid metadata to an asking eIDaS node + */ +//@WebServlet("/eidas/metadata") +public class EidasMetaDataRequest implements IAction { + private static final long serialVersionUID = -2129228304760706063L; + private Logger logger = org.slf4j.LoggerFactory.getLogger(EidasMetaDataRequest.class); + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) + */ + @Override + public SLOInformationInterface processRequest(IRequest req, + HttpServletRequest httpReq, HttpServletResponse httpResp, + IAuthData authData) throws MOAIDException { + + try { + logger.debug("EidasMetaDataServlet GET"); + + String pubURLPrefix = req.getAuthURL(); + + String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA; + + String sp_return_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_SP_POST; + String metaData = generateMetadata(metadata_url, sp_return_url); + + logger.trace(metaData); + + httpResp.setContentType("text/xml"); + httpResp.getWriter().print(metaData); + httpResp.flushBuffer(); + + } catch (Exception e) { + e.printStackTrace(); + } + + + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, + HttpServletResponse httpResp) { + return false; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + @Override + public String getDefaultActionName() { + return "eIDAS-Metadata Action"; + + } + + public String generateMetadata(String metadata_url, String sp_return_url) throws SAMLEngineException, EIDASEngineException{ + String metadata="invalid metadata"; + + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + MetadataGenerator generator = new MetadataGenerator(); + MetadataConfigParams mcp=new MetadataConfigParams(); + generator.setConfigParams(mcp); + generator.initialize(engine); + mcp.setEntityID(metadata_url); + + generator.addSPRole(); + String returnUrl = sp_return_url; + mcp.setAssertionConsumerUrl(returnUrl); + + generator.addIDPRole(); + mcp.setAssuranceLevel("http://eidas.europa.eu/LoA/substantial"); // TODO make configurable + + metadata = generator.generateMetadata(); + return metadata; + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo new file mode 100644 index 000000000..31d15951c --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo @@ -0,0 +1 @@ +at.gv.egovernment.moa.id.protocols.eidas.EIDASProtocol
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml new file mode 100644 index 000000000..f24ff1c28 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition id="eIDASAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"> + + + <pd:Task id="createAuthnRequest" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.GenerateAuthnRequestTask" /> + <pd:Task id="receiveAuthnResponse" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.ReceiveAuthnResponseTask" async="true" /> + <pd:Task id="finalizeAuthentication" class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.FinalizeAuthenticationTask" /> + <pd:Task id="generateIdentityLink" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.CreateIdentityLinkTask" /> + + <pd:StartEvent id="start" /> + <pd:Transition from="start" to="createAuthnRequest" /> + <pd:Transition from="createAuthnRequest" to="receiveAuthnResponse" /> + <pd:Transition from="receiveAuthnResponse" to="generateIdentityLink" /> + <pd:Transition from="generateIdentityLink" to="finalizeAuthentication" /> + <pd:Transition from="finalizeAuthentication" to="end" /> + <pd:EndEvent id="end" /> + +</pd:ProcessDefinition> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml new file mode 100644 index 000000000..0e1b60fe7 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:annotation-config /> + + <bean id="eIDASAuthModule" class="at.gv.egovernment.moa.id.auth.modules.eidas.eIDASAuthenticationModulImpl"> + <property name="priority" value="1" /> + </bean> + +</beans> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm new file mode 100644 index 000000000..8beb601c6 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm @@ -0,0 +1,38 @@ +## +## Velocity Template for SAML 2 HTTP-POST binding +## +## Velocity context may contain the following properties +## action - String - the action URL for the form +## RelayState - String - the relay state for the message +## SAMLRequest - String - the Base64 encoded SAML Request +## SAMLResponse - String - the Base64 encoded SAML Response +## Contains target attribute to delegate PEPS authentication out of iFrame + +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + + <body onload="document.forms[0].submit()"> + <noscript> + <p> + <strong>Note:</strong> Since your browser does not support JavaScript, + you must press the Continue button once to proceed. + </p> + </noscript> + + <form action="${action}" method="post" target="_top"> + <div> + #if($RelayState)<input type="hidden" name="RelayState" value="${RelayState}"/>#end + + #if($SAMLRequest)<input type="hidden" name="SAMLRequest" value="${SAMLRequest}"/>#end + + #if($SAMLResponse)<input type="hidden" name="SAMLResponse" value="${SAMLResponse}"/>#end + + </div> + <noscript> + <div> + <input type="submit" value="Continue"/> + </div> + </noscript> + </form> + + </body> +</html>
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml new file mode 100644 index 000000000..09084a34f --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID13456264458587874" IssueInstant="2012-08-22T11:07:25+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> + <saml:AttributeStatement> + <saml:Subject> + <saml:SubjectConfirmation> + <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> + <saml:SubjectConfirmationData> + <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>wJO/bvDJjUysG0yARn7I6w==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>XXXRúùd</pr:GivenName><pr:FamilyName primary="undefined">XXXVàn Nisteĺrooy</pr:FamilyName></pr:Name><pr:DateOfBirth>1969-02-13</pr:DateOfBirth></pr:Person> + </saml:SubjectConfirmationData> + </saml:SubjectConfirmation> + </saml:Subject> + <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="22280299907126338788314199678167217078072953115254374209747379168424021905237" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="40387096985250872237992703378062984723606079359080588656963239072881568409170" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><dsig:RSAKeyValue><dsig:Modulus>4Y4FL09VhczsfYQgFPuycP8quJNZBAAu1R1rFXNodI2711B6BTMjAGQn6xuFWfd3/nyFav/MLTr/ +t2VazvANS4TRFxJAcWyIx7xbxCdzZr6gJ+FCmq4g5JPrQvt50v3JX+wKSYft1gHBOWlDn90Ia4Gm +P8MVuze21T+VVKM6ZklmS6d5PT1er/uYQFydGErmJ17xlSQG6Fi5xuftopBDyJxG1tL1KIebpLFg +gaM2EyuB1HxH8/+Mfqa4UgeqIH65</dsig:Modulus><dsig:Exponent>AQAB</dsig:Exponent></dsig:RSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement> + <dsig:Signature> + <dsig:SignedInfo> + <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> + <dsig:Reference URI=""> + <dsig:Transforms> + <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> + <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> + </dsig:Transform> + <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + </dsig:Transforms> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>KEQEPY2O3Z3IRaISSSoRZVPzsHE=</dsig:DigestValue> + </dsig:Reference> + <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>gzGhjH1kdmPcPbgen0xojNIoJLk=</dsig:DigestValue> + </dsig:Reference> + </dsig:SignedInfo> + <dsig:SignatureValue> + 06wqWHgplwpu3N5HMhzb6QC5NkXMO1z4N4oc1L6eDqwZlvFJ9X1XGW//QqviKO9oog3il7IzdfJwnjygR4trgGCIqx+JYCDHJCrG9l8zlxlSW0ZqfsygGXthutcQ1aeUpfO6jYuhnWOUywa8BgzukRtWT+AOJBQZPRYTb8IBmey+uAwlhFLni94eMOd81l+efCvkWi3jRajwsG8ZOaNxSZT3aEV5vj+32Aqtx2MPEVzQWtIA7GqZi+EzcdSdHQvHhg7UB+8kqbU70ENAJbEMTANFZYvLOJ0Om9KfDtPf/+R2TvTc360fNo9RnPl04pHPhCIjcGZhFZorBpUhXFwd2Q== + </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIF3TCCBMWgAwIBAgIDByniMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMB4XDTEwMDcyODExMzY0M1oXDTE1MDcyODExMzY0M1owgbYxCzAJBgNVBAYTAkFUMR4wHAYDVQQKDBVEYXRlbnNjaHV0emtvbW1pc3Npb24xIjAgBgNVBAsMGVN0YW1temFobHJlZ2lzdGVyYmVob2VyZGUxLjAsBgNVBAMMJVNpZ25hdHVyc2VydmljZSBEYXRlbnNjaHV0emtvbW1pc3Npb24xFTATBgNVBAUTDDMyNTkyODMyMzk5ODEcMBoGCSqGSIb3DQEJARYNZHNrQGRzay5ndi5hdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+dBSEBGj2jUXIK1Mp3lVxc/Za+pJMiyKrX3G1ZxgX/ikx7D9scsPYMt473LlAWl9cmCbHbJK+PV2XNNdURLMUCIX+4vUNs2MHeDTQtX8BXjJFpwJYSoaRJQ39FVS/1r5sWcra9Hhdm7w5Gtx/2ukyDX0kdkxawkhP4EQEzi/SI+Fugn+WqgQ1nAdlbxb/dcBw5w1h9b3lmuwUf4z3ooQWUD2DgA/kKd1KejNR43mLUsmvSzevPxT9zs78pOR1OacB7IszTVJPXeOEaaNZHnnB/UeO3g8LEV/3OkXcUgcMkbIIiaBHlll71Pq0COj9kqjXoe7OrRjLY5i3KwOpa6TMCAwEAAaOCAgcwggIDMBMGA1UdIwQMMAqACEkcWDpP6A0DMH8GCCsGAQUFBwEBBHMwcTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMEYGCCsGAQUFBzAChjpodHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMmEuY3J0MFQGA1UdIARNMEswSQYGKigAEQESMD8wPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cuYS10cnVzdC5hdC9kb2NzL2NwL2Etc2lnbi1BbXRzc2lnbmF0dXIwgZ4GA1UdHwSBljCBkzCBkKCBjaCBioaBh2xkYXA6Ly9sZGFwLmEtdHJ1c3QuYXQvb3U9YS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQITAgOnhr0tbowDgYDVR0PAQH/BAQDAgSwMCAGA1UdEQQZMBeBFW1hcmN1cy5oaWxkQGRzay5ndi5hdDAJBgNVHRMEAjAAMA4GByooAAoBBwEEAwEB/zAUBgcqKAAKAQEBBAkMB0JTQi1EU0swDQYJKoZIhvcNAQEFBQADggEBAHTklnvPCH/bJSOlIPbLUEkSGuFHsektSZ8Vr22x/Yv7EzsxoQrJIiz2mQ2gQqFuExdWYxvsowjiSbiis9iUf1c0zscvDS3mIZxGs4M89XHsjHnIyb+Fuwnamw65QrFvM1tNB1ZMjxJ3x+YmHLHdtT3BEBcr3/NCRHd2S0HoBspNz9HVgJaZY1llR7poKBvnAc4g1i+QTvyVb00PtKxR9Lw/9ABInX/1pzpxqrPy7Ib2OP8z6dd3WHmIsCiSHUaj0Dxwwln6fYJjhxZ141SnbovlCLYtrsZLXoi9ljIqX4xO0PwMI2RfNc9cXxTRrRS6rEOvX7PpvgXiDXhp592Yyp4=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo> + <dsig:Object> + <dsig:Manifest Id="manifest"> + <dsig:Reference URI=""> + <dsig:Transforms> + <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> + <dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> + </dsig:Transform> + </dsig:Transforms> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>8e7RjLnA4Mgltq5ruIJzheKGxu0=</dsig:DigestValue> + </dsig:Reference> + </dsig:Manifest> + </dsig:Object> + </dsig:Signature> +</saml:Assertion>
\ No newline at end of file diff --git a/id/server/modules/moa-id-modules-saml1/pom.xml b/id/server/modules/moa-id-modules-saml1/pom.xml index 9c43ae277..b5d5a1f8f 100644 --- a/id/server/modules/moa-id-modules-saml1/pom.xml +++ b/id/server/modules/moa-id-modules-saml1/pom.xml @@ -24,7 +24,19 @@ <artifactId>moa-id-lib</artifactId> <scope>test</scope> <type>test-jar</type> - <version>3.0.3-Snapshot</version> + <version>${moa-id-version}</version> + </dependency> + + <dependency> + <groupId>MOA.id.server</groupId> + <artifactId>moa-id-lib</artifactId> + </dependency> + + <!-- Only for development to use SAML1 protocol + SAML1 is removed from official OPB release --> + <dependency> + <groupId>MOA.id.server.modules</groupId> + <artifactId>moa-id-module-eIDAS</artifactId> </dependency> <dependency> diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java index d4e73690f..7f3c353f1 100644 --- a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; @@ -40,6 +41,7 @@ import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.URLEncoder; +import eu.eidas.auth.commons.IPersonalAttributeList; public class GetArtifactAction implements IAction { @@ -71,8 +73,11 @@ public class GetArtifactAction implements IAction { SAML1AuthenticationServer saml1server = SAML1AuthenticationServer.getInstace(); // add other stork attributes to MOA assertion if available - if(null != authData.getStorkAttributes()) { - List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = SAML1AuthenticationServer.addAdditionalSTORKAttributes(authData.getStorkAttributes()); + IPersonalAttributeList storkAttributes = authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); + if(null != storkAttributes) { + List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = SAML1AuthenticationServer.addAdditionalSTORKAttributes(storkAttributes); authData.getExtendedSAMLAttributesOA().addAll(moaExtendedSAMLAttibutes); Logger.info("MOA assertion assembled and SAML Artifact generated."); } diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java index eb869756e..af5dada54 100644 --- a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java @@ -38,9 +38,6 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import eu.stork.peps.auth.commons.IPersonalAttributeList; -import eu.stork.peps.auth.commons.PersonalAttribute; - import at.gv.egovernment.moa.id.auth.AuthenticationServer; import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder; import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; @@ -64,7 +61,6 @@ import at.gv.egovernment.moa.id.config.auth.data.SAML1ConfigurationParameters; import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.storage.AssertionStorage; -//import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; @@ -77,6 +73,11 @@ import at.gv.util.xsd.persondata.IdentificationType.Value; import at.gv.util.xsd.persondata.PersonNameType; import at.gv.util.xsd.persondata.PersonNameType.FamilyName; import at.gv.util.xsd.persondata.PhysicalPersonType; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +//import eu.stork.peps.auth.commons.IPersonalAttributeList; +//import eu.stork.peps.auth.commons.PersonalAttribute; +//import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; public class SAML1AuthenticationServer extends AuthenticationServer { diff --git a/id/server/modules/module-stork/pom.xml b/id/server/modules/module-stork/pom.xml index b52c10391..2fec7f519 100644 --- a/id/server/modules/module-stork/pom.xml +++ b/id/server/modules/module-stork/pom.xml @@ -61,6 +61,50 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>eu.stork</groupId> + <artifactId>oasis-dss-api</artifactId> + <version>1.0.0-RELEASE</version> + <exclusions> + <exclusion> + <groupId>org.apache.commons</groupId> + <artifactId>commons-io</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- <dependency> + <groupId>eu.stork</groupId> + <artifactId>Commons</artifactId> + <version>1.4.0</version> + </dependency> --> + <dependency> + <groupId>eu.stork</groupId> + <artifactId>SamlEngine</artifactId> + <version>1.5.1</version> + </dependency> + + <dependency> + <groupId>eu.stork</groupId> + <artifactId>DocumentService</artifactId> + <version>0.0.1-SNAPSHOT</version> + <classifier>classes</classifier> + <exclusions> + <exclusion> + <artifactId>axis</artifactId> + <groupId>org.apache.axis</groupId> + </exclusion> + <exclusion> + <artifactId>bcprov-jdk16</artifactId> + <groupId>org.bouncycastle</groupId> + </exclusion> + <exclusion> + <artifactId>jaxws-tools</artifactId> + <groupId>com.sun.xml.ws</groupId> + </exclusion> + </exclusions> + </dependency> + </dependencies> </project> diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java index 41384690e..ecb568635 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java @@ -28,7 +28,11 @@ public class STORKAuthModuleImpl implements AuthModule { @Override
public String selectProcess(ExecutionContext context) {
- return StringUtils.isNotBlank((String) context.get("ccc")) ? "STORKAuthentication" : null;
+ if (StringUtils.isNotBlank((String) context.get("ccc")) ||
+ StringUtils.isNotBlank((String) context.get("CCC")))
+ return "STORKAuthentication";
+ else
+ return null;
}
@Override
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java index 939390847..ee4961d5e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java @@ -21,6 +21,7 @@ import org.apache.commons.io.IOUtils; import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.data.IdentityLink;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.BKUException;
@@ -113,7 +114,9 @@ public abstract class AbstractPepsConnectorWithLocalSigningTask extends Abstract moaSession.setIdentityLink(identityLink);
Logger.debug("Adding addtional STORK attributes to MOA session");
- moaSession.setStorkAttributes(personalAttributeList);
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ personalAttributeList);
// We don't have BKUURL, setting from null to "Not applicable"
moaSession.setBkuURL("Not applicable (STORK Authentication)");
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java index 138776976..c0422e06e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java @@ -26,11 +26,27 @@ import org.opensaml.common.IdentifierGenerator; import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.w3c.dom.DOMException;
-import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
-import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;
+import eu.stork.oasisdss.api.AdditionalProfiles;
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.api.Profiles;
+import eu.stork.oasisdss.api.QualityLevels;
+import eu.stork.oasisdss.api.SignatureTypes;
+import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
+import eu.stork.oasisdss.profile.AnyType;
+import eu.stork.oasisdss.profile.DocumentType;
+import eu.stork.oasisdss.profile.SignRequest;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.PersonalAttributeList;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.auth.engine.core.CitizenCountryCode;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.builder.CreateXMLSignatureRequestBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
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;
@@ -124,7 +140,10 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { AuthenticationSession moasession = BaseAuthenticationServer.getSession(sessionID);
IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
- if (StringUtils.isEmpty(ccc)) {
+ // bugfix: the new task system fails to initialize the CCC - set it here
+ moasession.setCcc((String) executionContext.get(MOAIDAuthConstants.PARAM_CCC));
+
+ if (StringUtils.isEmpty(moasession.getCcc())) {
// illegal state; task should not have been executed without a selected country
throw new AuthenticationException("stork.22", new Object[] { sessionID });
@@ -265,7 +284,7 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { //attributeList.add(newAttribute);
//store SignRequest for later...
- moasession.setSignedDoc(signedDoc);
+ moasession.setGenericDataToSession("STORK_signDoc", signedDoc);
acsURL = issuerValue + AbstractPepsConnectorWithLocalSigningTask.PEPSCONNECTOR_SERVLET_URL_PATTERN;
// TODO[branch]: STORK AuthReq acsURL "/PEPSConnectorWithLocalSigning"
@@ -340,7 +359,9 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { Logger.debug("STORK AuthnRequest successfully internally validated.");
//send
- moasession.setStorkAuthnRequest(authnRequest);
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ authnRequest);
// do PEPS-conform logging for easier evaluation
try {
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java index 7b9fa3f12..f872241ae 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java @@ -22,6 +22,7 @@ import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
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.AuthenticationSessionStorageConstants;
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.modules.TaskExecutionException;
@@ -142,7 +143,10 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec moaSession.setXMLVerifySignatureResponse(tmp);
executionContext.put("identityLinkAvailable", false);
try {
- IPersonalAttributeList personalAttributeList = moaSession.getAuthnResponseGetPersonalAttributeList();
+ IPersonalAttributeList personalAttributeList =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ IPersonalAttributeList.class);
// Add SignResponse TODO Add signature (extracted from signResponse)?
List<String> values = new ArrayList<String>();
values.add(signResponseString);
@@ -151,7 +155,8 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, "Available");
personalAttributeList.add(signedDocAttribute);
- String authnContextClassRef = moaSession.getAuthnContextClassRef();
+ String authnContextClassRef = moaSession.getGenericDataFromSession(
+ "STORK_authContextClass", String.class);
SZRGInsertion(moaSession, personalAttributeList, authnContextClassRef, citizenSignature);
executionContext.put("identityLinkAvailable", true);
} catch (STORKException e) {
@@ -187,8 +192,9 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec }
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
- // authnResponse?
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED);
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java index e84c33d5d..0ac26f45f 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java @@ -2,18 +2,15 @@ package at.gv.egovernment.moa.id.auth.modules.stork.tasks; import iaik.x509.X509Certificate;
-import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
-import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.Template;
@@ -24,6 +21,7 @@ import org.opensaml.saml2.core.StatusCode; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
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.AuthenticationSessionStorageConstants;
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.modules.TaskExecutionException;
@@ -207,7 +205,10 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep Logger.debug("MOA session is still valid");
- STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+ STORKAuthnRequest storkAuthnRequest =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ STORKAuthnRequest.class);
if (storkAuthnRequest == null) {
Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
@@ -266,11 +267,15 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep } else {
// store SAMLResponse
- moaSession.setSAMLResponse(request.getParameter("SAMLResponse"));
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
// store authnResponse
// moaSession.setAuthnResponse(authnResponse);//not serializable
- moaSession.setAuthnResponseGetPersonalAttributeList(attributeList);
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ attributeList);
String authnContextClassRef = null;
try {
@@ -280,12 +285,12 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
}
- moaSession.setAuthnContextClassRef(authnContextClassRef);
- moaSession.setReturnURL(request.getRequestURL());
+ moaSession.setGenericDataToSession("STORK_authContextClass", authnContextClassRef);
+ moaSession.setGenericDataToSession("STORK_returnURL", request.getRequestURL());
// load signedDoc
- String signRequest = moaSession.getSignedDoc();
-
+ String signRequest = moaSession.getGenericDataFromSession("STORK_signDoc", String.class);
+
// session is implicit stored in changeSessionID!!!!
String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
@@ -383,9 +388,11 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep }
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
- // authnResponse?
-
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
+
+
// session is implicit stored in changeSessionID!!!!
String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java index b505605ab..8322d1a02 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java @@ -2,7 +2,6 @@ package at.gv.egovernment.moa.id.auth.modules.stork.tasks; import iaik.x509.X509Certificate;
-import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
@@ -11,7 +10,6 @@ import java.util.ArrayList; import java.util.Arrays;
import java.util.Date;
import java.util.List;
-import java.util.Properties;
import javax.activation.DataSource;
import javax.servlet.http.HttpServletRequest;
@@ -39,6 +37,7 @@ import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
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.AuthenticationSessionStorageConstants;
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;
@@ -243,7 +242,10 @@ public class PepsConnectorTask extends AbstractAuthServletTask { Logger.debug("MOA session is still valid");
- STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+ STORKAuthnRequest storkAuthnRequest =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ STORKAuthnRequest.class);
if (storkAuthnRequest == null) {
Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
@@ -575,10 +577,15 @@ public class PepsConnectorTask extends AbstractAuthServletTask { moaSession.setIdentityLink(identityLink);
Logger.debug("Adding addtional STORK attributes to MOA session");
- moaSession.setStorkAttributes(attributeList);
-
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ attributeList);
+
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
+
// We don't have BKUURL, setting from null to "Not applicable"
moaSession.setBkuURL("Not applicable (STORK Authentication)");
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java index 9a0598cf6..fb9172f6e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java @@ -24,8 +24,7 @@ package at.gv.egovernment.moa.id.protocols.builder.attributes; import eu.stork.peps.auth.commons.IPersonalAttributeList; import eu.stork.peps.auth.commons.PersonalAttribute; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; -import at.gv.egovernment.moa.id.auth.stork.STORKConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.UnavailableAttributeException; import at.gv.egovernment.moa.logging.Logger; @@ -43,7 +42,10 @@ public class STORKAttributHelper { throw new UnavailableAttributeException(attributName); } else { - IPersonalAttributeList storkAttributes = authSession.getStorkAttributes(); + IPersonalAttributeList storkAttributes = + authSession.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); if ( storkAttributes == null ) { throw new UnavailableAttributeException(attributName); diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java index 2c7e5b539..f9f38e2d5 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java @@ -23,6 +23,7 @@ package at.gv.egovernment.moa.id.protocols.stork2; import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; 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; @@ -30,6 +31,7 @@ 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.IPersonalAttributeList; 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; @@ -83,12 +85,17 @@ public class MOAAttributeProvider { public void populateAttribute(PersonalAttributeList attributeList, PersonalAttribute requestedAttribute ) { String storkAttribute = requestedAttribute.getName(); - + + IPersonalAttributeList storkAttributes = + authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); + // 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())) { + if (null != authData && null != storkAttributes && storkAttributes.containsKey(requestedAttribute.getName())) { Logger.debug("Trying to get value for attribute directly from STORK2 response [" + storkAttribute + "]"); try { - PersonalAttribute tmp = authData.getStorkAttributes().get(requestedAttribute.getName()); + PersonalAttribute tmp = storkAttributes.get(requestedAttribute.getName()); attributeList.add((PersonalAttribute) tmp.clone()); } catch(Exception e) { Logger.error("Could not retrieve attribute from STORK2 response: " + storkAttribute); diff --git a/id/server/modules/pom.xml b/id/server/modules/pom.xml index c164252c7..69cd7c217 100644 --- a/id/server/modules/pom.xml +++ b/id/server/modules/pom.xml @@ -25,6 +25,7 @@ <module>moa-id-modules-saml1</module> <module>moa-id-module-openID</module> <module>moa-id-modul-citizencard_authentication</module> + <module>moa-id-module-eIDAS</module> </modules> <dependencies> |