diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-06-26 11:06:20 +0200 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-06-26 11:06:20 +0200 |
commit | ae550884f5467f6ff6df23100686bc54e100d2d4 (patch) | |
tree | cb06420ee6a0399991fd97b2dec912872990a5a2 | |
download | National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.tar.gz National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.tar.bz2 National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.zip |
initial commit
43 files changed, 3134 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..16a0a262 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +bin +gen +target +*~ +*.orig +*.log +.settings +.project +.classpath +.directory +.checkstyle +/id/server/moa-id-frontend-resources/src/main/resources/mainGUI/version.txt diff --git a/connector/pom.xml b/connector/pom.xml new file mode 100644 index 00000000..a461ab79 --- /dev/null +++ b/connector/pom.xml @@ -0,0 +1,98 @@ +<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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>at.gv.egiz.eidas</groupId> + <artifactId>ms_specific</artifactId> + <version>1.x</version> + </parent> + + <groupId>at.gv.egiz.eidas.ms_specific</groupId> + <artifactId>ms_specific_connector</artifactId> + <packaging>war</packaging> + <version>${egiz.eidas.version}</version> + <name>Connector Maven Webapp</name> + <url>http://maven.apache.org</url> + + <dependencies> + <!-- Web application --> + + <dependency> + <groupId>at.gv.egiz.components</groupId> + <artifactId>egiz-spring-api</artifactId> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_module_pvp2_idp</artifactId> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- Third party libs --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + + + <!-- Testing --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <finalName>ms_connector</finalName> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <!-- enable co-existence of testng and junit --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <threadCount>1</threadCount> + <argLine>--add-modules java.xml.bind</argLine> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> + + </plugins> + </build> +</project> diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSSpecificeIDASNodeSpringResourceProvider.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSSpecificeIDASNodeSpringResourceProvider.java new file mode 100644 index 00000000..f64b6073 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSSpecificeIDASNodeSpringResourceProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +public class MSSpecificeIDASNodeSpringResourceProvider implements SpringResourceProvider { + + @Override + public Resource[] getResourcesToLoad() { + ClassPathResource mseIDASNode = new ClassPathResource("/specific_eIDAS_connector.beans.xml", MSSpecificeIDASNodeSpringResourceProvider.class); + return new Resource[] {mseIDASNode}; + } + + @Override + public String[] getPackagesToScan() { + return null; + } + + @Override + public String getName() { + return "MS-specific eIDAS Node SpringResourceProvider"; + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSeIDASNodeConstants.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSeIDASNodeConstants.java new file mode 100644 index 00000000..97defade --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/MSeIDASNodeConstants.java @@ -0,0 +1,53 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector; + +import at.gv.egiz.eaaf.core.api.data.EAAFConfigConstants; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; + +public class MSeIDASNodeConstants { + //configuration properties + public static final String PROP_CONFIG_APPLICATION_PREFIX = "eidas.ms."; + public static final String PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX = "context.url.prefix"; + + private static final String PROP_CONFIG_PVP2_PREFIX = "pvp2."; + public static final String PROP_CONFIG_PVP2_KEYSTORE_PATH = PROP_CONFIG_PVP2_PREFIX + "keystore.path"; + public static final String PROP_CONFIG_PVP2_KEYSTORE_PASSWORD = PROP_CONFIG_PVP2_PREFIX + "keystore.password"; + public static final String PROP_CONFIG_PVP2_KEY_METADATA_ALIAS = PROP_CONFIG_PVP2_PREFIX + "key.metadata.alias"; + public static final String PROP_CONFIG_PVP2_KEY_METADATA_PASSWORD = PROP_CONFIG_PVP2_PREFIX + "key.metadata.password"; + public static final String PROP_CONFIG_PVP2_KEY_SIGNING_ALIAS = PROP_CONFIG_PVP2_PREFIX + "key.signing.alias"; + public static final String PROP_CONFIG_PVP2_KEY_SIGNING_PASSWORD = PROP_CONFIG_PVP2_PREFIX + "key.signing.password"; + public static final String PROP_CONFIG_PVP2_METADATA_VALIDITY = PROP_CONFIG_PVP2_PREFIX + "metadata.validity"; + + public static final String PROP_CONFIG_SP_LIST_PREFIX = "sp."; + public static final String PROP_CONFIG_SP_UNIQUEIDENTIFIER = EAAFConfigConstants.SERVICE_UNIQUEIDENTIFIER; + public static final String PROP_CONFIG_SP_FRIENDLYNAME = "friendlyName"; + public static final String PROP_CONFIG_SP_PVP2_METADATA_URL = "pvp2.metadata.url"; + public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE = "pvp2.metadata.truststore"; + public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE_PASSWORD = "pvp2.metadata.truststore.password"; + public static final String PROP_CONFIG_SP_POLICY_ALLOWED_TARGETS = "policy.allowed.requested.targets"; + public static final String PROP_CONFIG_SP_POLICY_BASEIDTRANSFER_RESTRICTION = "policy.hasBaseIdTransferRestriction"; + + public static final String PROP_CONFIG_PVP_SCHEME_VALIDATION = "configuration.pvp.scheme.validation"; + public static final String PROP_CONFIG_PVP_ENABLE_ENTITYCATEGORIES = "configuration.pvp.enable.entitycategories"; + + //default values + public static final String POLICY_DEFAULT_ALLOWED_TARGETS = + EAAFConstants.URN_PREFIX_CDID.replaceAll(".", "\\.").replaceAll("+", "\\+") + ".*"; + public static final int METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout + public static final int DEFAULT_PVP_METADATA_VALIDITY = 24; //24 hours + + //application end-points + public static final String ENDPOINT_PVP_METADATA = "/pvp/metadata"; + public static final String ENDPOINT_PVP_POST = "/pvp/post"; + public static final String ENDPOINT_PVP_REDIRECT = "/pvp/redirect"; + + + //paths and templates + public static final String CLASSPATH_TEMPLATE_DIR = "/templates/"; + + public static final String TEMPLATE_HTML_ERROR = "error.html"; + public static final String TEMPLATE_HTML_PVP_POSTBINDING = "pvp2_post_binding.html"; + + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/SpringInitializer.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/SpringInitializer.java new file mode 100644 index 00000000..d5c2632c --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/SpringInitializer.java @@ -0,0 +1,166 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector; + +import java.util.Arrays; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.request.RequestContextListener; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.context.support.ServletContextResource; +import org.springframework.web.servlet.DispatcherServlet; + +import at.gv.egiz.components.spring.api.SpringLoader; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; + +/** + * Web application initializer + * + * @author Thomas Lenz + */ +public class SpringInitializer implements WebApplicationInitializer { + + private static final Logger log = LoggerFactory.getLogger(SpringInitializer.class); + + private String[] rootServletContexts = null; + private String[] servletContexts = null; + private String[] activeProfiles = null; + + public SpringInitializer() { + this.rootServletContexts = null; + this.servletContexts = new String[] { + "/applicationContext.xml", + + }; + this.activeProfiles = null; + } + + + /* (non-Javadoc) + * @see org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet.ServletContext) + */ + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + try { + log.info("=============== Loading Config Root Context! ==============="); + ApplicationContext cfgRootContext = + new ClassPathXmlApplicationContext(new String[] { + "/applicationContext.xml" + }); + + + log.info("=============== Loading Root Context! ==============="); + GenericWebApplicationContext rootContext = new GenericWebApplicationContext(); + rootContext.setServletContext(servletContext); + rootContext.setParent(cfgRootContext); + +// log.info("=============== Setting active profiles! ==============="); +// if (this.activeProfiles != null) { +// for (String profile : this.activeProfiles) { +// rootContext.getEnvironment().addActiveProfile(profile); +// } +// } + + log.info("Spring-context was initialized with active profiles: " + + Arrays.asList(rootContext.getEnvironment().getActiveProfiles())); + + log.info("=============== Loading Local Contexts! ==============="); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader( + rootContext); + if (rootServletContexts != null) { + for (String rootServletContext : rootServletContexts) { + log.debug("Loading: "+ rootServletContext); + xmlReader.loadBeanDefinitions(new ServletContextResource( + servletContext, rootServletContext)); + } + } + // Manage the lifecycle of the root application context + servletContext.addListener(new ContextLoaderListener(rootContext)); + + // log.debug("Beans after logAMQP in {}", rootContext); + // dumpBeanDefinitions(rootContext); + + log.info("=============== Loading SPI Context! ==============="); + if (rootContext instanceof BeanDefinitionRegistry) { + log.debug("Loading modules and components"); + SpringLoader.loadSpringServices(rootContext); + + } else + log.warn("Failed to load external Spring since no BeanDefinitionRegistry"); + + log.trace("Beans after SPI in "+ rootContext); + dumpBeanDefinitions(rootContext); + + log.debug("Loading servlet config in "+ rootContext); + if (servletContexts != null) { + for (String servletContextString : servletContexts) + xmlReader.loadBeanDefinitions(new ClassPathResource(servletContextString, SpringInitializer.class)); + + } + + log.debug("Refreshing context "+ rootContext); + rootContext.refresh(); + + log.info("=============== Register Dispatcher Servlet! ==============="); + + log.trace("Final Beans in "+ rootContext); + dumpBeanDefinitions(rootContext); + + log.info("Registering dispatcher configuration"); + ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext)); + if (dispatcher != null) { + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/"); + dispatcher.setAsyncSupported(true); + + } else + log.error("Failed to register dispatcher server in servlet context!"); + + + log.info("=============== Register RequestContextListener! ==============="); + servletContext.addListener(new RequestContextListener()); + + //TODO: integrate message provider!!!! + //log.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null)); + + log.info("Bootstrap openSAML .... "); + EAAFDefaultSAML2Bootstrap.bootstrap(); + + log.info("Initialization of MS-specific eIDAS-connector finished."); + + + } catch (Throwable e) { + log.error("MS-specific eIDAS-connector initialization FAILED!", e); + + } + + } + + private void dumpBeanDefinitions(GenericApplicationContext context) { + log.trace("Registered Bean in context " + context.toString()); + + String[] registeredBeans = context.getBeanDefinitionNames(); + for (String registeredBean : registeredBeans) { + BeanDefinition beanDefinition = context + .getBeanDefinition(registeredBean); + log.trace(registeredBean + " -> " + beanDefinition.getBeanClassName()); + + } + + log.trace("Registered Bean in context --"+ context); + } +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/auth/AuthenticationManager.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/auth/AuthenticationManager.java new file mode 100644 index 00000000..e41bad28 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/auth/AuthenticationManager.java @@ -0,0 +1,38 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.auth; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.api.idp.slo.ISLOInformationContainer; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; + +@Service("AuthenticationManager") +public class AuthenticationManager extends AbstractAuthenticationManager { + private static final Logger log = LoggerFactory.getLogger(AuthenticationManager.class); + + @Override + public ISLOInformationContainer performSingleLogOut(HttpServletRequest httpReq, HttpServletResponse httpResp, + IRequest pendingReq, String internalSSOId) throws EAAFException { + throw new RuntimeException("Single LogOut is NOT supported by this implementation"); + + } + + @Override + protected void populateExecutionContext(ExecutionContext executionContext, + RequestImpl pendingReq, HttpServletRequest httpReq) + throws EAAFException { + log.trace("No implementation-specific population of execution-context required ... "); + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/AuthenticationDataBuilder.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/AuthenticationDataBuilder.java new file mode 100644 index 00000000..775e36f2 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/AuthenticationDataBuilder.java @@ -0,0 +1,64 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.builder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.w3c.dom.DOMException; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IAuthProcessDataContainer; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFBuilderException; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFParserException; +import at.gv.egiz.eaaf.core.exceptions.XPathException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; + +@Service("AuthenticationDataBuilder") +public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder { + private static final Logger log = LoggerFactory.getLogger(AuthenticationDataBuilder.class); + + @Override + public IAuthData buildAuthenticationData(IRequest pendingReq) throws EAAFAuthenticationException { + + IAuthProcessDataContainer authProcessData = new AuthProcessDataWrapper(pendingReq.genericFullDataStorage()); + AuthenticationData authData = new AuthenticationData(); + + try { + generateBasicAuthData(authData, pendingReq, authProcessData); + + } catch (EAAFBuilderException | EAAFParserException | EAAFConfigurationException + | XPathException | DOMException e) { + log.warn("Can not build authentication data from auth. process information"); + throw new EAAFAuthenticationException("TODO", new Object[]{}, + "Can not build authentication data from auth. process information", e); + + } + + + + + return null; + } + + @Override + protected Pair<String, String> getEncryptedbPKFromPVPAttribute(IAuthProcessDataContainer arg0, + AuthenticationData arg1, ISPConfiguration arg2) throws EAAFBuilderException { + return null; + + } + + @Override + protected Pair<String, String> getbaseIDFromSZR(AuthenticationData arg0, String arg1, String arg2) { + return null; + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/PVPSubjectNameGenerator.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/PVPSubjectNameGenerator.java new file mode 100644 index 00000000..d640539a --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/builder/PVPSubjectNameGenerator.java @@ -0,0 +1,19 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.builder; + +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; + +public class PVPSubjectNameGenerator implements ISubjectNameIdGenerator { + + @Override + public Pair<String, String> generateSubjectNameId(IAuthData authData, ISPConfiguration spConfig) throws PVP2Exception { + //TODO: maybe update + return Pair.newInstance(authData.getBPK(), authData.getBPKType()); + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/BasicConfigurationProvider.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/BasicConfigurationProvider.java new file mode 100644 index 00000000..b898dfef --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/BasicConfigurationProvider.java @@ -0,0 +1,114 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.config; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.idp.conf.AbstractConfigurationImpl; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +@Service("BasicMSSpecificNodeConfig") +public class BasicConfigurationProvider extends AbstractConfigurationImpl{ + private static final Logger log = LoggerFactory.getLogger(BasicConfigurationProvider.class); + + private Map<String, ISPConfiguration> spConfigCache = new HashMap<String, ISPConfiguration>(); + + public BasicConfigurationProvider(String configPath) throws EAAFConfigurationException { + super(configPath); + + } + + @Override + public ISPConfiguration getServiceProviderConfiguration(String entityId) throws EAAFConfigurationException { + if (!spConfigCache.containsKey(entityId)) { + log.debug("SP: " + entityId + " is NOT cached. Starting load operation ... "); + Map<String, String> allSPs = getBasicMOAIDConfigurationWithPrefix(MSeIDASNodeConstants.PROP_CONFIG_SP_LIST_PREFIX); + for (String key : allSPs.keySet()) { + if (key.endsWith(MSeIDASNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER) && + allSPs.get(key).equals(entityId)) { + String listId = KeyValueUtils.getParentKey(key); + log.trace("Find SP configuration with list-Id: " + listId + ". Extracting configuration elements ... "); + Map<String, String> spConfig = KeyValueUtils.getSubSetWithPrefix(allSPs, listId + KeyValueUtils.KEY_DELIMITER); + spConfigCache.put(entityId, + new ServiceProviderConfiguration(spConfig, this)); + break; + } + } + + if (spConfigCache.containsKey(entityId)) + log.info("SP: " + entityId + " is loaded. Continuing auth. process ... "); + else { + log.warn("SP: " + entityId + " is NOT found in configuration. Stopping auth. process ... "); + return null; + + } + + } else + log.trace("SP: " + entityId + " is already cached. Use configuration from there ... "); + + + return spConfigCache.get(entityId); + } + + @Override + public <T> T getServiceProviderConfiguration(String entityId, Class<T> decorator) throws EAAFConfigurationException { + ISPConfiguration spConfig = getServiceProviderConfiguration(entityId); + if (spConfig != null && decorator != null) { + if (decorator.isInstance(spConfig)) + return (T)spConfig; + else + log.error("SPConfig: " + spConfig.getClass().getName() + " is NOT instance of: " + decorator.getName()); + + } + + return null; + + } + + @Override + public String validateIDPURL(URL url) throws EAAFException { + log.trace("Validate requested URL: " + url); + String urlPrefixFromConfig = getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX); + if (StringUtils.isEmpty(urlPrefixFromConfig)) { + log.warn("Application config containts NO URL prefix"); + throw new EAAFConfigurationException("Application config containts NO URL prefix"); + + } + + //remove last slash + if (urlPrefixFromConfig.endsWith("/")) + urlPrefixFromConfig = urlPrefixFromConfig.substring(0, urlPrefixFromConfig.length()-1); + + if (url != null && url.toExternalForm().startsWith(urlPrefixFromConfig)) + return urlPrefixFromConfig; + + + log.info("URL: " + url + " does NOT match to allowed application prefix: " + urlPrefixFromConfig); + return null; + } + + @Override + public String getApplicationSpecificKeyPrefix() { + return MSeIDASNodeConstants.PROP_CONFIG_APPLICATION_PREFIX; + + } + + @Override + protected String getBackupConfigPath() { + return null; + + } + + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPEndPointConfiguration.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPEndPointConfiguration.java new file mode 100644 index 00000000..21e46e10 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPEndPointConfiguration.java @@ -0,0 +1,68 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.config; + +import java.util.List; + +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.Organization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +@Service("PVPEndPointConfiguration") +public class PVPEndPointConfiguration implements IPVP2BasicConfiguration { + private static final Logger log = LoggerFactory.getLogger(PVPEndPointConfiguration.class); + + @Autowired(required=true) IConfiguration basicConfiguration; + + @Override + public String getIDPEntityId(String authURL) throws EAAFException { + return removePostFix(authURL) + MSeIDASNodeConstants.ENDPOINT_PVP_METADATA; + + } + + @Override + public String getIDPSSOPostService(String authURL) throws EAAFException { + return removePostFix(authURL) + MSeIDASNodeConstants.ENDPOINT_PVP_POST; + + } + + @Override + public String getIDPSSORedirectService(String authURL) throws EAAFException { + return removePostFix(authURL) + MSeIDASNodeConstants.ENDPOINT_PVP_REDIRECT; + + } + + @Override + public Object getIDPSSOSOAPService(String extractAuthURLFromRequest) throws EAAFException { + log.warn("PVP S-Profile End-Point does NOT support SOAP Binding"); + return null; + + } + + @Override + public List<ContactPerson> getIDPContacts() throws EAAFException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Organization getIDPOrganisation() throws EAAFException { + // TODO Auto-generated method stub + return null; + } + + private String removePostFix(String url) { + if (url != null && url.endsWith("/")) + return url.substring(0, url.length() - 1); + else + return url; + } +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPMetadataConfiguration.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPMetadataConfiguration.java new file mode 100644 index 00000000..7d17baa1 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/PVPMetadataConfiguration.java @@ -0,0 +1,240 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.config; + +import java.util.Arrays; +import java.util.List; + +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.xml.security.credential.Credential; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +public class PVPMetadataConfiguration implements IPVPMetadataBuilderConfiguration{ + private static final Logger log = LoggerFactory.getLogger(PVPMetadataConfiguration.class); + + private IConfiguration basicConfig; + private String authUrl; + private AbstractCredentialProvider pvpIDPCredentials; + private IPVP2BasicConfiguration pvpBasicConfig; + + public PVPMetadataConfiguration(IConfiguration basicConfig, String authURL, IPVP2BasicConfiguration pvpBasicConfig, AbstractCredentialProvider pvpIDPCredentials) { + this.authUrl = authURL; + this.pvpIDPCredentials = pvpIDPCredentials; + this.basicConfig = basicConfig; + this.pvpBasicConfig = pvpBasicConfig; + + } + + @Override + public String getSPNameForLogging() { + return "PVP2 S-Profile IDP"; + } + + @Override + public int getMetadataValidUntil() { + return Integer.valueOf(basicConfig.getBasicConfiguration( + MSeIDASNodeConstants.PROP_CONFIG_PVP2_METADATA_VALIDITY, + String.valueOf(MSeIDASNodeConstants.DEFAULT_PVP_METADATA_VALIDITY))); + + } + + @Override + public boolean buildEntitiesDescriptorAsRootElement() { + return false; + + } + + @Override + public boolean buildIDPSSODescriptor() { + return true; + + } + + @Override + public boolean buildSPSSODescriptor() { + return false; + + } + + @Override + public String getEntityID() { + try { + return pvpBasicConfig.getIDPEntityId(authUrl); + + } catch (EAAFException e) { + log.error("Can NOT build PVP metadata configuration.", e); + throw new RuntimeException("Can NOT build PVP metadata configuration."); + + } + + } + + @Override + public String getEntityFriendlyName() { + return null; + + } + + @Override + public List<ContactPerson> getContactPersonInformation() { + try { + return pvpBasicConfig.getIDPContacts(); + + } catch (EAAFException e) { + log.error("Can NOT build PVP metadata configuration.", e); + throw new RuntimeException("Can NOT build PVP metadata configuration."); + + } + + } + + @Override + public Organization getOrgansiationInformation() { + try { + return pvpBasicConfig.getIDPOrganisation(); + + } catch (EAAFException e) { + log.error("Can NOT build PVP metadata configuration.", e); + throw new RuntimeException("Can NOT build PVP metadata configuration."); + + } + } + + @Override + public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return pvpIDPCredentials.getIDPMetaDataSigningCredential(); + + } + + @Override + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return pvpIDPCredentials.getIDPAssertionSigningCredential(); + + } + + @Override + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + return null; + + + } + + @Override + public String getIDPWebSSOPostBindingURL() { + try { + return pvpBasicConfig.getIDPSSOPostService(authUrl); + + } catch (EAAFException e) { + log.error("Can NOT build PVP metadata configuration.", e); + throw new RuntimeException("Can NOT build PVP metadata configuration."); + + } + + } + + @Override + public String getIDPWebSSORedirectBindingURL() { + try { + return pvpBasicConfig.getIDPSSORedirectService(authUrl); + + } catch (EAAFException e) { + log.error("Can NOT build PVP metadata configuration.", e); + throw new RuntimeException("Can NOT build PVP metadata configuration."); + + } + } + + @Override + public String getIDPSLOPostBindingURL() { + return null; + + } + + @Override + public String getIDPSLORedirectBindingURL() { + return null; + + } + + @Override + public String getSPAssertionConsumerServicePostBindingURL() { + return null; + + } + + @Override + public String getSPAssertionConsumerServiceRedirectBindingURL() { + return null; + + } + + @Override + public String getSPSLOPostBindingURL() { + return null; + + } + + @Override + public String getSPSLORedirectBindingURL() { + return null; + + } + + @Override + public String getSPSLOSOAPBindingURL() { + return null; + + } + + @Override + public List<Attribute> getIDPPossibleAttributes() { + return PVPAttributeBuilder.buildSupportedEmptyAttributes(); + + } + + @Override + public List<String> getIDPPossibleNameITTypes() { + return Arrays.asList(NameIDType.PERSISTENT, + NameIDType.TRANSIENT, + NameIDType.UNSPECIFIED); + } + + @Override + public List<RequestedAttribute> getSPRequiredAttributes() { + return null; + + } + + @Override + public List<String> getSPAllowedNameITTypes() { + return null; + + } + + @Override + public boolean wantAssertionSigned() { + return false; + + } + + @Override + public boolean wantAuthnRequestSigned() { + return true; + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/ServiceProviderConfiguration.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/ServiceProviderConfiguration.java new file mode 100644 index 00000000..3d8a3bdd --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/config/ServiceProviderConfiguration.java @@ -0,0 +1,105 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.config; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.idp.conf.SPConfigurationImpl; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +public class ServiceProviderConfiguration extends SPConfigurationImpl { + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(ServiceProviderConfiguration.class); + + private String minimumLoA = EAAFConstants.EIDAS_QAA_HIGH; + private String bPKTargetIdentifier; + + public ServiceProviderConfiguration(Map<String, String> spConfig, IConfiguration authConfig) { + super(spConfig, authConfig); + + } + + @Override + public boolean hasBaseIdInternalProcessingRestriction() { + return false; + + } + + @Override + public boolean hasBaseIdTransferRestriction() { + return isConfigurationValue( + MSeIDASNodeConstants.PROP_CONFIG_SP_POLICY_BASEIDTRANSFER_RESTRICTION, + true); + + } + + @Override + public String getMinimumLevelOfAssurence() { + return minimumLoA; + + } + + + @Override + public String getAreaSpecificTargetIdentifier() { + return bPKTargetIdentifier; + } + + + @Override + public String getFriendlyName() { + return getConfigurationValue( + MSeIDASNodeConstants.PROP_CONFIG_SP_FRIENDLYNAME, + "NO FRIENDLYNAME SET"); + + } + + /** + * Set the minimum level of eIDAS authentication for this SP + * <br> + * <b>Default:</b> http://eidas.europa.eu/LoA/high or + * + * @param minimumLoA eIDAS LoA URI + */ + + public void setMinimumLoA(String minimumLoA) { + this.minimumLoA = minimumLoA; + } + + + /** + * Set the bPK Target for this service provider + * + * @param bPKTargetIdentifier + * @throws EAAFException If the bPKTargetIdentifier is NOT ALLOWED for this service provider + */ + public void setbPKTargetIdentifier(String bPKTargetIdentifier) throws EAAFException { + String allowedTargetIdentifierRegExPattern = getConfigurationValue( + MSeIDASNodeConstants.PROP_CONFIG_SP_POLICY_ALLOWED_TARGETS, + MSeIDASNodeConstants.POLICY_DEFAULT_ALLOWED_TARGETS); + log.trace("Use bPK-target regex pattern: " + allowedTargetIdentifierRegExPattern); + + Pattern p = Pattern.compile(allowedTargetIdentifierRegExPattern); + Matcher m = p.matcher(bPKTargetIdentifier); + if (m.matches()) { + log.debug("Requested bPK-target: " + bPKTargetIdentifier + " matches regex pattern"); + this.bPKTargetIdentifier = bPKTargetIdentifier; + + } else { + log.warn("Requested bPK-target: " + bPKTargetIdentifier + " does NOT match regex pattern."); + throw new EAAFException("TODO", new Object[] {bPKTargetIdentifier}, + "Requested bPK-target: " + bPKTargetIdentifier + " does NOT match regex pattern."); + + } + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/controller/PVP2SProfileEndpoint.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/controller/PVP2SProfileEndpoint.java new file mode 100644 index 00000000..62092675 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/controller/PVP2SProfileEndpoint.java @@ -0,0 +1,59 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.AbstractPVP2XProtocol; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +@Controller +public class PVP2SProfileEndpoint extends AbstractPVP2XProtocol{ + + public static final String NAME = PVP2SProfileEndpoint.class.getName(); + public static final String PROTOCOL_ID = "pvp2-s"; + + @RequestMapping(value = MSeIDASNodeConstants.ENDPOINT_PVP_METADATA, method = {RequestMethod.POST, RequestMethod.GET}) + public void PVPMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + super.pvpMetadataRequest(req, resp); + + } + + @RequestMapping(value = MSeIDASNodeConstants.ENDPOINT_PVP_POST, method = {RequestMethod.POST}) + public void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + super.PVPIDPPostRequest(req, resp); + + } + + @RequestMapping(value = MSeIDASNodeConstants.ENDPOINT_PVP_REDIRECT, method = {RequestMethod.GET}) + public void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + super.PVPIDPRedirecttRequest(req, resp); + + } + + + @Override + public String getAuthProtocolIdentifier() { + return PROTOCOL_ID; + } + + @Override + public String getName() { + return NAME; + } + + @Override + protected boolean childPreProcess(HttpServletRequest arg0, HttpServletResponse arg1, PVPSProfilePendingRequest arg2) + throws Throwable { + return false; + } + + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/DefaultGUIBuilderImpl.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/DefaultGUIBuilderImpl.java new file mode 100644 index 00000000..e423b09a --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/DefaultGUIBuilderImpl.java @@ -0,0 +1,44 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.gui; + +import java.io.InputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; +import at.gv.egiz.eaaf.core.impl.gui.AbstractGUIFormBuilderImpl; + +@Service("DefaultGUIBuilderImpl") +public class DefaultGUIBuilderImpl extends AbstractGUIFormBuilderImpl{ + private static final Logger log = LoggerFactory.getLogger(DefaultGUIBuilderImpl.class); + + private static final String CLASSPATH_HTMLTEMPLATES_DIR = "templates/"; + + public DefaultGUIBuilderImpl() throws GUIBuildException { + super(); + + } + + @Override + protected InputStream getInternalTemplate(IGUIBuilderConfiguration config) throws GUIBuildException { + String viewName = config.getViewName(); + log.debug("GUI template:" + viewName + " is not found in configuration directory. " + + " Load template from project library ... "); + String pathLocation = getInternalClasspathTemplateDir(config, CLASSPATH_HTMLTEMPLATES_DIR) + viewName; + try { + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(pathLocation); + return is; + + } catch (Exception e1) { + log.error("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1); + throw new GUIBuildException("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1); + + } + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/GUIBuilderConfigurationFactory.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/GUIBuilderConfigurationFactory.java new file mode 100644 index 00000000..8132c063 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/GUIBuilderConfigurationFactory.java @@ -0,0 +1,32 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.gui; + +import java.net.MalformedURLException; +import java.net.URI; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +@Service("GUIBuilderConfigurationFactory") +public class GUIBuilderConfigurationFactory implements IGUIBuilderConfigurationFactory { + @Autowired(required=true) private IConfiguration basicConfig; + + @Override + public IGUIBuilderConfiguration getDefaultErrorGUI(String authURL) { + return new StaticGuiBuilderConfiguration(basicConfig, authURL, MSeIDASNodeConstants.TEMPLATE_HTML_ERROR, null); + } + + @Override + public IGUIBuilderConfiguration getSPSpecificSAML2PostConfiguration(IRequest pendingReq, String viewName, URI configRootContextDir) + throws MalformedURLException { + return new StaticGuiBuilderConfiguration(basicConfig, pendingReq,MSeIDASNodeConstants.TEMPLATE_HTML_PVP_POSTBINDING , null); + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/StaticGuiBuilderConfiguration.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/StaticGuiBuilderConfiguration.java new file mode 100644 index 00000000..8dd3c580 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/gui/StaticGuiBuilderConfiguration.java @@ -0,0 +1,91 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.gui; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.gui.AbstractGUIFormBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +public class StaticGuiBuilderConfiguration extends AbstractGUIFormBuilderConfiguration { + private static final Logger log = LoggerFactory.getLogger(StaticGuiBuilderConfiguration.class); + + private IRequest pendingReq = null; + private IConfiguration basicConfig = null; + + public StaticGuiBuilderConfiguration(IConfiguration basicConfig, String authURL, String viewName, String formSubmitEndpoint) { + super(authURL, viewName, formSubmitEndpoint); + this.basicConfig = basicConfig; + } + + public StaticGuiBuilderConfiguration(IConfiguration basicConfig, IRequest pendingReq, String viewName, String formSubmitEndpoint) { + super(pendingReq.getAuthURL(), viewName, formSubmitEndpoint); + this.pendingReq = pendingReq; + this.basicConfig = basicConfig; + + } + + @Override + public String getClasspathTemplateDir() { + return MSeIDASNodeConstants.CLASSPATH_TEMPLATE_DIR; + + } + + @Override + public String getDefaultContentType() { + return null; + + } + + @Override + public InputStream getTemplate(String viewName) { + String templateURL = MSeIDASNodeConstants.CLASSPATH_TEMPLATE_DIR + viewName; + try { + String absURL = FileUtils.makeAbsoluteURL(templateURL, this.basicConfig.getConfigurationRootDirectory()); + if (!absURL.startsWith("file:")) { + log.warn("Path to template looks like NOT absolut: " + absURL + ". Template loading FAILED"); + + } else { + log.debug("Load template URL for view: " + viewName + " from: " + absURL); + URI uri = new URL(absURL).toURI(); + return new FileInputStream(new File(uri)); + + } + + + } catch (MalformedURLException | URISyntaxException | FileNotFoundException e) { + log.warn("Can can build filesytem path to template: " + templateURL, e); + + } + + return null; + } + + @Override + protected Map<String, Object> getSpecificViewParameters() { + Map<String, Object> params = new HashMap<String, Object>(); + if (pendingReq != null) { + params.put(PARAM_PENDINGREQUESTID, StringEscapeUtils.escapeHtml(pendingReq.getPendingRequestId())); + + } + + return params; + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/mapper/LoALevelMapper.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/mapper/LoALevelMapper.java new file mode 100644 index 00000000..9432931e --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/mapper/LoALevelMapper.java @@ -0,0 +1,34 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.mapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; + +@Service("LoALevelMapper") +public class LoALevelMapper implements ILoALevelMapper{ + private static final Logger log = LoggerFactory.getLogger(LoALevelMapper.class); + + @Override + public String mapToSecClass(String LoA) { + log.info("Mapping to PVP SecClass is NOT supported"); + return null; + } + + @Override + public String mapToeIDASLoA(String LoA) { + if (LoA.startsWith(EAAFConstants.EIDAS_QAA_PREFIX)) + return LoA; + + else + log.info("Can NOT map '" + LoA + "' to eIDAS LoA"); + + return null; + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPEndPointCredentialProvider.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPEndPointCredentialProvider.java new file mode 100644 index 00000000..cd86c79a --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPEndPointCredentialProvider.java @@ -0,0 +1,92 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.provider; + +import java.net.MalformedURLException; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +public class PVPEndPointCredentialProvider extends AbstractCredentialProvider { + private static final Logger log = LoggerFactory.getLogger(PVPEndPointCredentialProvider.class); + + @Autowired(required=true) IConfiguration basicConfiguration; + + @Override + public String getFriendlyName() { + return "PVP2 S-Profile EndPoint"; + } + + @Override + public String getKeyStoreFilePath() throws EAAFException { + try { + String path = basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PATH); + if (StringUtils.isEmpty(path)) { + log.error(getFriendlyName() + " | Path to keyStore is NULL or EMPTY"); + throw new EAAFConfigurationException(getFriendlyName() + " | Path to keyStore is NULL or EMPTY"); + + } + + return FileUtils.makeAbsoluteURL( + path, + basicConfiguration.getConfigurationRootDirectory()); + + } catch (MalformedURLException e) { + log.error(getFriendlyName() + " | Path to keyStore NOT valid.", e); + throw new EAAFConfigurationException(getFriendlyName() + " | Path to keyStore NOT valid.", e); + + } + + } + + @Override + public String getKeyStorePassword() { + return basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PASSWORD); + + } + + @Override + public String getMetadataKeyAlias() { + return basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEY_METADATA_ALIAS); + } + + @Override + public String getMetadataKeyPassword() { + return basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEY_METADATA_PASSWORD); + + } + + @Override + public String getSignatureKeyAlias() { + return basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEY_SIGNING_ALIAS); + + } + + @Override + public String getSignatureKeyPassword() { + return basicConfiguration.getBasicConfiguration(MSeIDASNodeConstants.PROP_CONFIG_PVP2_KEY_SIGNING_PASSWORD); + + } + + @Override + public String getEncryptionKeyAlias() { + return null; + + } + + @Override + public String getEncryptionKeyPassword() { + return null; + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataConfigurationFactory.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataConfigurationFactory.java new file mode 100644 index 00000000..c5d2f29c --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataConfigurationFactory.java @@ -0,0 +1,28 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.provider; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eidas.specific.connector.config.PVPMetadataConfiguration; + +@Service("PVPMetadataConfigurationFactory") +public class PVPMetadataConfigurationFactory implements IPVPMetadataConfigurationFactory { + + @Autowired private IConfiguration basicConfig; + @Autowired private IPVP2BasicConfiguration pvpBasicConfig; + + @Override + public IPVPMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authURL, + AbstractCredentialProvider pvpIDPCredentials) { + return new PVPMetadataConfiguration(basicConfig, authURL, pvpBasicConfig, pvpIDPCredentials); + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataProvider.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataProvider.java new file mode 100644 index 00000000..0edc5fcd --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/PVPMetadataProvider.java @@ -0,0 +1,93 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.provider; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.List; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.xml.parse.BasicParserPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.AbstractChainingMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.MetadataFilterChain; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PVPEntityCategoryFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; +import at.gv.egiz.eidas.specific.connector.MSeIDASNodeConstants; + +@Service("PVPMetadataProvider") +public class PVPMetadataProvider extends AbstractChainingMetadataProvider{ + private static final Logger log = LoggerFactory.getLogger(PVPMetadataProvider.class); + + @Autowired(required=true) IConfiguration basicConfig; + + @Override + protected String getMetadataURL(String entityId) throws EAAFConfigurationException { + ISPConfiguration spConfig = basicConfig.getServiceProviderConfiguration(entityId); + if (spConfig != null) { + return spConfig.getConfigurationValue(MSeIDASNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_URL); + + } else + log.info("No ServiceProvider with entityId: " + entityId + " in configuration."); + + return null; + } + + @Override + protected MetadataProvider createNewMetadataProvider(String entityId) + throws EAAFConfigurationException, IOException, CertificateException { + ISPConfiguration spConfig = basicConfig.getServiceProviderConfiguration(entityId); + if (spConfig != null) { + String metadataURL = spConfig.getConfigurationValue(MSeIDASNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_URL); + String trustStoreUrl = spConfig.getConfigurationValue(MSeIDASNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE); + return createNewSimpleMetadataProvider(metadataURL, + buildMetadataFilterChain(spConfig, metadataURL, trustStoreUrl), + spConfig.getConfigurationValue(MSeIDASNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER), + getTimer(), + new BasicParserPool(), + createHttpClient(metadataURL)); + + } else + log.info("No ServiceProvider with entityId: " + entityId + " in configuration."); + + return null; + } + + @Override + protected List<String> getAllMetadataURLsFromConfiguration() throws EAAFConfigurationException { + // TODO Auto-generated method stub + return null; + } + + private HttpClient createHttpClient(String metadataURL) { + HttpClient httpClient = new HttpClient(); + HttpClientParams httpClientParams = new HttpClientParams(); + httpClientParams.setSoTimeout(MSeIDASNodeConstants.METADATA_SOCKED_TIMEOUT); + httpClient.setParams(httpClientParams); + return httpClient; + + } + + private MetadataFilterChain buildMetadataFilterChain(ISPConfiguration oaParam, String metadataURL, String trustStoreUrl) throws CertificateException{ + MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.getFilters().add(new SchemaValidationFilter( + basicConfig.getBasicMOAIDConfigurationBoolean(MSeIDASNodeConstants.PROP_CONFIG_PVP_SCHEME_VALIDATION, true))); + + //TODO: add signature validation filter + + + filterChain.getFilters().add(new PVPEntityCategoryFilter( + basicConfig.getBasicMOAIDConfigurationBoolean(MSeIDASNodeConstants.PROP_CONFIG_PVP_ENABLE_ENTITYCATEGORIES, true))); + + return filterChain; + } +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/StatusMessageProvider.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/StatusMessageProvider.java new file mode 100644 index 00000000..6e3f45cc --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/provider/StatusMessageProvider.java @@ -0,0 +1,30 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.provider; + +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.IStatusMessager; + +@Service("StatusMessageProvider") +public class StatusMessageProvider implements IStatusMessager { + + @Override + public String getMessage(String messageId, Object[] parameters) { + return "NOT IMPLEMENTED YET"; + + } + + @Override + public String getResponseErrorCode(Throwable throwable) { + return "NOT IMPLEMENTED YET"; + + } + + @Override + public String mapInternalErrorToExternalError(String intErrorCode) { + return "NOT IMPLEMENTED YET"; + + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java new file mode 100644 index 00000000..e4d02dae --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java @@ -0,0 +1,138 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.storage; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; + +@Service("SimpleInMemoryTransactionStorage") +public class SimpleInMemoryTransactionStorage implements ITransactionStorage{ + private static final Logger log = LoggerFactory.getLogger(SimpleInMemoryTransactionStorage.class); + + private Map<String, TransactionStoreElement> storage = new ConcurrentHashMap<String, TransactionStoreElement>(); + + @Override + public void changeKey(String oldKey, String newKey, Object value) throws EAAFException { + if (containsKey(oldKey)) { + + + } else + throw new EAAFStorageException("No element in TransactionStorage with key: " + oldKey); + + } + + @Override + public List<String> clean(Date now, long dataTimeOut) { + List<String> result = new ArrayList<String>(); + Iterator<String> iterator = storage.keySet().iterator(); + while (iterator.hasNext()) { + String key = iterator.next(); + synchronized (storage) { + if (storage.containsKey(key)) { + TransactionStoreElement element = storage.get(key); + if (now.getTime() - element.getCreated().getTime() > dataTimeOut) + result.add(key); + } + } + } + + return result; + + } + + @Override + public boolean containsKey(String key) { + if (key != null) + return storage.containsKey(key); + else + return false; + + } + + @Override + public Object get(String key) throws EAAFException { + if (key != null && containsKey(key)) { + TransactionStoreElement element = storage.get(key); + return element.getData(); + + } else + return null; + } + + @Override + public <T> T get(String key, Class<T> type) throws EAAFException { + return get(key, type, -1); + + } + + @Override + public <T> T get(String key, Class<T> type, long dataTimeOut) throws EAAFException { + if (key != null && containsKey(key)) { + TransactionStoreElement value = storage.get(key); + + if (dataTimeOut > -1) { + long now = new Date().getTime(); + if (now - value.getCreated().getTime() > dataTimeOut) { + log.info("Transaction-Data with key: " + key + " is out of time."); + throw new EAAFStorageException("Transaction-Data with key: " + key + " is out of time."); + + } + } + + if (type.isAssignableFrom(value.getData().getClass())) { + return (T) value.getData(); + + } else + log.warn("Can NOT cast '" + value.getClass() + "' to '" + type + "'"); + + } + + return null; + } + + @Override + public Object getRaw(String key) throws EAAFException { + return storage.get(key); + + } + + @Override + public void put(String key, Object value, int dataTimeOut) throws EAAFException { + TransactionStoreElement element = new TransactionStoreElement(); + element.setKey(key); + element.setData(value); + storage.put(key, element); + + } + + @Override + public void putRaw(String key, Object value) throws EAAFException { + if (value instanceof TransactionStoreElement) + storage.put(((TransactionStoreElement) value).getKey(), (TransactionStoreElement) value); + else + log.info(value.getClass().getName() + " is NOT a RAW element of " + ITransactionStorage.class.getName()); + + } + + @Override + public void remove(String key) { + if (containsKey(key)) { + log.debug("Remove element with key: " + key + " from " + ITransactionStorage.class.getName()); + storage.remove(key); + + } + } + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/TransactionStoreElement.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/TransactionStoreElement.java new file mode 100644 index 00000000..a0224813 --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/storage/TransactionStoreElement.java @@ -0,0 +1,34 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.storage; + +import java.util.Date; + +public class TransactionStoreElement { + + private String key = null; + private Object data = null; + private Date created; + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public Date getCreated() { + return created; + } + public void setCreated(Date created) { + this.created = created; + } + + + +} diff --git a/connector/src/main/java/at/gv/egiz/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java new file mode 100644 index 00000000..ed88091b --- /dev/null +++ b/connector/src/main/java/at/gv/egiz/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java @@ -0,0 +1,136 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.connector.verification; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.xml.security.x509.BasicX509Credential; +import org.opensaml.xml.signature.SignatureValidator; +import org.opensaml.xml.validation.ValidationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; +import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.SAMLRequestNotSignedException; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.AbstractMetadataSignatureFilter; + +public class MetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter{ + private static final Logger log = LoggerFactory.getLogger(MetadataSignatureVerificationFilter.class); + + private String metadataURL; + private List<BasicX509Credential> trustedCredential = new ArrayList<BasicX509Credential>(); + + public MetadataSignatureVerificationFilter(String trustStorePath, String trustStorePassword, String metadataURL) + throws PVP2MetadataException { + this.metadataURL = metadataURL; + + log.trace("Initialize metadata signature-verification filter with truststore: " + trustStorePath + " ... "); + try { + KeyStore keyStore = KeyStoreUtils.loadKeyStore(trustStorePath, trustStorePassword); + if (keyStore != null) { + //load trusted certificates + Enumeration<String> aliases = keyStore.aliases(); + while(aliases.hasMoreElements()) { + String el = aliases.nextElement(); + log.trace("Process TrustStoreEntry: " + el); + if (keyStore.isCertificateEntry(el)) { + Certificate cert = keyStore.getCertificate(el); + if (cert != null && cert instanceof X509Certificate) { + BasicX509Credential trustedCert = new BasicX509Credential(); + trustedCert.setEntityCertificate((X509Certificate) cert); + this.trustedCredential.add(trustedCert); + log.debug("Add cert: " + ((X509Certificate) cert).getSubjectDN() + " as trusted for metadata: " + metadataURL); + + } else + log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); + + } + } + + + } + + } catch (KeyStoreException | IOException e) { + log.warn("Can not open trustStore: " + trustStorePath + " for metadata: " + metadataURL + " Reason: " + e.getMessage(), e); + throw new PVP2MetadataException("Can not open trustStore: " + trustStorePath + " for metadata", null, e); + + } + + + } + + + @Override + protected void verify(EntityDescriptor desc) throws PVP2MetadataException { + try { + internalVerify(desc); + + } catch (EAAFException e) { + log.info("Metadata verification FAILED for: " + metadataURL + " Reason: " +e.getMessage()); + throw new PVP2MetadataException("Metadata verification FAILED for: " + metadataURL + " Reason: " +e.getMessage(), null, e); + + } + } + + @Override + protected void verify(EntitiesDescriptor desc) throws PVP2MetadataException { + throw new PVP2MetadataException("EntitiesDescritors are NOT supported", null); + + } + + @Override + protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws PVP2MetadataException { + throw new PVP2MetadataException("EntitiesDescritors are NOT supported", null); + + } + + private void internalVerify(SignableSAMLObject signedElement) + throws EAAFException { + if (signedElement.getSignature() == null) { + throw new SAMLRequestNotSignedException(); + } + + try { + SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); + sigValidator.validate(signedElement.getSignature()); + } catch (ValidationException e) { + log.error("Failed to validate Signature", e); + throw new SAMLRequestNotSignedException(e); + } + + boolean isTrusted = false; + for (BasicX509Credential cred : trustedCredential) { + SignatureValidator sigValidator = new SignatureValidator(cred); + try { + sigValidator.validate(signedElement.getSignature()); + isTrusted = true; + + } catch (ValidationException e) { + log.info("Failed to verfiy Signature with cert: " + cred.getEntityCertificate().getSubjectDN() + + " Reason: " + e.getMessage()); + + } + } + + if (!isTrusted) { + log.warn("PVP2 metadata: " + metadataURL + " are NOT trusted!"); + throw new SAMLRequestNotSignedException(); + + } + + } + +} diff --git a/connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 00000000..fafe72f5 --- /dev/null +++ b/connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egiz.eidas.specific.connector.MSSpecificeIDASNodeSpringResourceProvider
\ No newline at end of file diff --git a/connector/src/main/resources/applicationContext.xml b/connector/src/main/resources/applicationContext.xml new file mode 100644 index 00000000..5ede0b7f --- /dev/null +++ b/connector/src/main/resources/applicationContext.xml @@ -0,0 +1,33 @@ +<?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" + xmlns:mvc="http://www.springframework.org/schema/mvc" + 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 + http://www.springframework.org/schema/mvc + http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/tx + http://www.springframework.org/schema/tx/spring-tx.xsd + " +> + + <context:annotation-config /> + <mvc:annotation-driven /> + + <mvc:default-servlet-handler/> + +<!-- <mvc:interceptors> + <bean class="at.gv.egovernment.moa.id.auth.servlet.interceptor.WebFrontEndSecurityInterceptor" /> + <bean class="at.gv.egovernment.moa.id.auth.servlet.interceptor.UniqueSessionIdentifierInterceptor" /> + </mvc:interceptors> --> + + <bean id="BasicMSSpecificNodeConfig" + class="at.gv.egiz.eidas.specific.connector.config.BasicConfigurationProvider"> + <constructor-arg value="#{systemProperties['eidas.ms.configuration']}"/> + </bean> + +</beans> diff --git a/connector/src/main/resources/config/default_config.properties b/connector/src/main/resources/config/default_config.properties new file mode 100644 index 00000000..9eb856b8 --- /dev/null +++ b/connector/src/main/resources/config/default_config.properties @@ -0,0 +1 @@ +eidas.ms.context.url.prefix=https://labda.iaik.tugraz.at:8443/ms_connector/
\ No newline at end of file diff --git a/connector/src/main/resources/specific_eIDAS_connector.beans.xml b/connector/src/main/resources/specific_eIDAS_connector.beans.xml new file mode 100644 index 00000000..1e61d0d6 --- /dev/null +++ b/connector/src/main/resources/specific_eIDAS_connector.beans.xml @@ -0,0 +1,81 @@ +<?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" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:mvc="http://www.springframework.org/schema/mvc" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + 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-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> + + <context:annotation-config /> + <mvc:annotation-driven /> + <mvc:default-servlet-handler/> + + <bean id="SimpleInMemoryTransactionStorage" + class="at.gv.egiz.eidas.specific.connector.storage.SimpleInMemoryTransactionStorage" /> + + <bean id="AuthenticationManager" + class="at.gv.egiz.eidas.specific.connector.auth.AuthenticationManager" /> + + <bean id="AuthenticationDataBuilder" + class="at.gv.egiz.eidas.specific.connector.builder.AuthenticationDataBuilder" /> + + <bean id="PVPEndPointConfiguration" + class="at.gv.egiz.eidas.specific.connector.config.PVPEndPointConfiguration"/> + + <bean id="PVPEndPointCredentialProvider" + class="at.gv.egiz.eidas.specific.connector.provider.PVPEndPointCredentialProvider" /> + + <bean id="PVPMetadataConfigurationFactory" + class="at.gv.egiz.eidas.specific.connector.provider.PVPMetadataConfigurationFactory" /> + + <bean id="PVP2XProtocol" + class="at.gv.egiz.eidas.specific.connector.controller.PVP2SProfileEndpoint"> + <property name="pvpIDPCredentials"> + <ref bean="PVPEndPointCredentialProvider" /> + </property> + </bean> + + <bean id="pvpMetadataService" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction"> + <property name="pvpIDPCredentials"> + <ref bean="PVPEndPointCredentialProvider" /> + </property> + </bean> + + <bean id="PVPAuthenticationRequestAction" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction"> + <property name="pvpIDPCredentials"> + <ref bean="PVPEndPointCredentialProvider" /> + </property> + </bean> + + <bean id="PVPMetadataProvider" + class="at.gv.egiz.eidas.specific.connector.provider.PVPMetadataProvider" /> + + <bean id="PVPSubjectNameGenerator" + class="at.gv.egiz.eidas.specific.connector.builder.PVPSubjectNameGenerator"/> + + <bean id="LoALevelMapper" + class="at.gv.egiz.eidas.specific.connector.mapper.LoALevelMapper"/> + + <bean id="GUIBuilderConfigurationFactory" + class="at.gv.egiz.eidas.specific.connector.gui.GUIBuilderConfigurationFactory" /> + + <bean id="DefaultGUIBuilderImpl" + class="at.gv.egiz.eidas.specific.connector.gui.DefaultGUIBuilderImpl"/> + + <bean id="StatusMessageProvider" + class="at.gv.egiz.eidas.specific.connector.provider.StatusMessageProvider" /> + + <bean id="DummyRevisionLogger" + class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> + + <bean id="DummyStatisticLogger" + class="at.gv.egiz.eaaf.core.impl.logging.DummyStatisticLogger" /> + +</beans>
\ No newline at end of file diff --git a/connector/src/main/webapp/WEB-INF/web.xml b/connector/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..d5425ad4 --- /dev/null +++ b/connector/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + <display-name>AT eIDAS connector</display-name> + <description>MS specific eIDAS connector to national eID infrastructure</description> + + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> + + <session-config> + <session-timeout>5</session-timeout> + </session-config> + + <error-page> + <error-code>500</error-code> + <location>/errorpage.jsp</location> + </error-page> + +</web-app> diff --git a/connector/src/main/webapp/index.html b/connector/src/main/webapp/index.html new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/connector/src/main/webapp/index.html diff --git a/eidas_modules/authmodule-eIDAS-v2/pom.xml b/eidas_modules/authmodule-eIDAS-v2/pom.xml new file mode 100644 index 00000000..48a5a249 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/pom.xml @@ -0,0 +1,124 @@ +<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>at.gv.egiz.eidas.ms_specific</groupId> + <artifactId>modules</artifactId> + <version>1.x</version> + </parent> + + <artifactId>authmodule-eIDAS-v2</artifactId> + <name>eIDAS v2 authentication module</name> + <version>${egiz.eidas.version}</version> + <description>eIDAS module based on eIDAS node reference implementation v2.x</description> + + <properties> + <eidas-commons.version>2.0.0</eidas-commons.version> + <eidas-light-commons.version>2.0.0</eidas-light-commons.version> + <eidas-specific-communication-definition.version>2.0.0</eidas-specific-communication-definition.version> + </properties> + + <profiles> + <profile> + <id>default</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>egiz-commons</id> + <url>https://demo.egiz.gv.at/int-repo/</url> + <releases> + <enabled>true</enabled> + </releases> + </repository> + </repositories> + </profile> + </profiles> + + <dependencies> + <dependency> + <groupId>at.gv.egiz.components</groupId> + <artifactId>egiz-spring-api</artifactId> + </dependency> + + + <!-- eIDAS reference implemenation libs --> + <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> + + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>eidas-light-commons</artifactId> + <version>${eidas-light-commons.version}</version> + </dependency> + + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>eidas-specific-communication-definition</artifactId> + <version>${eidas-specific-communication-definition.version}</version> + </dependency> + + <!-- other third party libs --> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-text</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <!-- enable co-existence of testng and junit --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <threadCount>1</threadCount> + <argLine>--add-modules java.xml.bind</argLine> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java new file mode 100644 index 00000000..de7d9100 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java @@ -0,0 +1,45 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Constants { + + //configuration properties + public static final String CONIG_PROPS_EIDAS_PREFIX="auth.eIDAS"; + public static final String CONIG_PROPS_EIDAS_NODE= CONIG_PROPS_EIDAS_PREFIX + ".node_v2"; + public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode"; + + + //http endpoint descriptions + public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/light/sp/post"; + public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/light/sp/redirect"; + public static final String eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST = "/eidas/light/ColleagueRequest"; + public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/light/metadata"; + + //eIDAS request parameters + public static final String eIDAS_REQ_NAMEID_FORMAT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"; + + //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 = "FirstName"; + public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "FamilyName"; + public static final String eIDAS_ATTR_LEGALPERSONIDENTIFIER = "LegalPersonIdentifier"; + public static final String eIDAS_ATTR_LEGALNAME = "LegalName"; + + public static final List<URI> NATURALPERSONMINIMUMDATASETLIST = Collections.unmodifiableList(new ArrayList<URI>() { + private static final long serialVersionUID = 1L; + { + //TODO: find correct location of attribute definitions +// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri()); +// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri()); +// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri()); +// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri()); + } + }); +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java new file mode 100644 index 00000000..1ce2f949 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java @@ -0,0 +1,52 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2; + +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_v2"; + else + return null; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:eIDAS.Authentication.process.xml" }; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java new file mode 100644 index 00000000..b491b8d8 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java @@ -0,0 +1,30 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +public class eIDASAuthenticationSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "Auth. module for eIDAS Ref. Impl. v2.x"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + ClassPathResource eIDASAuthConfig = new ClassPathResource("/eidas_v2_auth.beans", eIDASAuthenticationSpringResourceProvider.class); + + return new Resource[] {eIDASAuthConfig}; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java new file mode 100644 index 00000000..51d1bd0c --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java @@ -0,0 +1,82 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egovernment.moa.id.auth.servlet.AbstractProcessEngineSignalController; + +/** + * @author tlenz + * + */ +@Controller +public class eIDASSignalServlet extends AbstractProcessEngineSignalController { + + private static final Logger log = LoggerFactory.getLogger(eIDASSignalServlet.class); + + + public eIDASSignalServlet() { + super(); + log.debug("Registering servlet " + getClass().getName() + + " with mappings '"+ Constants.eIDAS_HTTP_ENDPOINT_SP_POST + + "' and '"+ Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT + "'."); + + } + + @RequestMapping(value = { Constants.eIDAS_HTTP_ENDPOINT_SP_POST, + Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT + }, + method = {RequestMethod.POST, RequestMethod.GET}) + public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException { + signalProcessManagement(req, resp); + } + + @Override + /** + * Protocol specific implementation to get the pending-requestID + * from http request object + * + * @param request The http Servlet-Request object + * @return The Pending-request id + * + */ + public String getPendingRequestId(HttpServletRequest request) { + String sessionId = super.getPendingRequestId(request); + + try { + + // use SAML2 relayState + if (sessionId == null) { + log.trace("No transaction identifier from pendingReq. Search for SAML2 'RelayState' ..."); + sessionId = StringEscapeUtils.escapeHtml4(request.getParameter("RelayState")); + + if (StringUtils.isEmpty(sessionId)) + log.info("NO transaction identifier found! Stopping process ...."); + else + log.debug("Find transaction identifier in SAML2 'RelayState': " + sessionId); + + + } else + log.trace("Find transaction identifier from pendingReq."); + + } catch (Exception e) { + log.warn("Unable to retrieve moa session id.", e); + + } + + return sessionId; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java new file mode 100644 index 00000000..dfd945c9 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java @@ -0,0 +1,160 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; + +import java.io.InputStream; +import java.text.SimpleDateFormat; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.joda.time.DateTime; +import org.springframework.stereotype.Component; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; +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.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; +import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; + +/** + * @author tlenz + * + */ +@Component("CreateIdentityLinkTask") +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{ + defaultTaskInitialization(request, executionContext); + + //get eIDAS attributes from MOA-Session + ImmutableAttributeMap eIDASAttributes = moasession.getGenericDataFromSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + ImmutableAttributeMap.class); + + IIdentityLink 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 fake baseID; + Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + + + Object eIdentifier = eIDASAttributes.getFirstValue( + SAMLEngineUtils.getMapOfAllAvailableAttributes().get( + Constants.eIDAS_ATTR_PERSONALIDENTIFIER)); + if (eIdentifier == null || !(eIdentifier instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + prIdentification.getFirstChild().setNodeValue((String) eIdentifier); + + //build personal identifier which looks like a baseID +// String fakeBaseID = new BPKBuilder().buildBPK(eIdentifier, "baseID"); +// Logger.info("Map eIDAS eIdentifier:" + eIdentifier + " to fake baseID:" + fakeBaseID); +// prIdentification.getFirstChild().setNodeValue(fakeBaseID); + + // - set last name + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + Object familyName = eIDASAttributes.getFirstValue( + SAMLEngineUtils.getMapOfAllAvailableAttributes().get( + Constants.eIDAS_ATTR_CURRENTFAMILYNAME)); + if (familyName == null || !(familyName instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + prFamilyName.getFirstChild().setNodeValue((String) familyName); + + // - set first name + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + Object givenName = eIDASAttributes.getFirstValue( + SAMLEngineUtils.getMapOfAllAvailableAttributes().get( + Constants.eIDAS_ATTR_CURRENTGIVENNAME)); + if (givenName == null || !(givenName instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + prGivenName.getFirstChild().setNodeValue((String) givenName); + + // - set date of birth + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + Object dateOfBirth = eIDASAttributes.getFirstValue( + SAMLEngineUtils.getMapOfAllAvailableAttributes().get( + Constants.eIDAS_ATTR_DATEOFBIRTH)); + if (dateOfBirth == null || !(dateOfBirth instanceof DateTime)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); + + String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirth).toDate()); + prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth); + + identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + + //resign IDL + IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); + Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.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); + } + + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED); + moasession.setForeigner(true); + moasession.setIdentityLink(identityLink); + moasession.setBkuURL("Not applicable (eIDASAuthentication)"); + + //store MOA-session to database + requestStoreage.storePendingRequest(pendingReq); + + } catch (eIDASAttributeException e) { + throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); + + } catch (MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } catch (Exception e) { + Logger.error("IdentityLink generation for foreign person FAILED.", e); + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java new file mode 100644 index 00000000..358b681e --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java @@ -0,0 +1,313 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import com.google.common.net.MediaType; + +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants; +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.commons.api.IRequest; +import at.gv.egovernment.moa.id.commons.api.data.CPEPS; +import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.EidasStringUtil; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; +import eu.eidas.auth.commons.light.impl.LightRequest; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.protocol.IRequestMessage; +import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance; +import eu.eidas.auth.commons.protocol.eidas.LevelOfAssuranceComparison; +import eu.eidas.auth.commons.protocol.eidas.SpType; +import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; + +/** + * @author tlenz + * + */ +@Component("GenerateAuthnRequestTask") +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{ + //get service-provider configuration + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + + // get target and validate citizen countryCode + 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("eIDAS.03", new Object[] { "" }); + + } + CPEPS cpeps = authConfig.getStorkConfig().getCPEPSWithFullName(citizenCountryCode); + if(null == cpeps) { + Logger.error("PEPS unknown for country: " + citizenCountryCode); + throw new AuthenticationException("eIDAS.04", new Object[] {citizenCountryCode}); + } + Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode); + + + //TODO: load authnReq End-Point URL from configuration + SingleSignOnService authnReqEndpoint = null; + + + //TODO: switch to entityID and set new status codes +// revisionsLogger.logEvent(oaConfig, pendingReq, +// MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED, +// metadataUrl); + + // assemble requested attributes + Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes(); + + // - prepare attribute list + + // - fill container + List<AttributeDefinition<?>> reqAttrList = new ArrayList<AttributeDefinition<?>>(); + //TODO: update requested attribute builder +// for (StorkAttribute current : attributesFromConfig) { +// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(current.getName()); +// +// if (newAttribute == null) { +// Logger.warn("eIDAS attribute with friendlyName:" + current.getName() + " is not supported."); +// +// } else { +// boolean globallyMandatory = false; +// for (StorkAttribute currentGlobalAttribute : authConfig.getStorkConfig().getStorkAttributes()) +// if (current.getName().equals(currentGlobalAttribute.getName())) { +// globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory()); +// break; +// } +// +// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(current.getMandatory() || globallyMandatory); +// reqAttrList.add(attrBuilder.build()); +// +// } +// } + + //request +// if (reqAttrList.isEmpty()) { +// Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix() +// + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default"); +// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); +// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true); +// reqAttrList.add(attrBuilder.build()); +// +// } + + //build requested attribute set + ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build(); + + //build eIDAS AuthnRequest + LightRequest.Builder authnRequestBuilder = LightRequest.builder(); + + authnRequestBuilder.id(UUID.randomUUID().toString()); + authnRequestBuilder.providerName(pendingReq.getAuthURL()); + String issur = pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA; + authnRequestBuilder.issuer(issur); + + //TODO: + //authnRequestBuilder.destination(authnReqEndpoint.getLocation()); + + + authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT); + + //set minimum required eIDAS LoA from OA config + String LoA = oaConfig.getQaaLevel(); + //TODO: +// if (MiscUtil.isNotEmpty(LoA)) +// authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel())); +// else + authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH.getValue()); + + //TODO: check if required + //authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM); + + + //set correct SPType for this online application + if (oaConfig.hasBaseIdTransferRestriction()) + authnRequestBuilder.spType(SpType.PRIVATE.getValue()); + else + authnRequestBuilder.spType(SpType.PUBLIC.getValue()); + + + //TODO + //set service provider (eIDAS node) countryCode +// authnRequestBuilder.serviceProviderCountryCode( +// authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT")); + + //set citizen country code for foreign uses + authnRequestBuilder.citizenCountryCode(cpeps.getCountryCode()); + + //add requested attributes + authnRequestBuilder.requestedAttributes(reqAttrMap); + + + LightRequest lightAuthnReq = authnRequestBuilder.build(); + + + + //IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur); + + //encode AuthnRequest +// byte[] token = authnRequest.getMessageBytes(); +// String SAMLRequest = EidasStringUtil.encodeToBase64(token); + + +// if (SAMLConstants.SAML2_POST_BINDING_URI.equals(authnReqEndpoint.getBinding())) +// buildPostBindingRequest(pendingReq, authnReqEndpoint, SAMLRequest, authnRequest, response); +// +// //TODO: redirect Binding is not completely implemented +// //else if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(authnReqEndpoint.getBinding())) +// //buildRedirecttBindingRequest(pendingReq, authnReqEndpoint, token, authnRequest, response); +// +// else { +// Logger.error("eIDAS-node use an unsupported binding (" +// + authnReqEndpoint.getBinding() + "). Request eIDAS node not possible."); +// throw new MOAIDException("eIDAS.02", new Object[]{"eIDAS-node use an unsupported binding"}); +// +// } + + + +// }catch (EIDASSAMLEngineException e){ +// throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", +// new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e)); + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e); + + } catch (Exception e) { + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + } + + /** + * Encode the eIDAS request with POST binding + * + * @param pendingReq + * @param authnReqEndpoint + * @param SAMLRequest + * @param authnRequest + * @param response + * @throws MOAIDException + */ + private void buildPostBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint, + String SAMLRequest, IRequestMessage authnRequest, HttpServletResponse response) + throws MOAIDException { + //send + try { + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm"); + VelocityContext context = new VelocityContext(); + + String actionType = "SAMLRequest"; + context.put(actionType, SAMLRequest); + context.put("RelayState", pendingReq.getRequestID()); + context.put("action", authnReqEndpoint.getLocation()); + + Logger.debug("Using SingleSignOnService url as action: " + authnReqEndpoint.getLocation()); + Logger.debug("Encoded " + actionType + " original: " + SAMLRequest); + + 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()); + + + byte[] content = writer.getBuffer().toString().getBytes("UTF-8"); + response.setContentType(MediaType.HTML_UTF_8.toString()); + response.setContentLength(content.length); + response.getOutputStream().write(content); + + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, + MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED, + authnRequest.getRequest().getId()); + + } catch (Exception e) { + Logger.error("Velocity general error: " + e.getMessage()); + throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e); + + } + + } + + /** + * Select a SingleSignOnService endPoint from eIDAS node metadata. + * This endPoint receives the Authn. request + * + * @param idpEntity + * @return + */ + private SingleSignOnService selectSingleSignOnServiceFromMetadata(EntityDescriptor idpEntity) { + //select SingleSignOn Service endpoint from IDP metadata + SingleSignOnService endpoint = null; + if (idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) == null) { + return null; + + } + + for (SingleSignOnService sss : + idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { + + // use POST binding as default if it exists + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) + endpoint = sss; + + //TODO: redirect Binding is not completely implemented + // use Redirect binding as backup +// else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) +// && endpoint == null ) +// endpoint = sss; + + } + + return endpoint; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java new file mode 100644 index 00000000..055c402f --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java @@ -0,0 +1,143 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.opensaml.saml2.core.StatusCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; +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.engine.MOAeIDASChainingMetadataProvider; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASResponseNotSuccessException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.EidasStringUtil; +import eu.eidas.auth.commons.protocol.IAuthenticationResponse; +import eu.eidas.auth.engine.ProtocolEngineI; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; + +@Component("ReceiveAuthnResponseTask") +public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { + + @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; + + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { + + try{ + //get SAML Response + 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); + + } + + //get MOASession + defaultTaskInitialization(request, executionContext); + + //decode SAML response + byte[] decSamlToken = EidasStringUtil.decodeBytesFromBase64(base64SamlToken); + + //get eIDAS SAML-engine + ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); + + //validate SAML token + IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken, + request.getRemoteHost(), + Constants.CONFIG_PROPS_SKEWTIME_BEFORE, + Constants.CONFIG_PROPS_SKEWTIME_AFTER, + pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); + + if (samlResp.isEncrypted()) { + Logger.info("Received encrypted eIDAS SAML-Response."); + //TODO: check if additional decryption operation is required + + } + + + //check response StatusCode + if (!samlResp.getStatusCode().equals(StatusCode.SUCCESS_URI)) { + Logger.info("Receice eIDAS Response with StatusCode:" + samlResp.getStatusCode() + + " Subcode:" + samlResp.getSubStatusCode() + " Msg:" + samlResp.getStatusMessage()); + throw new EIDASResponseNotSuccessException("eIDAS.11", new Object[]{samlResp.getStatusMessage()}); + + } + + // ********************************************************** + // ******* MOA-ID specific response validation ********** + // ********************************************************** + String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"); + eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry); + + + // ********************************************************** + // ******* Store resonse infos into session object ********** + // ********************************************************** + + //update MOA-Session data with received information + Logger.debug("Store eIDAS response information into MOA-session."); + + moasession.setQAALevel(samlResp.getLevelOfAssurance()); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + samlResp.getAttributes()); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_RESPONSE, + decSamlToken); + + //set issuer nation as PVP attribute into MOASession + moasession.setGenericDataToSession(PVPConstants.EID_ISSUING_NATION_NAME, samlResp.getCountry()); + + //store MOA-session to database + requestStoreage.storePendingRequest(pendingReq); + + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, + MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED, + samlResp.getId()); + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e); + + }catch (EIDASSAMLEngineException e) { + Logger.warn("eIDAS Response validation FAILED.", e); + Logger.debug("eIDAS response was: " + request.getParameter("SAMLResponse")); + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, + MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); + throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", + new EIDASEngineException("eIDAS.09", new Object[]{e.getMessage()}, e)); + + } catch (MOADatabaseException e) { + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, + MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); + throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", + new MOAIDException("init.04", new Object[]{""}, e)); + + } catch (Exception e) { + Logger.warn("eIDAS Response processing FAILED.", e); + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, + MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); + throw new TaskExecutionException(pendingReq, e.getMessage(), + new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e)); + + } + + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 00000000..f5af2dc4 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.eIDASAuthenticationSpringResourceProvider
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml new file mode 100644 index 00000000..958c3391 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition id="eIDASAuthentication_v2" + xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"> + + + <pd:Task id="createAuthnRequest" class="GenerateAuthnRequestTask" /> + <pd:Task id="receiveAuthnResponse" class="ReceiveAuthnResponseTask" + async="true" /> + <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" /> + <pd:Task id="generateIdentityLink" class="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/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml new file mode 100644 index 00000000..1ad8cbeb --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml @@ -0,0 +1,34 @@ +<?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" + xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + 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-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <context:annotation-config /> + + <bean id="eIDASAuthModule" + class="at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.eIDASAuthenticationModulImpl"> + <property name="priority" value="2" /> + </bean> + + <bean id="eIDASSignalServlet" + class="at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.eIDASSignalServlet" /> + + + <!-- Authentication Process Tasks --> + <bean id="GenerateAuthnRequestTask" + class="at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks.GenerateAuthnRequestTask" + scope="prototype" /> + + <bean id="ReceiveAuthnResponseTask" + class="at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks.ReceiveAuthnResponseTask" + scope="prototype" /> + + <bean id="CreateIdentityLinkTask" + class="at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks.CreateIdentityLinkTask" + scope="prototype" /> + +</beans>
\ No newline at end of file diff --git a/eidas_modules/pom.xml b/eidas_modules/pom.xml new file mode 100644 index 00000000..2111af3a --- /dev/null +++ b/eidas_modules/pom.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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>at.gv.egiz.eidas</groupId> + <artifactId>ms_specific</artifactId> + <version>1.x</version> + </parent> + + <groupId>at.gv.egiz.eidas.ms_specific</groupId> + <artifactId>modules</artifactId> + <packaging>pom</packaging> + + <name>Modules for MS specific eIDAS Node</name> + + <modules> + <!-- <module>authmodule-eIDAS-v2</module> --> + </modules> + + +</project>
\ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..f6b400b9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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> + <groupId>at.gv.egiz.eidas</groupId> + <artifactId>ms_specific</artifactId> + <version>1.x</version> + <packaging>pom</packaging> + + <name>MS specific eIDAS components</name> + + <properties> + <!-- Project versions--> + <egiz.eidas.version>1.0.0-SNAPSHOT</egiz.eidas.version> + + + <!-- ===================================================================== --> + <egiz-spring-api>0.1</egiz-spring-api> + <eaaf-core.version>1.0.0-snapshot</eaaf-core.version> + + <!-- <org.springframework.version>5.0.6.RELEASE</org.springframework.version> --> + <org.springframework.version>4.3.17.RELEASE</org.springframework.version> + + <org.apache.commons-lang3.version>3.7</org.apache.commons-lang3.version> + <org.apache.commons-text.version>1.3</org.apache.commons-text.version> + <surefire.version>2.20.1</surefire.version> + <org.slf4j.version>1.7.25</org.slf4j.version> + + </properties> + + <profiles> + <profile> + <id>default</id> + <activation> + <activeByDefault>true</activeByDefault> + <property> + <name>default</name> + </property> + </activation> + <repositories> + <repository> + <id>egiz-commons</id> + <url>http://demo.egiz.gv.at/int-repo/</url> + <releases> + <enabled>true</enabled> + </releases> + </repository> + + </repositories> + </profile> + </profiles> + + <modules> + <module>connector</module> + <module>eidas_modules</module> + </modules> + + <dependencyManagement> + <dependencies> + <!-- Web application --> + <dependency> + <groupId>at.gv.egiz.components</groupId> + <artifactId>egiz-spring-api</artifactId> + <version>${egiz-spring-api}</version> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <version>${eaaf-core.version}</version> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_module_pvp2_idp</artifactId> + <version>${eaaf-core.version}</version> + </dependency> + + + <!-- Third party libs --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + <version>${org.springframework.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${org.slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${org.slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${org.apache.commons-lang3.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-text</artifactId> + <version>${org.apache.commons-text.version}</version> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + + + <!-- Testing --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <build> + <finalName>ms-specific_eidas_node</finalName> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.7.0</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <!-- enable co-existence of testng and junit --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + <argLine>--add-modules java.xml.bind</argLine> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </pluginManagement> + </build> + +</project>
\ No newline at end of file |