From cea2f395ec773b386ec628d60120752cf320f6b6 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 27 Jan 2014 16:27:02 +0100 Subject: add PVP2 Demo Application change SZRGWClient to JAXWs --- .../egovernment/moa/id/demoOA/Configuration.java | 243 ++++++++++++++++++ .../at/gv/egovernment/moa/id/demoOA/Constants.java | 9 + .../gv/egovernment/moa/id/demoOA/PVPConstants.java | 230 +++++++++++++++++ .../demoOA/exception/ConfigurationException.java | 20 ++ .../moa/id/demoOA/servlet/pvp2/Authenticate.java | 222 ++++++++++++++++ .../moa/id/demoOA/servlet/pvp2/BuildMetadata.java | 279 +++++++++++++++++++++ .../id/demoOA/servlet/pvp2/DemoApplication.java | 264 +++++++++++++++++++ .../moa/id/demoOA/utils/ApplicationBean.java | 93 +++++++ .../moa/id/demoOA/utils/AttributeListBuilder.java | 57 +++++ .../demoOA/utils/MetaDataVerificationFilter.java | 54 ++++ .../moa/id/demoOA/utils/SAML2Utils.java | 87 +++++++ id/oa/src/main/resources/defaultConfig.properties | 20 ++ .../templates/pvp_postbinding_template.html | 51 ++++ id/oa/src/main/webapp/WEB-INF/web.xml | 36 ++- id/oa/src/main/webapp/auth.jsp | 48 ---- id/oa/src/main/webapp/chooseBKU.jsp | 19 -- id/oa/src/main/webapp/css/index.css | 205 +++++++++++++++ id/oa/src/main/webapp/demoapp.jsp | 73 ++++++ id/oa/src/main/webapp/form.jsp | 20 -- id/oa/src/main/webapp/getBKUSelectTag.jsp | 6 - id/oa/src/main/webapp/index.jsp | 60 ----- id/oa/src/main/webapp/js/common.js | 32 +++ id/oa/src/main/webapp/stateful_login.jsp | 29 --- 23 files changed, 1974 insertions(+), 183 deletions(-) create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Configuration.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/PVPConstants.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/exception/ConfigurationException.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/AttributeListBuilder.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/MetaDataVerificationFilter.java create mode 100644 id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/SAML2Utils.java create mode 100644 id/oa/src/main/resources/defaultConfig.properties create mode 100644 id/oa/src/main/resources/templates/pvp_postbinding_template.html delete mode 100644 id/oa/src/main/webapp/auth.jsp delete mode 100644 id/oa/src/main/webapp/chooseBKU.jsp create mode 100644 id/oa/src/main/webapp/css/index.css create mode 100644 id/oa/src/main/webapp/demoapp.jsp delete mode 100644 id/oa/src/main/webapp/form.jsp delete mode 100644 id/oa/src/main/webapp/getBKUSelectTag.jsp delete mode 100644 id/oa/src/main/webapp/index.jsp create mode 100644 id/oa/src/main/webapp/js/common.js delete mode 100644 id/oa/src/main/webapp/stateful_login.jsp (limited to 'id/oa/src/main') diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Configuration.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Configuration.java new file mode 100644 index 000000000..0ca5464a7 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Configuration.java @@ -0,0 +1,243 @@ +package at.gv.egovernment.moa.id.demoOA; + + +import iaik.x509.X509Certificate; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.Properties; +import java.util.Timer; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.httpclient.HttpClient; +import org.opensaml.DefaultBootstrap; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.security.x509.BasicX509Credential; + +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.MetaDataVerificationFilter; +import at.iaik.commons.util.MiscUtil; + + +public class Configuration { + + private Properties props; + private static final String SYSTEM_PROP_CONFIG = "moa.id.demoOA"; + + private HTTPMetadataProvider idpMetadataProvider = null; + private boolean pvp2logininitialzied = false; + + private String publicURLPreFix = null; + private KeyStore keyStore = null; + + private static Configuration instance = null; + + public static Configuration getInstance() throws ConfigurationException { + if (instance == null) { + instance = new Configuration(); + + } + + return instance; + } + + public String getPublicUrlPreFix(HttpServletRequest request) { + publicURLPreFix = props.getProperty("general.publicURLContext"); + + if (MiscUtil.isEmpty(publicURLPreFix) && request != null) { + String url = request.getRequestURL().toString(); + String contextpath = request.getContextPath(); + int index = url.indexOf(contextpath); + publicURLPreFix = url.substring(0, index + contextpath.length() + 1); + } + + return publicURLPreFix; + } + + public KeyStore getPVP2KeyStore() throws ConfigurationException { + + try { + if (keyStore == null) { + String keystoretype = getPVP2MetadataKeystoreType(); + if (MiscUtil.isEmpty(keystoretype)) { + keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + + } else { + keyStore = KeyStore.getInstance(keystoretype); + + } + + + String file = getPVP2MetadataKeystoreURL(); + if (MiscUtil.isEmpty(file)) { + throw new ConfigurationException("KeyStoreURL is empty"); + } + + FileInputStream inputStream = new FileInputStream(file); + keyStore.load(inputStream, getPVP2MetadataKeystorePassword().toCharArray()); + inputStream.close(); + } + + return keyStore; + + } catch (Exception e){ + throw new ConfigurationException("KeyStore intialization FAILED", e); + + } + + } + + public String getPVP2LoginEntityName() { + return props.getProperty("general.login.pvp2.OA.metadata.entity.name"); + } + + public String getPVP2MetadataEntitiesName() { + return props.getProperty("general.login.pvp2.OA.metadata.entities.name"); + } + + public String getPVP2MetadataKeystoreURL() { + return props.getProperty("general.login.pvp2.OA.keystore.url"); + } + + public String getPVP2MetadataKeystorePassword() { + return props.getProperty("general.login.pvp2.OA.keystore.password"); + } + + public String getPVP2MetadataKeystoreType() { + return props.getProperty("general.login.pvp2.OA.keystore.type"); + } + + public String getPVP2KeystoreMetadataKeyAlias() { + return props.getProperty("general.login.pvp2.OA.keystore.metadata.sign.key.alias"); + } + + public String getPVP2KeystoreMetadataKeyPassword() { + return props.getProperty("general.login.pvp2.OA.keystore.metadata.sign.key.password"); + } + + public String getPVP2KeystoreAuthRequestKeyAlias() { + return props.getProperty("general.login.pvp2.keystore.authrequest.sign.key.alias"); + } + + public String getPVP2KeystoreAuthRequestKeyPassword() { + return props.getProperty("general.login.pvp2.keystore.authrequest.sign.key.password"); + } + + public String getPVP2KeystoreAuthRequestEncryptionKeyAlias() { + return props.getProperty("general.login.pvp2.keystore.assertion.encryption.key.alias"); + } + + public String getPVP2KeystoreAuthRequestEncryptionKeyPassword() { + return props.getProperty("general.login.pvp2.keystore.assertion.encryption.key.password"); + } + + public String getPVP2IDPMetadataURL() { + return props.getProperty("general.login.pvp2.idp.metadata.url"); + } + + public String getPVP2IDPMetadataCertificate() { + return props.getProperty("general.login.pvp2.idp.metadata.certificate"); + } + + public String getPVP2IDPMetadataEntityName() { + return props.getProperty("general.login.pvp2.idp.metadata.entityID"); + } + + + public void initializePVP2Login() throws ConfigurationException { + if (!pvp2logininitialzied) + initalPVP2Login(); + + } + + public HTTPMetadataProvider getMetaDataProvier() throws ConfigurationException { + + if (!pvp2logininitialzied) + initalPVP2Login(); + + return idpMetadataProvider; + } + + + private Configuration() throws ConfigurationException { + inizialize(); + } + + private void inizialize() throws ConfigurationException { + + String configFileName = System.getProperty(SYSTEM_PROP_CONFIG); + + if (configFileName == null) { + throw new ConfigurationException("No DemoOA configuration found."); + } + + File propertiesFile = new File(configFileName); + FileInputStream fis; + props = new Properties(); + + try { + + fis = new FileInputStream(propertiesFile); + props.load(fis); + + fis.close(); + + DefaultBootstrap.bootstrap(); + + } catch ( FileNotFoundException e) { + throw new ConfigurationException("DemoOA configuration is not found at " + configFileName); + + + } catch (IOException e) { + throw new ConfigurationException("DemoOA configuration can not be read from file " + configFileName); + + } catch (org.opensaml.xml.ConfigurationException e) { + throw new ConfigurationException("OpenSAML library initialization FAILED"); + + } + } + + private void initalPVP2Login() throws ConfigurationException { + try { + + String metadataCert = getPVP2IDPMetadataCertificate(); + if (MiscUtil.isEmpty(metadataCert)) { + throw new ConfigurationException("NO IDP Certificate to verify IDP Metadata"); + } + + InputStream certstream = new FileInputStream(metadataCert); + X509Certificate cert = new X509Certificate(certstream); + BasicX509Credential idpCredential = new BasicX509Credential(); + idpCredential.setEntityCertificate(cert); + + + String metadataurl = getPVP2IDPMetadataURL(); + if (MiscUtil.isEmpty(metadataurl)) { + throw new ConfigurationException("NO IDP Metadata URL."); + } + + idpMetadataProvider = new HTTPMetadataProvider(new Timer(), new HttpClient(), metadataurl); + idpMetadataProvider.setRequireValidMetadata(true); + idpMetadataProvider.setParserPool(new BasicParserPool()); + idpMetadataProvider.setMetadataFilter(new MetaDataVerificationFilter(idpCredential)); + idpMetadataProvider.setMaxRefreshDelay(1000 * 3600 * 12 ); //refresh Metadata every 12h + idpMetadataProvider.initialize(); + + pvp2logininitialzied = true; + + } catch (Exception e) { + throw new ConfigurationException("PVP2 authentification can not be initialized.", e); + } + } + + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java new file mode 100644 index 000000000..1f5d4871b --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java @@ -0,0 +1,9 @@ +package at.gv.egovernment.moa.id.demoOA; + +public class Constants { + public static final String FILEPREFIX = "file:"; + + public static final String SERVLET_PVP2ASSERTION = "demoapplication"; + + public static final String SESSION_PVP2REQUESTID = "pvp2requestid"; +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/PVPConstants.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/PVPConstants.java new file mode 100644 index 000000000..facc2feb2 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/PVPConstants.java @@ -0,0 +1,230 @@ +package at.gv.egovernment.moa.id.demoOA; + +public interface PVPConstants { + public static final String URN_OID_PREFIX = "urn:oid:"; + + public static final String PVP_VERSION_OID = "1.2.40.0.10.2.1.1.261.10"; + public static final String PVP_VERSION_NAME = URN_OID_PREFIX + PVP_VERSION_OID; + public static final String PVP_VERSION_FRIENDLY_NAME = "PVP-VERSION"; + public static final String PVP_VERSION_2_1 = "2.1"; + + public static final String SECCLASS_FRIENDLY_NAME = "SECCLASS"; + + public static final String PRINCIPAL_NAME_OID = "1.2.40.0.10.2.1.1.261.20"; + public static final String PRINCIPAL_NAME_NAME = URN_OID_PREFIX + PRINCIPAL_NAME_OID; + public static final String PRINCIPAL_NAME_FRIENDLY_NAME = "PRINCIPAL-NAME"; + public static final int PRINCIPAL_NAME_MAX_LENGTH = 128; + + public static final String GIVEN_NAME_OID = "2.5.4.42"; + public static final String GIVEN_NAME_NAME = URN_OID_PREFIX + GIVEN_NAME_OID; + public static final String GIVEN_NAME_FRIENDLY_NAME = "GIVEN-NAME"; + public static final int GIVEN_NAME_MAX_LENGTH = 128; + + public static final String BIRTHDATE_OID = "1.2.40.0.10.2.1.1.55"; + public static final String BIRTHDATE_NAME = URN_OID_PREFIX + BIRTHDATE_OID; + public static final String BIRTHDATE_FRIENDLY_NAME = "BIRTHDATE"; + public static final String BIRTHDATE_FORMAT_PATTERN = "yyyy-MM-dd"; + + public static final String USERID_OID = "0.9.2342.19200300.100.1.1"; + public static final String USERID_NAME = URN_OID_PREFIX + USERID_OID; + public static final String USERID_FRIENDLY_NAME = "USERID"; + public static final int USERID_MAX_LENGTH = 128; + + public static final String GID_OID = "1.2.40.0.10.2.1.1.1"; + public static final String GID_NAME = URN_OID_PREFIX + GID_OID; + public static final String GID_FRIENDLY_NAME = "GID"; + public static final int GID_MAX_LENGTH = 128; + + public static final String BPK_OID = "1.2.40.0.10.2.1.1.149"; + public static final String BPK_NAME = URN_OID_PREFIX + BPK_OID; + public static final String BPK_FRIENDLY_NAME = "BPK"; + public static final int BPK_MAX_LENGTH = 1024; + + public static final String ENC_BPK_LIST_OID = "1.2.40.0.10.2.1.1.261.22"; + public static final String ENC_BPK_LIST_NAME = URN_OID_PREFIX+ENC_BPK_LIST_OID; + public static final String ENC_BPK_LIST_FRIENDLY_NAME = "ENC-BPK-LIST"; + public static final int ENC_BPK_LIST_MAX_LENGTH = 32767; + + public static final String MAIL_OID = "0.9.2342.19200300.100.1.3"; + public static final String MAIL_NAME = URN_OID_PREFIX + MAIL_OID; + public static final String MAIL_FRIENDLY_NAME = "MAIL"; + public static final int MAIL_MAX_LENGTH = 128; + + public static final String TEL_OID = "2.5.4.20"; + public static final String TEL_NAME = URN_OID_PREFIX + TEL_OID; + public static final String TEL_FRIENDLY_NAME = "TEL"; + public static final int TEL_MAX_LENGTH = 32; + + public static final String PARTICIPANT_ID_OID = "1.2.40.0.10.2.1.1.71"; + public static final String PARTICIPANT_ID_NAME = URN_OID_PREFIX + PARTICIPANT_ID_OID; + public static final String PARTICIPANT_ID_FRIENDLY_NAME = "PARTICIPANT-ID"; + public static final int PARTICIPANT_MAX_LENGTH = 39; + + public static final String PARTICIPANT_OKZ_OID = "1.2.40.0.10.2.1.1.261.24"; + public static final String PARTICIPANT_OKZ_NAME = URN_OID_PREFIX + PARTICIPANT_OKZ_OID; + public static final String PARTICIPANT_OKZ_FRIENDLY_NAME = "PARTICIPANT-OKZ"; + public static final int PARTICIPANT_OKZ_MAX_LENGTH = 32; + + public static final String OU_OKZ_OID = "1.2.40.0.10.2.1.1.153"; + public static final String OU_OKZ_NAME = URN_OID_PREFIX + OU_OKZ_OID; + public static final int OU_OKZ_MAX_LENGTH = 32; + + public static final String OU_GV_OU_ID_OID = "1.2.40.0.10.2.1.1.3"; + public static final String OU_GV_OU_ID_NAME = URN_OID_PREFIX + OU_GV_OU_ID_OID; + public static final String OU_GV_OU_ID_FRIENDLY_NAME = "OU-GV-OU-ID"; + public static final int OU_GV_OU_ID_MAX_LENGTH = 39; + + public static final String OU_OID = "2.5.4.11"; + public static final String OU_NAME = URN_OID_PREFIX + OU_OID; + public static final String OU_FRIENDLY_NAME = "OU"; + public static final int OU_MAX_LENGTH = 64; + + public static final String FUNCTION_OID = "1.2.40.0.10.2.1.1.33"; + public static final String FUNCTION_NAME = URN_OID_PREFIX + FUNCTION_OID; + public static final String FUNCTION_FRIENDLY_NAME = "FUNCTION"; + public static final int FUNCTION_MAX_LENGTH = 32; + + public static final String ROLES_OID = "1.2.40.0.10.2.1.1.261.30"; + public static final String ROLES_NAME = URN_OID_PREFIX + ROLES_OID; + public static final String ROLES_FRIENDLY_NAME = "ROLES"; + public static final int ROLES_MAX_LENGTH = 32767; + + public static final String EID_CITIZEN_QAA_LEVEL_OID = "1.2.40.0.10.2.1.1.261.94"; + public static final String EID_CITIZEN_QAA_LEVEL_NAME = URN_OID_PREFIX + EID_CITIZEN_QAA_LEVEL_OID; + public static final String EID_CITIZEN_QAA_LEVEL_FRIENDLY_NAME = "EID-CITIZEN-QAA-LEVEL"; + + public static final String EID_ISSUING_NATION_OID = "1.2.40.0.10.2.1.1.261.32"; + public static final String EID_ISSUING_NATION_NAME = URN_OID_PREFIX + EID_ISSUING_NATION_OID; + public static final String EID_ISSUING_NATION_FRIENDLY_NAME = "EID-ISSUING-NATION"; + public static final int EID_ISSUING_NATION_MAX_LENGTH = 2; + + public static final String EID_SECTOR_FOR_IDENTIFIER_OID = "1.2.40.0.10.2.1.1.261.34"; + public static final String EID_SECTOR_FOR_IDENTIFIER_NAME = URN_OID_PREFIX + EID_SECTOR_FOR_IDENTIFIER_OID; + public static final String EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME = "EID-SECTOR-FOR-IDENTIFIER"; + public static final int EID_SECTOR_FOR_IDENTIFIER_MAX_LENGTH = 255; + + public static final String EID_SOURCE_PIN_OID = "1.2.40.0.10.2.1.1.261.36"; + public static final String EID_SOURCE_PIN_NAME = URN_OID_PREFIX + EID_SOURCE_PIN_OID; + public static final String EID_SOURCE_PIN_FRIENDLY_NAME = "EID-SOURCE-PIN"; + public static final int EID_SOURCE_PIN_MAX_LENGTH = 128; + + public static final String EID_SOURCE_PIN_TYPE_OID = "1.2.40.0.10.2.1.1.261.104"; + public static final String EID_SOURCE_PIN_TYPE_NAME = URN_OID_PREFIX + EID_SOURCE_PIN_TYPE_OID; + public static final String EID_SOURCE_PIN_TYPE_FRIENDLY_NAME = "EID-SOURCE-PIN-TYPE"; + public static final int EID_SOURCE_PIN_TYPE_MAX_LENGTH = 128; + + public static final String EID_IDENTITY_LINK_OID = "1.2.40.0.10.2.1.1.261.38"; + public static final String EID_IDENTITY_LINK_NAME = URN_OID_PREFIX + EID_IDENTITY_LINK_OID; + public static final String EID_IDENTITY_LINK_FRIENDLY_NAME = "EID-IDENTITY-LINK"; + public static final int EID_IDENTITY_LINK_MAX_LENGTH = 32767; + + public static final String EID_AUTH_BLOCK_OID = "1.2.40.0.10.2.1.1.261.62"; + public static final String EID_AUTH_BLOCK_NAME = URN_OID_PREFIX + EID_AUTH_BLOCK_OID; + public static final String EID_AUTH_BLOCK_FRIENDLY_NAME = "EID-AUTH-BLOCK"; + public static final int EID_AUTH_BLOCK_MAX_LENGTH = 32767; + + public static final String EID_CCS_URL_OID = "1.2.40.0.10.2.1.1.261.64"; + public static final String EID_CCS_URL_NAME = URN_OID_PREFIX + EID_CCS_URL_OID; + public static final String EID_CCS_URL_FRIENDLY_NAME = "EID-CCS-URL"; + public static final int EID_CCS_URL_MAX_LENGTH = 1024; + + public static final String EID_SIGNER_CERTIFICATE_OID = "1.2.40.0.10.2.1.1.261.66"; + public static final String EID_SIGNER_CERTIFICATE_NAME = URN_OID_PREFIX + EID_SIGNER_CERTIFICATE_OID; + public static final String EID_SIGNER_CERTIFICATE_FRIENDLY_NAME = "EID-SIGNER-CERTIFICATE"; + public static final int EID_SIGNER_CERTIFICATE_MAX_LENGTH = 32767; + + public static final String EID_STORK_TOKEN_OID = "1.2.40.0.10.2.1.1.261.96"; + public static final String EID_STORK_TOKEN_NAME = URN_OID_PREFIX + EID_STORK_TOKEN_OID; + public static final String EID_STORK_TOKEN_FRIENDLY_NAME = "EID-STORK-TOKEN"; + public static final int EID_STORK_TOKEN_MAX_LENGTH = 32767; + + public static final String MANDATE_TYPE_OID = "1.2.40.0.10.2.1.1.261.68"; + public static final String MANDATE_TYPE_NAME = URN_OID_PREFIX + MANDATE_TYPE_OID; + public static final String MANDATE_TYPE_FRIENDLY_NAME = "MANDATE-TYPE"; + public static final int MANDATE_TYPE_MAX_LENGTH = 256; + + public static final String MANDATE_NAT_PER_SOURCE_PIN_OID = "1.2.40.0.10.2.1.1.261.70"; + public static final String MANDATE_NAT_PER_SOURCE_PIN_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_SOURCE_PIN_OID; + public static final String MANDATE_NAT_PER_SOURCE_PIN_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-SOURCE-PIN"; + public static final int MANDATE_NAT_PER_SOURCE_PIN_MAX_LENGTH = 128; + + public static final String MANDATE_LEG_PER_SOURCE_PIN_OID = "1.2.40.0.10.2.1.1.261.100"; + public static final String MANDATE_LEG_PER_SOURCE_PIN_NAME = URN_OID_PREFIX + MANDATE_LEG_PER_SOURCE_PIN_OID; + public static final String MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME = "MANDATOR-LEGAL-PERSON-SOURCE-PIN"; + public static final int MANDATE_LEG_PER_SOURCE_PIN_MAX_LENGTH = 128; + + public static final String MANDATE_NAT_PER_SOURCE_PIN_TYPE_OID = "1.2.40.0.10.2.1.1.261.102"; + public static final String MANDATE_NAT_PER_SOURCE_PIN_TYPE_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_SOURCE_PIN_TYPE_OID; + public static final String MANDATE_NAT_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-SOURCE-PIN-TYPE"; + public static final int MANDATE_NAT_PER_SOURCE_PIN_TYPE_MAX_LENGTH = 128; + + public static final String MANDATE_LEG_PER_SOURCE_PIN_TYPE_OID = "1.2.40.0.10.2.1.1.261.76"; + public static final String MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME = URN_OID_PREFIX + MANDATE_LEG_PER_SOURCE_PIN_TYPE_OID; + public static final String MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME = "MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE"; + public static final int MANDATE_LEG_PER_SOURCE_PIN_TYPE_MAX_LENGTH = 128; + + public static final String MANDATE_NAT_PER_BPK_OID = "1.2.40.0.10.2.1.1.261.98"; + public static final String MANDATE_NAT_PER_BPK_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_BPK_OID; + public static final String MANDATE_NAT_PER_BPK_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-BPK"; + public static final int MANDATE_NAT_PER_BPK_MAX_LENGTH = 1024; + + public static final String MANDATE_NAT_PER_ENC_BPK_LIST_OID = "1.2.40.0.10.2.1.1.261.72"; + public static final String MANDATE_NAT_PER_ENC_BPK_LIST_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_ENC_BPK_LIST_OID; + public static final String MANDATE_NAT_PER_ENC_BPK_LIST_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-ENC-BPK-LIST"; + public static final int MANDATE_NAT_PER_ENC_BPK_LIST_MAX_LENGTH = 32767; + + public static final String MANDATE_NAT_PER_GIVEN_NAME_OID = "1.2.40.0.10.2.1.1.261.78"; + public static final String MANDATE_NAT_PER_GIVEN_NAME_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_GIVEN_NAME_OID; + public static final String MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-GIVEN-NAME"; + public static final int MANDATE_NAT_PER_GIVEN_NAME_MAX_LENGTH = 128; + + public static final String MANDATE_NAT_PER_FAMILY_NAME_OID = "1.2.40.0.10.2.1.1.261.80"; + public static final String MANDATE_NAT_PER_FAMILY_NAME_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_FAMILY_NAME_OID; + public static final String MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-FAMILY-NAME"; + public static final int MANDATE_NAT_PER_FAMILY_NAME_MAX_LENGTH = 128; + + public static final String MANDATE_NAT_PER_BIRTHDATE_OID = "1.2.40.0.10.2.1.1.261.82"; + public static final String MANDATE_NAT_PER_BIRTHDATE_NAME = URN_OID_PREFIX + MANDATE_NAT_PER_BIRTHDATE_OID; + public static final String MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME = "MANDATOR-NATURAL-PERSON-BIRTHDATE"; + public static final String MANDATE_NAT_PER_BIRTHDATE_FORMAT_PATTERN = BIRTHDATE_FORMAT_PATTERN; + + public static final String MANDATE_LEG_PER_FULL_NAME_OID = "1.2.40.0.10.2.1.1.261.84"; + public static final String MANDATE_LEG_PER_FULL_NAME_NAME = URN_OID_PREFIX + MANDATE_LEG_PER_FULL_NAME_OID; + public static final String MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME = "MANDATOR-LEGAL-PERSON-FULL-NAME"; + public static final int MANDATE_LEG_PER_FULL_NAME_MAX_LENGTH = 256; + + public static final String MANDATE_PROF_REP_OID_OID = "1.2.40.0.10.2.1.1.261.86"; + public static final String MANDATE_PROF_REP_OID_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_OID_OID; + public static final String MANDATE_PROF_REP_OID_FRIENDLY_NAME = "MANDATOR-PROF-REP-OID"; + public static final int MANDATE_PROF_REP_OID_MAX_LENGTH = 256; + + public static final String MANDATE_PROF_REP_DESC_OID = "1.2.40.0.10.2.1.1.261.88"; + public static final String MANDATE_PROF_REP_DESC_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_DESC_OID; + public static final String MANDATE_PROF_REP_DESC_FRIENDLY_NAME = "MANDATOR-PROF-REP-DESCRIPTION"; + public static final int MANDATE_PROF_REP_DESC_MAX_LENGTH = 1024; + + public static final String MANDATE_REFERENCE_VALUE_OID = "1.2.40.0.10.2.1.1.261.90"; + public static final String MANDATE_REFERENCE_VALUE_NAME = URN_OID_PREFIX + MANDATE_REFERENCE_VALUE_OID; + public static final String MANDATE_REFERENCE_VALUE_FRIENDLY_NAME = "MANDATE-REFERENCE-VALUE"; + public static final int MANDATE_REFERENCE_VALUE_MAX_LENGTH = 100; + + public static final String MANDATE_FULL_MANDATE_OID = "1.2.40.0.10.2.1.1.261.92"; + public static final String MANDATE_FULL_MANDATE_NAME = URN_OID_PREFIX + MANDATE_FULL_MANDATE_OID; + public static final String MANDATE_FULL_MANDATE_FRIENDLY_NAME = "MANDATE-FULL-MANDATE"; + public static final int MANDATE_FULL_MANDATE_MAX_LENGTH = 32767; + + public static final String INVOICE_RECPT_ID_OID = "1.2.40.0.10.2.1.1.261.40"; + public static final String INVOICE_RECPT_ID_NAME = URN_OID_PREFIX + INVOICE_RECPT_ID_OID; + public static final String INVOICE_RECPT_ID_FRIENDLY_NAME = "INVOICE-RECPT-ID"; + public static final int INVOICE_RECPT_ID_MAX_LENGTH = 64; + + public static final String COST_CENTER_ID_OID = "1.2.40.0.10.2.1.1.261.50"; + public static final String COST_CENTER_ID_NAME = URN_OID_PREFIX + COST_CENTER_ID_OID; + public static final String COST_CENTER_ID_FRIENDLY_NAME = "COST-CENTER-ID"; + public static final int COST_CENTER_ID_MAX_LENGTH = 32767; + + public static final String CHARGE_CODE_OID = "1.2.40.0.10.2.1.1.261.60"; + public static final String CHARGE_CODE_NAME = URN_OID_PREFIX + CHARGE_CODE_OID; + public static final String CHARGE_CODE_FRIENDLY_NAME = "CHARGE-CODE"; + public static final int CHARGE_CODE_MAX_LENGTH = 32767; +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/exception/ConfigurationException.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/exception/ConfigurationException.java new file mode 100644 index 000000000..77250d818 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/exception/ConfigurationException.java @@ -0,0 +1,20 @@ +package at.gv.egovernment.moa.id.demoOA.exception; + + +public class ConfigurationException extends Exception { + + private static final long serialVersionUID = 1L; + + public ConfigurationException(String errorname) { + super(errorname); + } + + public ConfigurationException(String errorname, Throwable e) { + super(errorname, e); + } + + public ConfigurationException(Throwable e) { + super(e); + } + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java new file mode 100644 index 000000000..68fef277b --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java @@ -0,0 +1,222 @@ +package at.gv.egovernment.moa.id.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +import org.joda.time.DateTime; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; +import org.opensaml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.ws.transport.http.HttpServletResponseAdapter; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.iaik.commons.util.MiscUtil; + + +/** + * Servlet implementation class Authenticate + */ +public class Authenticate extends HttpServlet { + private static final long serialVersionUID = 1L; + + private static final Logger log = LoggerFactory + .getLogger(Authenticate.class); + + /** + * @see HttpServlet#HttpServlet() + */ + public Authenticate() { + super(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + builder = factory.newDocumentBuilder(); + + } catch (ParserConfigurationException e) { + log.warn("PVP2 AuthenticationServlet can not be initialized.", e); + } + } + + DocumentBuilder builder; + + + protected void process(HttpServletRequest request, + HttpServletResponse response, Map legacyParameter) throws ServletException, IOException { + try { + + Configuration config = Configuration.getInstance(); + config.initializePVP2Login(); + + AuthnRequest authReq = SAML2Utils + .createSAMLObject(AuthnRequest.class); + SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + authReq.setID(gen.generateIdentifier()); + + HttpSession session = request.getSession(); + if (session != null) { + session.setAttribute(Constants.SESSION_PVP2REQUESTID, authReq.getID()); + } + + authReq.setAssertionConsumerServiceIndex(0); + authReq.setAttributeConsumingServiceIndex(0); + authReq.setIssueInstant(new DateTime()); + Subject subject = SAML2Utils.createSAMLObject(Subject.class); + NameID name = SAML2Utils.createSAMLObject(NameID.class); + Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); + + String serviceURL = config.getPublicUrlPreFix(request); + if (!serviceURL.endsWith("/")) + serviceURL = serviceURL + "/"; + name.setValue(serviceURL); + issuer.setValue(serviceURL); + + subject.setNameID(name); + authReq.setSubject(subject); + issuer.setFormat(NameIDType.ENTITY); + authReq.setIssuer(issuer); + NameIDPolicy policy = SAML2Utils + .createSAMLObject(NameIDPolicy.class); + policy.setAllowCreate(true); + policy.setFormat(NameID.PERSISTENT); + authReq.setNameIDPolicy(policy); + + String entityname = config.getPVP2IDPMetadataEntityName(); + if (MiscUtil.isEmpty(entityname)) { + log.info("No IDP EntityName configurated"); + throw new ConfigurationException("No IDP EntityName configurated"); + } + + HTTPMetadataProvider idpmetadata = config.getMetaDataProvier(); + EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); + if (idpEntity == null) { + log.info("IDP EntityName is not found in IDP Metadata"); + throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); + } + + SingleSignOnService redirectEndpoint = null; + for (SingleSignOnService sss : + idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { + + //Get the service address for the binding you wish to use + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + redirectEndpoint = sss; + } + } + + authReq.setDestination(redirectEndpoint.getLocation()); + + RequestedAuthnContext reqAuthContext = + SAML2Utils.createSAMLObject(RequestedAuthnContext.class); + + AuthnContextClassRef authnClassRef = + SAML2Utils.createSAMLObject(AuthnContextClassRef.class); + + authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); + + reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); + + reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); + + authReq.setRequestedAuthnContext(reqAuthContext); + + KeyStore keyStore = config.getPVP2KeyStore(); + + X509Credential authcredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreAuthRequestKeyAlias(), + config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); + + Signature signer = SAML2Utils.createSAMLObject(Signature.class); + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); + signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signer.setSigningCredential(authcredential); + + authReq.setSignature(signer); + + VelocityEngine engine = new VelocityEngine(); + engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); + engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); + engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); + engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); + engine.setProperty("classpath.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + engine.init(); + + HTTPPostEncoder encoder = new HTTPPostEncoder(engine, + "templates/pvp_postbinding_template.html"); + HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( + response, true); + BasicSAMLMessageContext context = new BasicSAMLMessageContext(); + SingleSignOnService service = new SingleSignOnServiceBuilder() + .buildObject(); + service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); + service.setLocation(redirectEndpoint.getLocation());; + + context.setOutboundSAMLMessageSigningCredential(authcredential); + context.setPeerEntityEndpoint(service); + context.setOutboundSAMLMessage(authReq); + context.setOutboundMessageTransport(responseAdapter); + + encoder.encode(context); + + } catch (Exception e) { + log.warn("Authentication Request can not be generated", e); + throw new ServletException("Authentication Request can not be generated.", e); + } + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + process(request, response, null); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + process(request, response, null); + } + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java new file mode 100644 index 000000000..f3821374a --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java @@ -0,0 +1,279 @@ +package at.gv.egovernment.moa.id.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.io.StringWriter; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.log4j.Logger; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.KeyDescriptor; +import org.opensaml.saml2.metadata.LocalizedString; +import org.opensaml.saml2.metadata.NameIDFormat; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.ServiceName; +import org.opensaml.xml.io.Marshaller; +import org.opensaml.xml.security.credential.Credential; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.Signer; +import org.w3c.dom.Document; + +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.AttributeListBuilder; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.iaik.commons.util.MiscUtil; + +public class BuildMetadata extends HttpServlet { + private static final long serialVersionUID = 1L; + + private static final Logger log = Logger.getLogger(BuildMetadata.class); + + /** + * @see HttpServlet#HttpServlet() + */ + public BuildMetadata() { + super(); + } + + protected static Signature getSignature(Credential credentials) { + Signature signer = SAML2Utils.createSAMLObject(Signature.class); + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); + signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signer.setSigningCredential(credentials); + return signer; + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + try { + Configuration config = Configuration.getInstance(); + + SecureRandomIdentifierGenerator idGen = new SecureRandomIdentifierGenerator(); + + EntitiesDescriptor spEntitiesDescriptor = SAML2Utils. + createSAMLObject(EntitiesDescriptor.class); + + String name = config.getPVP2MetadataEntitiesName(); + if (MiscUtil.isEmpty(name)) { + log.info("NO Metadata EntitiesName configurated"); + throw new ConfigurationException("NO Metadata EntitiesName configurated"); + } + + spEntitiesDescriptor.setName(name); + spEntitiesDescriptor.setID(idGen.generateIdentifier()); + + EntityDescriptor spEntityDescriptor = SAML2Utils + .createSAMLObject(EntityDescriptor.class); + + spEntitiesDescriptor.getEntityDescriptors().add(spEntityDescriptor); + + String serviceURL = config.getPublicUrlPreFix(request); + if (!serviceURL.endsWith("/")) + serviceURL = serviceURL + "/"; + + log.debug("Set OnlineApplicationURL to " + serviceURL); + spEntityDescriptor.setEntityID(serviceURL); + + SPSSODescriptor spSSODescriptor = SAML2Utils + .createSAMLObject(SPSSODescriptor.class); + + spSSODescriptor.setAuthnRequestsSigned(true); + spSSODescriptor.setWantAssertionsSigned(true); + + X509KeyInfoGeneratorFactory keyInfoFactory = new X509KeyInfoGeneratorFactory(); + keyInfoFactory.setEmitEntityCertificate(true); + KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); + + + KeyStore keyStore = config.getPVP2KeyStore(); + + X509Credential signingcredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreMetadataKeyAlias(), + config.getPVP2KeystoreMetadataKeyPassword().toCharArray()); + + + log.debug("Set Metadata key information"); + //Set MetaData Signing key + KeyDescriptor entitiesSignKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + entitiesSignKeyDescriptor.setUse(UsageType.SIGNING); + entitiesSignKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(signingcredential)); + Signature entitiesSignature = getSignature(signingcredential); + spEntitiesDescriptor.setSignature(entitiesSignature); + + + //Set AuthRequest Signing certificate + X509Credential authcredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreAuthRequestKeyAlias(), + config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); + KeyDescriptor signKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + signKeyDescriptor.setUse(UsageType.SIGNING); + signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential)); + spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); + + + //set AuthRequest encryption certificate + if (MiscUtil.isNotEmpty(config.getPVP2KeystoreAuthRequestEncryptionKeyAlias()) || + MiscUtil.isNotEmpty(config.getPVP2KeystoreAuthRequestEncryptionKeyPassword())) { + X509Credential authEncCredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreAuthRequestEncryptionKeyAlias(), + config.getPVP2KeystoreAuthRequestEncryptionKeyPassword().toCharArray()); + KeyDescriptor encryKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + encryKeyDescriptor.setUse(UsageType.ENCRYPTION); + encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential)); + spSSODescriptor.getKeyDescriptors().add(encryKeyDescriptor); + + } else { + log.warn("No Assertion Encryption-Key defined. This setting is not recommended!"); + + } + + + NameIDFormat persistentnameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + persistentnameIDFormat.setFormat(NameIDType.PERSISTENT); + + spSSODescriptor.getNameIDFormats().add(persistentnameIDFormat); + + NameIDFormat transientnameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + transientnameIDFormat.setFormat(NameIDType.TRANSIENT); + + spSSODescriptor.getNameIDFormats().add(transientnameIDFormat); + + NameIDFormat unspecifiednameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + unspecifiednameIDFormat.setFormat(NameIDType.UNSPECIFIED); + + spSSODescriptor.getNameIDFormats().add(unspecifiednameIDFormat); + + AssertionConsumerService postassertionConsumerService = + SAML2Utils.createSAMLObject(AssertionConsumerService.class); + + postassertionConsumerService.setIndex(0); + postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + postassertionConsumerService.setLocation(serviceURL + Constants.SERVLET_PVP2ASSERTION); + + spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); + + spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + + spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor); + + spSSODescriptor.setWantAssertionsSigned(true); + spSSODescriptor.setAuthnRequestsSigned(true); + + AttributeConsumingService attributeService = + SAML2Utils.createSAMLObject(AttributeConsumingService.class); + + attributeService.setIndex(0); + attributeService.setIsDefault(true); + ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class); + serviceName.setName(new LocalizedString("Default Service", "de")); + attributeService.getNames().add(serviceName); + + attributeService.getRequestAttributes().addAll(AttributeListBuilder.getRequestedAttributes()); + + spSSODescriptor.getAttributeConsumingServices().add(attributeService); + + DocumentBuilder builder; + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + + builder = factory.newDocumentBuilder(); + Document document = builder.newDocument(); + Marshaller out = org.opensaml.Configuration.getMarshallerFactory().getMarshaller(spEntitiesDescriptor); + out.marshall(spEntitiesDescriptor, document); + + Signer.signObject(entitiesSignature); + + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + DOMSource source = new DOMSource(document); + transformer.transform(source, sr); + sw.close(); + + String metadataXML = sw.toString(); + + response.setContentType("text/xml"); + response.getOutputStream().write(metadataXML.getBytes()); + + response.getOutputStream().close(); + + } catch (ConfigurationException e) { + log.warn("Configuration can not be loaded.", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + + } catch (NoSuchAlgorithmException e) { + log.warn("Requested Algorithm could not found.", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + + } catch (ParserConfigurationException e) { + log.warn("PVP2 Metadata createn error", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + + } catch (TransformerConfigurationException e) { + log.warn("PVP2 Metadata createn error", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + + } catch (TransformerFactoryConfigurationError e) { + log.warn("PVP2 Metadata createn error", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + + } catch (TransformerException e) { + log.warn("PVP2 Metadata createn error", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + } + + catch (Exception e) { + log.warn("Unspecific PVP2 Metadata createn error", e); + throw new ServletException("MetaData can not be created. Look into LogFiles for more details."); + } + + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + } + +} \ No newline at end of file diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java new file mode 100644 index 000000000..2d32ce9af --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java @@ -0,0 +1,264 @@ +package at.gv.egovernment.moa.id.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.AttributeStatement; +import org.opensaml.saml2.core.EncryptedAssertion; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.encryption.Decrypter; +import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.security.MetadataCredentialResolver; +import org.opensaml.security.MetadataCredentialResolverFactory; +import org.opensaml.security.MetadataCriteria; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.ws.transport.http.HttpServletRequestAdapter; +import org.opensaml.xml.encryption.ChainingEncryptedKeyResolver; +import org.opensaml.xml.encryption.InlineEncryptedKeyResolver; +import org.opensaml.xml.encryption.SimpleRetrievalMethodEncryptedKeyResolver; +import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.security.CriteriaSet; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.criteria.EntityIDCriteria; +import org.opensaml.xml.security.criteria.UsageCriteria; +import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xml.security.keyinfo.KeyInfoProvider; +import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver; +import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider; +import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider; +import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; + +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.PVPConstants; +import at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.gv.egovernment.moa.util.DOMUtils; + + +public class DemoApplication extends HttpServlet { + + private static final long serialVersionUID = -2129228304760706063L; + private static final Logger log = Logger.getLogger(DemoApplication.class); + + + + private void process(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + + ApplicationBean bean = new ApplicationBean(); + + + String method = request.getMethod(); + HttpSession session = request.getSession(); + if (session == null) { + log.info("NO HTTP Session"); + bean.setErrorMessage("NO HTTP session"); + setAnser(request, response, bean); + return; + } + + if (method.equals("POST")) { + + try { + Configuration config = Configuration.getInstance(); + + //Decode with HttpPost Binding + HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool()); + BasicSAMLMessageContext messageContext = new BasicSAMLMessageContext(); + messageContext + .setInboundMessageTransport(new HttpServletRequestAdapter( + request)); + decode.decode(messageContext); + + Response samlResponse = (Response) messageContext.getInboundMessage(); + + Signature sign = samlResponse.getSignature(); + if (sign == null) { + log.info("Only http POST Requests can be used"); + bean.setErrorMessage("Only http POST Requests can be used"); + setAnser(request, response, bean); + return; + } + + //Validate Signature + SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + profileValidator.validate(sign); + + //Verify Signature + List keyInfoProvider = new ArrayList(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + + KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + MetadataCredentialResolverFactory credentialResolverFactory = MetadataCredentialResolverFactory.getFactory(); + MetadataCredentialResolver credentialResolver = credentialResolverFactory.getInstance(config.getMetaDataProvier()); + + CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityIDCriteria(config.getPVP2IDPMetadataEntityName())); + criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); + + ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver); + trustEngine.validate(sign, criteriaSet); + + log.info("PVP2 Assertion is valid"); + + if (samlResponse.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { + + List saml2assertions = new ArrayList(); + + //check encrypted Assertion + List encryAssertionList = samlResponse.getEncryptedAssertions(); + if (encryAssertionList != null && encryAssertionList.size() > 0) { + //decrypt assertions + + log.debug("Found encryped assertion. Start decryption ..."); + + KeyStore keyStore = config.getPVP2KeyStore(); + + X509Credential authDecCredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreAuthRequestEncryptionKeyAlias(), + config.getPVP2KeystoreAuthRequestEncryptionKeyPassword().toCharArray()); + + + StaticKeyInfoCredentialResolver skicr = + new StaticKeyInfoCredentialResolver(authDecCredential); + + ChainingEncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(); + encryptedKeyResolver.getResolverChain().add( new InlineEncryptedKeyResolver() ); + encryptedKeyResolver.getResolverChain().add( new EncryptedElementTypeEncryptedKeyResolver() ); + encryptedKeyResolver.getResolverChain().add( new SimpleRetrievalMethodEncryptedKeyResolver() ); + + Decrypter samlDecrypter = + new Decrypter(null, skicr, encryptedKeyResolver); + + for (EncryptedAssertion encAssertion : encryAssertionList) { + saml2assertions.add(samlDecrypter.decrypt(encAssertion)); + + } + + log.debug("Assertion decryption finished. "); + + } else { + saml2assertions = samlResponse.getAssertions(); + + } + + String givenName = null; + String familyName = null; + String birthday = null; + + for (org.opensaml.saml2.core.Assertion saml2assertion : saml2assertions) { + + //loop through the nodes to get what we want + List attributeStatements = saml2assertion.getAttributeStatements(); + for (int i = 0; i < attributeStatements.size(); i++) + { + List attributes = attributeStatements.get(i).getAttributes(); + for (int x = 0; x < attributes.size(); x++) + { + String strAttributeName = attributes.get(x).getDOM().getAttribute("Name"); + + if (strAttributeName.equals(PVPConstants.PRINCIPAL_NAME_NAME)) + familyName = attributes.get(x).getAttributeValues().get(0).getDOM().getTextContent(); + + if (strAttributeName.equals(PVPConstants.GIVEN_NAME_NAME)) + givenName = attributes.get(x).getAttributeValues().get(0).getDOM().getTextContent(); + + if (strAttributeName.equals(PVPConstants.BIRTHDATE_NAME)) { + birthday = attributes.get(x).getAttributeValues().get(0).getDOM().getTextContent(); + } + } + } + } + + org.w3c.dom.Document doc = SAML2Utils.asDOMDocument(samlResponse); + String assertion = DOMUtils.serializeNode(doc); + + bean.setAssertion(assertion); + bean.setDateOfBirth(birthday); + bean.setFamilyName(familyName); + bean.setGivenName(givenName); + bean.setLogin(true); + + setAnser(request, response, bean); + return; + + + } else { + bean.setErrorMessage("Der Anmeldevorgang wurde abgebrochen.
Eine genaue Beschreibung des Fehlers finden Sie in der darunterliegenden Assertion."); + setAnser(request, response, bean); + return; + + } + + } catch (Exception e) { + log.warn(e); + bean.setErrorMessage("Internal Error: " + e.getMessage()); + setAnser(request, response, bean); + return; + } + + } else { + bean.setErrorMessage("Die Demoapplikation unterstützt nur SAML2 POST-Binding."); + setAnser(request, response, bean); + return; + + } + } + + private void setAnser(HttpServletRequest request, HttpServletResponse response, ApplicationBean answersBean) throws ServletException, IOException { + // store bean in session + request.setAttribute("answers", answersBean); + + // you now can forward to some view, for example some results.jsp + request.getRequestDispatcher("demoapp.jsp").forward(request, response); + + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + process(request, response); + } + + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + process(request, response); + } +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java new file mode 100644 index 000000000..83f9a8b2c --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java @@ -0,0 +1,93 @@ +package at.gv.egovernment.moa.id.demoOA.utils; + +import java.io.Serializable; + +public class ApplicationBean implements Serializable { + + private static final long serialVersionUID = -1280536194708616850L; + + private String familyName; + private String givenName; + private String dateOfBirth; + private String assertion; + + private boolean isLogin = false; + + private String errorMessage; + + /** + * @return the familyName + */ + public String getFamilyName() { + return familyName; + } + /** + * @param familyName the familyName to set + */ + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + /** + * @return the givenName + */ + public String getGivenName() { + return givenName; + } + /** + * @param givenName the givenName to set + */ + public void setGivenName(String givenName) { + this.givenName = givenName; + } + /** + * @return the dateOfBirth + */ + public String getDateOfBirth() { + return dateOfBirth; + } + /** + * @param dateOfBirth the dateOfBirth to set + */ + public void setDateOfBirth(String dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + /** + * @return the assertion + */ + public String getAssertion() { + return assertion; + } + /** + * @param assertion the assertion to set + */ + public void setAssertion(String assertion) { + this.assertion = assertion; + } + /** + * @return the errorMessage + */ + public String getErrorMessage() { + return errorMessage; + } + /** + * @param errorMessage the errorMessage to set + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + /** + * @return the isLogin + */ + public boolean isLogin() { + return isLogin; + } + /** + * @param isLogin the isLogin to set + */ + public void setLogin(boolean isLogin) { + this.isLogin = isLogin; + } + + + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/AttributeListBuilder.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/AttributeListBuilder.java new file mode 100644 index 000000000..8c9d15d11 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/AttributeListBuilder.java @@ -0,0 +1,57 @@ +package at.gv.egovernment.moa.id.demoOA.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.metadata.RequestedAttribute; + +import at.gv.egovernment.moa.id.demoOA.PVPConstants; + + + +public class AttributeListBuilder implements PVPConstants{ + + protected static RequestedAttribute buildReqAttribute(String name, String friendlyName, boolean required) { + RequestedAttribute attribute = SAML2Utils.createSAMLObject(RequestedAttribute.class); + attribute.setIsRequired(required); + attribute.setName(name); + attribute.setFriendlyName(friendlyName); + attribute.setNameFormat(Attribute.URI_REFERENCE); + return attribute; + } + + public static List getRequestedAttributes() { + List requestedAttributes = new ArrayList(); + + requestedAttributes.add(buildReqAttribute(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(GIVEN_NAME_NAME, GIVEN_NAME_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(BIRTHDATE_NAME, BIRTHDATE_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(BPK_NAME, BPK_FRIENDLY_NAME, true)); + + requestedAttributes.add(buildReqAttribute(EID_CITIZEN_QAA_LEVEL_NAME, EID_CITIZEN_QAA_LEVEL_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_ISSUING_NATION_NAME, EID_ISSUING_NATION_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_SECTOR_FOR_IDENTIFIER_NAME, EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_SIGNER_CERTIFICATE_NAME, EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_CCS_URL_NAME, EID_CCS_URL_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_AUTH_BLOCK_NAME, EID_AUTH_BLOCK_FRIENDLY_NAME, true)); + requestedAttributes.add(buildReqAttribute(EID_IDENTITY_LINK_NAME, EID_IDENTITY_LINK_FRIENDLY_NAME, true)); + + requestedAttributes.add(buildReqAttribute(MANDATE_TYPE_NAME, MANDATE_TYPE_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_FULL_MANDATE_NAME, MANDATE_FULL_MANDATE_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_LEG_PER_FULL_NAME_NAME, MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_LEG_PER_SOURCE_PIN_NAME, MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false)); + + requestedAttributes.add(buildReqAttribute(MANDATE_NAT_PER_BIRTHDATE_NAME, MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_NAT_PER_BPK_NAME, MANDATE_NAT_PER_BPK_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_NAT_PER_FAMILY_NAME_NAME, MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_NAT_PER_GIVEN_NAME_NAME, MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false)); + + requestedAttributes.add(buildReqAttribute(MANDATE_REFERENCE_VALUE_NAME, MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_PROF_REP_OID_NAME, MANDATE_PROF_REP_OID_FRIENDLY_NAME, false)); + requestedAttributes.add(buildReqAttribute(MANDATE_PROF_REP_DESC_NAME, MANDATE_PROF_REP_DESC_FRIENDLY_NAME, false)); + return requestedAttributes; + } +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/MetaDataVerificationFilter.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/MetaDataVerificationFilter.java new file mode 100644 index 000000000..2b4e20ba0 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/MetaDataVerificationFilter.java @@ -0,0 +1,54 @@ +package at.gv.egovernment.moa.id.demoOA.utils; + +import java.util.Iterator; + +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.provider.FilterException; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.security.x509.BasicX509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureValidator; +import org.opensaml.xml.validation.ValidationException; + +public class MetaDataVerificationFilter implements MetadataFilter { + + BasicX509Credential credential; + + public MetaDataVerificationFilter(BasicX509Credential credential) { + this.credential = credential; + } + + + public void doFilter(XMLObject metadata) throws FilterException { + if (metadata instanceof EntitiesDescriptor) { + EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata; + + if(entitiesDescriptor.getSignature() == null) { + throw new FilterException("IDP metadata is not signed", null); + } + + Signature sign = entitiesDescriptor.getSignature(); + + try { + + //Validate signature + SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + profileValidator.validate(sign); + + + //Verify signature + SignatureValidator sigValidator = new SignatureValidator(credential); + sigValidator.validate(sign); + + } catch (ValidationException e) { + throw new FilterException("IDP metadata validation error", e); + + } + + } + } + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/SAML2Utils.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/SAML2Utils.java new file mode 100644 index 000000000..f04caf888 --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/SAML2Utils.java @@ -0,0 +1,87 @@ +package at.gv.egovernment.moa.id.demoOA.utils; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.opensaml.Configuration; +import org.opensaml.DefaultBootstrap; +import org.opensaml.xml.ConfigurationException; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.XMLObjectBuilder; +import org.opensaml.xml.XMLObjectBuilderFactory; +import org.opensaml.xml.io.Marshaller; +import org.opensaml.xml.io.MarshallingException; +import org.w3c.dom.Document; + + +public class SAML2Utils { + + static { + try { + DefaultBootstrap.bootstrap(); + } catch (ConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setValidating(false); + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static DocumentBuilder builder; + + public static T createSAMLObject(final Class clazz) { + try { + + XMLObjectBuilderFactory builderFactory = Configuration + .getBuilderFactory(); + + QName defaultElementName = (QName) clazz.getDeclaredField( + "DEFAULT_ELEMENT_NAME").get(null); + Map builder = builderFactory.getBuilders(); + Iterator it = builder.keySet().iterator(); + + while (it.hasNext()) { + QName qname = it.next(); + if (qname.equals(defaultElementName)) { + System.out.printf("Builder for: %s\n", qname.toString()); + } + } + XMLObjectBuilder xmlBuilder = builderFactory + .getBuilder(defaultElementName); + + T object = (T) xmlBuilder.buildObject(defaultElementName); + return object; + } catch (Throwable e) { + System.out.printf("Failed to create object for: %s\n", + clazz.toString()); + e.printStackTrace(); + return null; + } + } + + public static Document asDOMDocument(XMLObject object) throws IOException, + MarshallingException, TransformerException { + org.w3c.dom.Document document = builder.newDocument(); + Marshaller out = Configuration.getMarshallerFactory().getMarshaller( + object); + out.marshall(object, document); + return (Document) document; + } + + + +} diff --git a/id/oa/src/main/resources/defaultConfig.properties b/id/oa/src/main/resources/defaultConfig.properties new file mode 100644 index 000000000..a15143ad3 --- /dev/null +++ b/id/oa/src/main/resources/defaultConfig.properties @@ -0,0 +1,20 @@ +general.login.pvp2.idp.metadata.url=https://labda.iaik.tugraz.at:8443/moa-id-auth/pvp2/metadata +general.login.pvp2.idp.metadata.certificate=D:/Projekte/svn/moa-id/configs/moa_idp.crt +general.login.pvp2.idp.metadata.entityID=https://labda.iaik.tugraz.at:8443/moa-id-auth + +general.login.pvp2.OA.metadata.entities.name=MOA-ID 2.x Configuration Tool +general.login.pvp2.OA.metadata.entity.name=https://labda.iaik.tugraz.at:8443/oa + +general.login.pvp2.OA.keystore.url=D:/Projekte/svn/moa-id/configs/pvp.p12 +general.login.pvp2.OA.keystore.password=123456 +general.login.pvp2.OA.keystore.type=PKCS12 + +general.login.pvp2.OA.keystore.metadata.sign.key.alias=pvpsp +general.login.pvp2.OA.keystore.metadata.sign.key.password=123456 + +general.login.pvp2.keystore.authrequest.sign.key.alias=pvpidp +general.login.pvp2.keystore.authrequest.sign.key.password=123456 + +general.login.pvp2.keystore.assertion.encryption.key.alias=pvpencryption +general.login.pvp2.keystore.assertion.encryption.key.password=123456 + diff --git a/id/oa/src/main/resources/templates/pvp_postbinding_template.html b/id/oa/src/main/resources/templates/pvp_postbinding_template.html new file mode 100644 index 000000000..1215c2b58 --- /dev/null +++ b/id/oa/src/main/resources/templates/pvp_postbinding_template.html @@ -0,0 +1,51 @@ +## +## Velocity Template for SAML 2 HTTP-POST binding +## +## Velocity context may contain the following properties +## action - String - the action URL for the form +## RelayState - String - the relay state for the message +## SAMLRequest - String - the Base64 encoded SAML Request +## SAMLResponse - String - the Base64 encoded SAML Response + + + + + + + +
Your login is being processed. Thank you for waiting.
+ + + +
+
+ #if($RelayState)#end + + #if($SAMLRequest)#end + + #if($SAMLResponse)#end + +
+ +
+ + + \ No newline at end of file diff --git a/id/oa/src/main/webapp/WEB-INF/web.xml b/id/oa/src/main/webapp/WEB-INF/web.xml index 13158fdaa..85a1bbaeb 100644 --- a/id/oa/src/main/webapp/WEB-INF/web.xml +++ b/id/oa/src/main/webapp/WEB-INF/web.xml @@ -4,6 +4,40 @@ Sample OA - MOA Sample OA + MOA PVP2.1 Sample OA + + + pvp2login + pvp2login + at.gv.egovernment.moa.id.demoOA.servlet.pvp2.Authenticate + + + + pvp2login + /servlet/pvp2login + + + + pvp2metadata + Metadata + at.gv.egovernment.moa.id.demoOA.servlet.pvp2.BuildMetadata + + + + pvp2metadata + /servlet/metadata + + + + pvp2demooa + Secure area + at.gv.egovernment.moa.id.demoOA.servlet.pvp2.DemoApplication + + + + pvp2demooa + /demoapplication + + diff --git a/id/oa/src/main/webapp/auth.jsp b/id/oa/src/main/webapp/auth.jsp deleted file mode 100644 index 0b563a83e..000000000 --- a/id/oa/src/main/webapp/auth.jsp +++ /dev/null @@ -1,48 +0,0 @@ - - -MOA ID Auth Sample Login - - -<% /** assumes moa-id-auth and oa in the same servlet container, - and moa-id-proxy on a different fixed location */ - String authUrlPath = - request.getScheme() + "://" - + request.getServerName() + ":" + request.getServerPort() - + "/moa-id-auth/"; - String proxyUrlPath = "http://10.16.126.28:9080/moa-id-proxy/"; - String oaUrlPath = - request.getScheme() + "://" - + request.getServerName() + ":" + request.getServerPort() - + "/oa/"; - String params = - "Target=gb&" + - "OA=" + proxyUrlPath + "index.jsp"; - String urlStartAuth = - authUrlPath + - "StartAuthentication?" + - params; - String templateParam = - "&Template=" + oaUrlPath + "AuthTemplate.jsp"; - String urlStartAuthCustom = - urlStartAuth + - templateParam; - String urlSelectBKU = - authUrlPath + - "SelectBKU?" + - params; - String urlSelectBKUCustom = - urlSelectBKU + - templateParam + - "&BKUSelectionTemplate=" + oaUrlPath + "BKUSelectionTemplate.jsp"; -%> -Log in to sample application -
-Log in to sample application using custom form -
-Choose BKU (HTMLComplete or HTMLSelect) and log in -
-Choose BKU (HTMLSelect) using custom form and log in -
-">Wrong parameters example - - \ No newline at end of file diff --git a/id/oa/src/main/webapp/chooseBKU.jsp b/id/oa/src/main/webapp/chooseBKU.jsp deleted file mode 100644 index 0135b6fdf..000000000 --- a/id/oa/src/main/webapp/chooseBKU.jsp +++ /dev/null @@ -1,19 +0,0 @@ - - -BKU Auswahl - - -

BKU Auswahl

-

-

"> - - -
-

- - \ No newline at end of file diff --git a/id/oa/src/main/webapp/css/index.css b/id/oa/src/main/webapp/css/index.css new file mode 100644 index 000000000..6ff99af63 --- /dev/null +++ b/id/oa/src/main/webapp/css/index.css @@ -0,0 +1,205 @@ +@charset "utf-8"; + +h2#demonstrator_tabheader, h2#demonstrator_contentheader { + padding:2px; + font-size:1.1em; + color:#fff; + border-bottom:2px solid #fff; +} + +#demonstrator_centercontent { + width:auto; + +} + +#demonstrator_content { + padding:20px; +} + +#demonstrator_content a { + text-decoration:underline; + color: #000; +} + +.logoutbuttons { + margin-bottom: 5px; + margin-top: 0; +} + +p { + margin-bottom:1em; +} + + +/* [OPTIONAL] Geben Sie hier die Farbe fuer den hellen Hintergrund an */ +.demonstrator_hell { + background-color : #DDDDDD; +} + +/* [OPTIONAL] Geben Sie hier die Farbe fuer den dunklen Hintergrund an */ +.demonstrator_dunkel { + background-color: #A02D2D; +} + +.demonstrator_logoutButton { + position: relative; + margin-left: 65%; + bottom: 15px; +} + +.demonstrator_button { +/* background: #efefef; + border:2px solid #000; */ + cursor: pointer; + width: 180px; + height: 25px; + text-align: center; + margin-bottom: 10px; + margin-top: 25px; + border-radius: 5px; + padding-top: 5px; + padding-bottom: 5px; +} + +#demonstrator_SAML-assertion { + display: none; +} + +#demonstrator_samlArea{ + width: 100%; +} + +/* Anmeldeframe */ +#demonstrator_main { + clear:both; +} + +#demonstrator_leftcontent { + /*float:left;*/ +/* width:255px; */ + margin-left: 40%; + position: relative; +/* margin: 0 auto; */ +} + +#submitbutton { + width: 150px; +} + +h2#demonstrator_tabheader, h2#demonstrator_contentheader { + padding:2px; + font-size:1.1em; + color:#fff; + border-bottom:2px solid #fff; +} + +#demonstrator_bkulogin { + overflow:hidden; +} + +#demonstrator_bkukarte { + float:left; + background: url(../img/karte.gif) no-repeat top center; + padding: 90px 10px 10px 10px; + text-align:center; + width:40%; +} + +#demonstrator_bkuhandy { + float:right; + background: url(../img/handy.gif) no-repeat top center; + padding: 90px 10px 10px 10px; + text-align:center; + width:40%; +} + +#demonstrator_mandate{ + text-align:center; + padding : 5px 5px 5px 5px; + clear: both; +} + +#demonstrator_stork{ + text-align:center; + padding-top: 5px; + padding-bottom: 5px; + clear: both; +} + +/* .demonstrator_button input { + background: #efefef; + border:1px solid #000; + cursor: pointer; +} */ + +#demonstrator_installJava, #demonstrator_BrowserNOK { + clear:both; + font-size:0.8em; + padding:4px; +} + +#demonstrator_localBKU { + padding:4px; +} + +#demonstrator_localBKU p{ + text-align: left; +} + +.demonstrator_sendButton { + background-color: DarkGray; + border-style: solid; + border-width: 1px; + border-color: black; +} + +#demonstrator_tab { + margin-top:2px; + padding:2px; + clear:both; +} + +#demonstrator_leftcontent a { + text-decoration:none; + color: #000; +/* display:block;*/ + padding:4px; +} + +#demonstrator_leftcontent a:hover, #demonstrator_leftcontent a:focus, #demonstrator_leftcontent a:active { + text-decoration:underline; + color: #000; +} + +#demonstrator_navlist { + margin-top:20px; +} + +#demonstrator_navlist ul { + list-style: none; + margin-left: 0; +} + +#demonstrator_navlist li { + border-bottom:1px solid #fff; +} + +/* iframe { + width:250px; +} */ + +.demonstrator_infobutton { + background-color: #005a00; + color: white; + font-family: serif; + text-decoration: none; + padding-top: 2px; + padding-right: 4px; + padding-bottom: 2px; + padding-left: 4px; + font-weight: bold; +} + +#demonstrator_cccSelection{ + margin-bottom: auto; +} diff --git a/id/oa/src/main/webapp/demoapp.jsp b/id/oa/src/main/webapp/demoapp.jsp new file mode 100644 index 000000000..c6b005deb --- /dev/null +++ b/id/oa/src/main/webapp/demoapp.jsp @@ -0,0 +1,73 @@ + +<%@ page import = "at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean" %> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + + + + + Demo Applikation + + + + <% + ApplicationBean bean = (ApplicationBean) request.getAttribute("answers"); + %> + +
+ +
+

Anmeldedaten

+
+ + <% if (bean.isLogin()) {%> +
+
+

LogOut

+
+ +
+ + + + + +
Benutzerdaten:<%= bean.getGivenName()%>  + <%= bean.getFamilyName()%>  + <%= bean.getDateOfBirth()%>
+ + <%} else { %> + +
+ LogIn +
+

<%= bean.getErrorMessage()%>

+ <%} %> + + +
+ +
+ + +
+

SAML Assertion

+
+ +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/id/oa/src/main/webapp/form.jsp b/id/oa/src/main/webapp/form.jsp deleted file mode 100644 index d439fa84d..000000000 --- a/id/oa/src/main/webapp/form.jsp +++ /dev/null @@ -1,20 +0,0 @@ -<%@ page import="java.util.*" %> - - -Sample Online Application - - -

Sample Form

-

-

-<% String param1 = request.getParameter("param1"); - if (param1 == null) param1 = ""; %> -Input some text: - -
Previous text input: <%=param1%>
- -
-

-

Back

- - \ No newline at end of file diff --git a/id/oa/src/main/webapp/getBKUSelectTag.jsp b/id/oa/src/main/webapp/getBKUSelectTag.jsp deleted file mode 100644 index 028dbd348..000000000 --- a/id/oa/src/main/webapp/getBKUSelectTag.jsp +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/id/oa/src/main/webapp/index.jsp b/id/oa/src/main/webapp/index.jsp deleted file mode 100644 index 35e49d743..000000000 --- a/id/oa/src/main/webapp/index.jsp +++ /dev/null @@ -1,60 +0,0 @@ -<%@ page import="java.util.*,javax.servlet.http.*,sun.misc.BASE64Decoder" %> - - -Sample Online Application - - -

Sample Online Application

- -

Request headers: - - <% - /* collect parameters from request */ - for (Enumeration headers = request.getHeaderNames(); headers.hasMoreElements(); ) { - String key = (String) headers.nextElement(); - String value = request.getHeader(key); %> - - <% } %> -
<%=key%><%=value%>
-

- -<% String query=request.getQueryString(); %> -

QueryString: "<%=query%>" -

- -

Request parameters: - - <% - /* collect parameters from request */ - for (Enumeration params = request.getParameterNames(); params.hasMoreElements(); ) { - String name = (String) params.nextElement(); - String value = request.getParameter(name); %> - - <% } %> -
<%=name%><%=value%>
-

- -

Cookies: - - <% - /* collect attributes from request */ - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (int i = 0; i < cookies.length; i++) { - Cookie cookie = cookies[i]; %> - - <% } - } %> -
<%=cookie.getName()%><%=cookie.getValue()%>
-

- -<% String authHeader = request.getHeader("Authorization"); - if (authHeader != null) { - authHeader = authHeader.substring(authHeader.indexOf(" ")+1); - String decAuthHeader = new String(new BASE64Decoder().decodeBuffer(authHeader)); -%> -

Basic authentication credentials: <%=decAuthHeader%>

-<% } %> -

Form sample

- - \ No newline at end of file diff --git a/id/oa/src/main/webapp/js/common.js b/id/oa/src/main/webapp/js/common.js new file mode 100644 index 000000000..59b7b4e0e --- /dev/null +++ b/id/oa/src/main/webapp/js/common.js @@ -0,0 +1,32 @@ +function gup(name) { + name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); + var regexS = "[\\?&]"+name+"=([^&#]*)"; + var regex = new RegExp( regexS ); + var results = regex.exec( window.location.href ); + if( results == null ) + return ""; + else + return results[1]; +} +function jumpToAnker() { + var jump = gup("jump"); + if (jump != "") { + location.hash="#"+jump; + } +} +function PVP2LoginIframe(url) { + var el = document.getElementById("demonstrator_leftcontent"); + + var iframe = document.createElement("iframe"); + iframe.setAttribute("src", url); + iframe.setAttribute("width", "240"); + iframe.setAttribute("height", "220"); + iframe.setAttribute("frameborder", "0"); + iframe.setAttribute("scrolling", "no"); + iframe.setAttribute("title", "Login"); + + var button = document.getElementById("submitbutton"); + button.parentNode.removeChild(button); + + el.appendChild(iframe, el); +} diff --git a/id/oa/src/main/webapp/stateful_login.jsp b/id/oa/src/main/webapp/stateful_login.jsp deleted file mode 100644 index eaede507f..000000000 --- a/id/oa/src/main/webapp/stateful_login.jsp +++ /dev/null @@ -1,29 +0,0 @@ -<%@ page import="javax.servlet.http.*" %> -<% - /* check request's remote IP address - must be moa-id-proxy's address */ - String remoteIPAddress = request.getRemoteAddr(); - if (! "127.0.0.1".equals(remoteIPAddress)) { /* Substitute "127.0.0.1" for moa-id-proxy's IP address */ - response.setStatus(403); - return; - } - - /* store authentication data in cookies */ - String fn = request.getParameter("FamilyName"); - String gn = request.getParameter("GivenName"); - /* set cookie domain and cookie path ! */ - String cookieDomain = ".test.test"; /* Set this to the common domain of moa-id-proxy and of the online application */ - String cookiePath = request.getContextPath(); /* Set this to the context path of the online application */ - - Cookie cfn = new Cookie("familyname", fn); - cfn.setDomain(cookieDomain); - cfn.setPath(cookiePath); - response.addCookie(cfn); - - Cookie cgn = new Cookie("givenname", gn); - cgn.setDomain(cookieDomain); - cgn.setPath(cookiePath); - response.addCookie(cgn); - - /* redirect to online application's start page */ - response.sendRedirect("http://oa.test.test:8080/oa/index.jsp"); /* Substitute for URL in online application */ -%> -- cgit v1.2.3