diff options
Diffstat (limited to 'id/server')
81 files changed, 4395 insertions, 462 deletions
diff --git a/id/server/auth/pom.xml b/id/server/auth/pom.xml index 96f51666f..98ec73a25 100644 --- a/id/server/auth/pom.xml +++ b/id/server/auth/pom.xml @@ -132,17 +132,25 @@ </exclusion> </exclusions> </dependency> - <dependency> + + <!-- Adding eIDAS module dependency automatically adds eIDAS protocol capabilities. --> + <dependency> + <groupId>MOA.id.server.modules</groupId> + <artifactId>moa-id-module-eIDAS</artifactId> + </dependency> + + +<!-- <dependency> <groupId>eu.stork</groupId> <artifactId>oasis-dss-api</artifactId> <version>1.0.0-RELEASE</version> - </dependency> + </dependency> --> - <!-- Adding stork module dependency automatically adds stork capabilities. --> - <dependency> + <!-- Adding stork module dependency automatically adds stork capabilities. --> +<!-- <dependency> <groupId>MOA.id.server.modules</groupId> <artifactId>moa-id-module-stork</artifactId> - </dependency> + </dependency> --> <!-- Adding monitoring module dependency automatically adds monitoring capabilities. --> <dependency> diff --git a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml index 8f01ca22b..a67549ef3 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml @@ -93,6 +93,16 @@ <from>^/stork2/RetrieveMandate$</from> <to type="forward">/dispatcher?mod=id_stork2&action=MandateRetrievalRequest&%{query-string}</to> </rule> + + <!-- eIDAS protocol --> + <rule match-type="regex"> + <from>^/eidas/ColleagueRequest$</from> + <to type="forward">/dispatcher?mod=eidas&action=AuthenticationRequest&%{query-string}</to> + </rule> + <rule match-type="regex"> + <from>^/eidas/metadata$</from> + <to type="forward">/dispatcher?mod=eidas&action=MetadataRequest&%{query-string}</to> + </rule> <rule match-type="regex"> diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml b/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml new file mode 100644 index 000000000..9fef4fa2e --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + +<properties> + <comment>SWModule encrypt with JKS.</comment> + <entry key="keystorePath">keys/eidasKeyStore.jks</entry> + <entry key="keyStorePassword">local-demo</entry> + <entry key="keyPassword">local-demo</entry> + + <!-- Management of the encryption activation --> + <entry key="encryptionActivation">eIDAS/encryptionConf.xml</entry> + + + <entry key="responseToPointIssuer.BE">CN=local-demo-cert, OU=DIGIT, O=European Comission, L=Brussels, ST=Belgium,C=BE</entry> + <entry key="responseToPointSerialNumber.BE">54C8F779</entry> + + <!-- If not present then no decryption will be applied on response --> + <entry key="responseDecryptionIssuer">CN=local-demo-cert, OU=DIGIT, O=European Comission, L=Brussels, ST=Belgium, C=BE</entry> + <entry key="serialNumber">54C8F779</entry> + + <entry key="keystoreType">JKS</entry> +</properties>
\ No newline at end of file diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/SamlEngine_basics.xml b/id/server/data/deploy/conf/moa-id/eIDAS/SamlEngine_basics.xml new file mode 100644 index 000000000..2327fb0d8 --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/eIDAS/SamlEngine_basics.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + +<properties> + <comment>SAML constants for AuthnRequests and Responses.</comment> + + <!-- + Types of consent obtained from the user for this authentication and + data transfer. + Allow values: 'unspecified'. + --> + <entry key="consentAuthnRequest">unspecified</entry> + <!-- + Allow values: 'obtained', 'prior', 'curent-implicit', 'curent-explicit', 'unspecified'. + --> + <entry key="consentAuthnResponse">obtained</entry> + + <!--URI representing the classification of the identifier + Allow values: 'entity'. + --> + <entry key="formatEntity">entity</entry> + + <!--Only HTTP-POST binding is only supported for inter PEPS--> + <!--The SOAP binding is only supported for direct communication between SP-MW and VIdP--> + <entry key="protocolBinding">HTTP-POST</entry> + + <entry key="eIDSectorShare">false</entry> + <entry key="eIDCrossSectorShare">false</entry> + <entry key="eIDCrossBorderShare">false</entry> + + <!-- Attributes with require option --> + <entry key="isRequired">true</entry> + + <!-- A friendly name for the attribute that can be displayed to a user --> + <entry key="friendlyName">false</entry> + + <!--PEPS in the Service Provider's country--> + <entry key="requester">http://S-PEPS.gov.xx</entry> + + <!--PEPS in the citizen's origin country--> + <entry key="responder">http://C-PEPS.gov.xx</entry> + + <!--Subject cannot be confirmed on or after this seconds time (positive number)--> + <entry key="timeNotOnOrAfter">300</entry> + + <!--Validation IP of the response--> + <entry key="ipAddrValidation">false</entry> + + <!--One time use--> + <entry key="oneTimeUse">true</entry> + + <!--Subject Attribute Definitions--> + <entry key="eIdentifier">http://www.stork.gov.eu/1.0/eIdentifier</entry> + <entry key="givenName">http://www.stork.gov.eu/1.0/givenName</entry> + <entry key="surname">http://www.stork.gov.eu/1.0/surname</entry> + <entry key="inheritedFamilyName">http://www.stork.gov.eu/1.0/inheritedFamilyName</entry> + <entry key="adoptedFamilyName">http://www.stork.gov.eu/1.0/adoptedFamilyName</entry> + <entry key="gender">http://www.stork.gov.eu/1.0/gender</entry> + <entry key="dateOfBirth">http://www.stork.gov.eu/1.0/dateOfBirth</entry> + <entry key="countryCodeOfBirth">http://www.stork.gov.eu/1.0/countryCodeOfBirth</entry> + <entry key="nationalityCode">http://www.stork.gov.eu/1.0/nationalityCode</entry> + <entry key="maritalStatus">http://www.stork.gov.eu/1.0/maritalStatus</entry> + <entry key="textResidenceAddress">http://www.stork.gov.eu/1.0/textResidenceAddress</entry> + <entry key="canonicalResidenceAddress">http://www.stork.gov.eu/1.0/canonicalResidenceAddress</entry> + <entry key="eMail">http://www.stork.gov.eu/1.0/eMail</entry> + <entry key="title">http://www.stork.gov.eu/1.0/title</entry> + <entry key="residencePermit">http://www.stork.gov.eu/1.0/residencePermit</entry> + <entry key="pseudonym">http://www.stork.gov.eu/1.0/pseudonym</entry> + <entry key="age">http://www.stork.gov.eu/1.0/age</entry> + <entry key="isAgeOver">http://www.stork.gov.eu/1.0/isAgeOver</entry> + <entry key="signedDoc">http://www.stork.gov.eu/1.0/signedDoc</entry> + <entry key="citizenQAALevel">http://www.stork.gov.eu/1.0/citizenQAALevel</entry> + <entry key="fiscalNumber">http://www.stork.gov.eu/1.0/fiscalNumber</entry> + <entry key="unknown">http://www.stork.gov.eu/1.0/unknown</entry> + + + <!--Subject Attribute Definitions eidas format, natural person --> + <entry key="eidas/attributes/CurrentFamilyName">http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</entry> + <entry key="eidas/attributes/CurrentGivenName">http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</entry> + <entry key="eidas/attributes/DateOfBirth">http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</entry> + <entry key="eidas/attributes/PersonIdentifier">http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</entry> + <entry key="eidas/attributes/BirthName">http://eidas.europa.eu/attributes/naturalperson/BirthName</entry> + <entry key="eidas/attributes/PlaceOfBirth">http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth</entry> + <entry key="eidas/attributes/CurrentAddress">http://eidas.europa.eu/attributes/naturalperson/CurrentAddress</entry> + <entry key="eidas/attributes/Gender">http://eidas.europa.eu/attributes/naturalperson/Gender</entry> + <!--Subject Attribute Definitions eidas format, legal person --> + <entry key="eidas/attributes/LegalPersonIdentifier">http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier</entry> + <entry key="eidas/attributes/LegalAddress">http://eidas.europa.eu/attributes/legalperson/LegalAddress</entry> + <entry key="eidas/attributes/LegalName">http://eidas.europa.eu/attributes/legalperson/LegalName</entry> + <entry key="eidas/attributes/VATRegistration">http://eidas.europa.eu/attributes/legalperson/VATRegistration</entry> + <entry key="eidas/attributes/TaxReference">http://eidas.europa.eu/attributes/legalperson/TaxReference</entry> + <entry key="eidas/attributes/D-2012-17-EUIdentifier">http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier</entry> + <entry key="eidas/attributes/LEI">http://eidas.europa.eu/attributes/legalperson/LEI</entry> + <entry key="eidas/attributes/EORI">http://eidas.europa.eu/attributes/legalperson/EORI</entry> + <entry key="eidas/attributes/SEED">http://eidas.europa.eu/attributes/legalperson/SEED</entry> + <entry key="eidas/attributes/SIC">http://eidas.europa.eu/attributes/legalperson/SIC</entry> + +</properties>
\ No newline at end of file diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml b/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml new file mode 100644 index 000000000..745580428 --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + +<properties> + <comment>SWModule sign with JKS.</comment> + <entry key="keystorePath">keys/eidasKeyStore_Service_CB.jks</entry> + <entry key="keyStorePassword">local-demo</entry> + <entry key="keyPassword">local-demo</entry> + <entry key="issuer">CN=cpeps-cb-demo-certificate, OU=STORK, O=CPEPS, L=EU, ST=EU, C=CB</entry> + <entry key="serialNumber">54C8F839</entry> + <entry key="keystoreType">JKS</entry> + + <entry key="metadata.keystorePath">keys/eidasKeyStore_METADATA.jks</entry> + <entry key="metadata.keyStorePassword">local-demo</entry> + <entry key="metadata.keyPassword">local-demo</entry> + <entry key="metadata.issuer">CN=metadata, OU=DIGIT, O=EC, L=Brussels, ST=EU, C=BE</entry> + <entry key="metadata.serialNumber">561BC0C8</entry> + <entry key="metadata.keystoreType">JKS</entry> +</properties> diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/encryptionConf.xml b/id/server/data/deploy/conf/moa-id/eIDAS/encryptionConf.xml new file mode 100644 index 000000000..ff8307f10 --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/eIDAS/encryptionConf.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> +<properties> + <entry key="EncryptTo.CA">false</entry> + + <entry key="EncryptTo.CB">false</entry> + + <entry key="EncryptTo.CC">false</entry> + + <entry key="EncryptTo.CD">false</entry> + + <entry key="EncryptTo.CF">false</entry> + +</properties>
\ No newline at end of file diff --git a/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore.jks b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore.jks Binary files differnew file mode 100644 index 000000000..c8a28d0ae --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore.jks diff --git a/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_METADATA.jks b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_METADATA.jks Binary files differnew file mode 100644 index 000000000..e52051dd8 --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_METADATA.jks diff --git a/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_Service_CB.jks b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_Service_CB.jks Binary files differnew file mode 100644 index 000000000..9275f9fdd --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/keys/eidasKeyStore_Service_CB.jks diff --git a/id/server/data/deploy/conf/moa-id/moa-id.properties b/id/server/data/deploy/conf/moa-id/moa-id.properties index 49e69c561..09568ce68 100644 --- a/id/server/data/deploy/conf/moa-id/moa-id.properties +++ b/id/server/data/deploy/conf/moa-id/moa-id.properties @@ -48,6 +48,12 @@ stork.fakeIdL.keygroup= stork.documentservice.url= +## eIDAS protocol configuration +moa.id.protocols.eIDAS.samlengine.config.file=eIDAS/SamlEngine_basics.xml +moa.id.protocols.eIDAS.samlengine.sign.config.file=eIDAS/SignModule.xml +moa.id.protocols.eIDAS.samlengine.enc.config.file=eIDAS/EncryptModule.xml +moa.id.protocols.eIDAS.metadata.validation.truststore=eIDAS_metadata + ##Protocol configuration## #PVP2 protocols.pvp2.idp.ks.file=file:$PATH_TO_CONFIG$/conf/moa-id/keys/moa_idp[password].p12 diff --git a/id/server/data/deploy/conf/moa-spss/SampleMOASPSSConfiguration.xml b/id/server/data/deploy/conf/moa-spss/SampleMOASPSSConfiguration.xml index 9d130971d..ce5a21d57 100644 --- a/id/server/data/deploy/conf/moa-spss/SampleMOASPSSConfiguration.xml +++ b/id/server/data/deploy/conf/moa-spss/SampleMOASPSSConfiguration.xml @@ -47,6 +47,10 @@ <cfg:Id>C-PEPS</cfg:Id> <cfg:TrustAnchorsLocation>trustProfiles/C-PEPS</cfg:TrustAnchorsLocation> </cfg:TrustProfile> + <cfg:TrustProfile> + <cfg:Id>eIDAS_metadata</cfg:Id> + <cfg:TrustAnchorsLocation>trustProfiles/eIDAS_metadata</cfg:TrustAnchorsLocation> + </cfg:TrustProfile> </cfg:PathValidation> <cfg:RevocationChecking> <cfg:EnableChecking>true</cfg:EnableChecking> diff --git a/id/server/data/deploy/conf/moa-spss/trustProfiles/eIDAS_metadata/eIDAS_test_node.crt b/id/server/data/deploy/conf/moa-spss/trustProfiles/eIDAS_metadata/eIDAS_test_node.crt new file mode 100644 index 000000000..14e5e5cb5 --- /dev/null +++ b/id/server/data/deploy/conf/moa-spss/trustProfiles/eIDAS_metadata/eIDAS_test_node.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIFMTCCAxkCBFYbwMgwDQYJKoZIhvcNAQENBQAwXTELMAkGA1UEBhMCQkUxCzAJBgNVBAgMAkVV +MREwDwYDVQQHDAhCcnVzc2VsczELMAkGA1UECgwCRUMxDjAMBgNVBAsMBURJR0lUMREwDwYDVQQD +DAhtZXRhZGF0YTAeFw0xNTEwMTIxNDE2NDBaFw0xNjEwMTExNDE2NDBaMF0xCzAJBgNVBAYTAkJF +MQswCQYDVQQIDAJFVTERMA8GA1UEBwwIQnJ1c3NlbHMxCzAJBgNVBAoMAkVDMQ4wDAYDVQQLDAVE +SUdJVDERMA8GA1UEAwwIbWV0YWRhdGEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN +5mYsOKzSJ9ksT9dHtFOztF1M8GIMeBLm6chIvtKHwXVLzO53RKhcOwt0j847VL6m5PcAAp57SutC +DeukA8p6UCUA905p+m7+dt7iEsUV3yje4M8dDFS/LwEF9GhFm3v471ZRYPDW769v14QkmnA9vxWB +WAj4WcMRMats9choHJdnRa1xUnVjx8yMojoVaPwt1tkG/rRnPev2o0g+VI63XkYd1pLKAU5Pt+n7 +LevLPJsvgkKLQhEB7bvMG1tZ1P4fJ0n3FOHmfLHJ/yEWA+hHXorX5T3G8Fq6GsI5O/c1zkZ7QMSw +WwzXDbq5qrfyzesdlTPfdsPnFIRddCgx8NuVwI+brlYDSdLGEm+byfM9W4WmfDN6SK1oGMSibuz7 +K49Xh0MFVKNyxT9hCz309UiV71RGnveZxdMGu4vdzP74Ll3G48IIgQ4ymFPMONYBesuorxDunSqs +R2F1+Th7k7UXL1xblFRaEyqdHlvhVrJqDP6sM9k3lM75aN4L4QMOyKRAqar+Q7f7NoUcx8cvHfqD +GLJUPcqn2msMa3mAXO5ihA2ERN41wmnmeJzsd/UiFkaqIvXUTZVwxUfQWn3D9uCg2lRAvOTHydkP +Cfwj4BtL0P9L3eSZ9NM8IGlTmlyApp2bPlzO92BsE8RE7feOmSLZESDKosqkQzZo2CMr/7V9XQID +AQABMA0GCSqGSIb3DQEBDQUAA4ICAQALfSi+sa90MbJkAeTIA/la1ibtRkPX6jIjHBvkeq8IYEZi +XxjJvI4CuQY6WSPMoDY0w9iJvKIygCxRlVi77CtFzu/otOLrXb8ozInopykRMIH4TyVmKYf//CoE +fkQ3vThaf1JLpKpLuhtqHwV03f7jwODaJBqvqdaBX3VHHMPDOeAWQTAd2abMoHgYRlUgB9TKcbJ1 +akWUyX7hnwZSCiKWbL4nrwsFJc0skFVkfjEQxlZUeRXj/bKgnb0BYUsPsFfxXKJIsIc8CmXGvxKz +B5TSpYIR79WliT9Fo8T1dJ9a/wr+bOXeM/aSUxLechCl+uDuP8yI2iRz9LT++/16HOrRSUuefHpo +7wJLJnALMABW21eMwS2XBInUBrBN9CVGAJUDF6GQWMbfxA8x0uh4oKoa/4stP5maaf/FBe52pNNv +Tacb7P3xJc0mS7jatuAHH0UfXy3+3D3z+SJY4Vy2a1cj5U1nUuxxwIRwsoRtWph0BER4RlOz4lXS +N8ZK9ahgmCsndm+eDvIJm706s7bd8m/X8Xc/lMK+eKhrK6uIIMmkwbdzbgsOS7Plj9IMGm0S4Kdb +rnAKhkhAXUi4zbd55aTx1kDodpid/dYPiqxSauyYmCXKbyFCAfY76Zw9SuFBRJClx4h5Mxb/EEpq +1WHM9IyZshufnuZ587WzqtGmJJubTA== +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/id/server/idserverlib/pom.xml b/id/server/idserverlib/pom.xml index afc432628..532b74209 100644 --- a/id/server/idserverlib/pom.xml +++ b/id/server/idserverlib/pom.xml @@ -33,7 +33,7 @@ <version>6.1.1</version>
<scope>test</scope>
</dependency>
- <dependency>
+<!-- <dependency>
<groupId>eu.stork</groupId>
<artifactId>oasis-dss-api</artifactId>
<version>1.0.0-RELEASE</version>
@@ -43,7 +43,7 @@ <artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
- </dependency>
+ </dependency> -->
<dependency>
<groupId>at.gv.egiz.components</groupId>
@@ -90,6 +90,11 @@ <artifactId>Commons</artifactId>
<version>1.4.0</version>
</dependency> -->
+<!-- <dependency>
+ <groupId>eu.stork</groupId>
+ <artifactId>SamlEngine</artifactId>
+ <version>1.5.1</version>
+ </dependency> -->
<dependency>
@@ -467,11 +472,11 @@ </dependency> -->
- <dependency>
+<!-- <dependency>
<groupId>eu.stork</groupId>
<artifactId>SamlEngine</artifactId>
<version>1.5.1</version>
- </dependency>
+ </dependency> -->
<!-- spring -->
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index 022ec9def..038a35d42 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -14,9 +14,10 @@ import javax.activation.CommandMap; import javax.activation.MailcapCommandMap; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigLoader; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector; +import at.gv.egovernment.moa.id.util.AxisSecureSocketFactory; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.id.util.SSLUtils; import at.gv.egovernment.moa.logging.Logger; @@ -157,7 +158,7 @@ public class MOAIDAuthInitializer { // Starts the session cleaner thread to remove unpicked authentication data AuthenticationSessionCleaner.start(); - AuthConfigLoader.start(); + MOAGarbageCollector.start(); } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java index 57a5316e8..fe29dd2b7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java @@ -32,7 +32,9 @@ import java.security.PrivateKey; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.Iterator; import java.util.List; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -62,6 +64,7 @@ import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameTy import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.auth.data.IdentityLink; import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; @@ -69,6 +72,7 @@ import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.auth.exception.DynamicOABuildException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; @@ -790,16 +794,24 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { //set STORK attributes if (extractor.containsAttribute(PVPConstants.EID_STORK_TOKEN_NAME)) { - authData.setStorkAuthnResponse(extractor.getSingleAttributeValue(PVPConstants.EID_STORK_TOKEN_NAME)); - authData.setForeigner(true); + try { + authData.setGenericData(AuthenticationSessionStorageConstants.STORK_RESPONSE, + extractor.getSingleAttributeValue(PVPConstants.EID_STORK_TOKEN_NAME)); + authData.setForeigner(true); + + } catch (SessionDataStorageException e) { + Logger.warn("STORK Response can not stored into generic authData.", e); + + } - } - - if (!extractor.getSTORKAttributes().isEmpty()) { - authData.setStorkAttributes(extractor.getSTORKAttributes()); - authData.setForeigner(true); } + +// if (!extractor.getSTORKAttributes().isEmpty()) { +// authData.setStorkAttributes(extractor.getSTORKAttributes()); +// authData.setForeigner(true); +// +// } authData.setSsoSession(true); authData.setInterfederatedSSOSession(true); @@ -889,10 +901,22 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { authData.setBkuURL(session.getBkuURL()); - authData.setStorkAttributes(session.getStorkAttributes()); - authData.setStorkAuthnResponse(session.getStorkAuthnResponse()); - authData.setStorkRequest(session.getStorkAuthnRequest()); - + //copy all generic authentication information to authData + if (session.getGenericSessionDataStorage() != null && + !session.getGenericSessionDataStorage().isEmpty()) { + Iterator<Entry<String, Object>> copyInterator = session.getGenericSessionDataStorage().entrySet().iterator(); + while (copyInterator.hasNext()) { + Entry<String, Object> element = copyInterator.next(); + try { + authData.setGenericData(element.getKey(), element.getValue()); + + } catch (SessionDataStorageException e) { + Logger.warn("Can not add generic authData with key:" + element.getKey(), e); + + } + } + } + authData.setSignerCertificate(session.getEncodedSignerCertificate()); authData.setAuthBlock(session.getAuthBlock()); @@ -923,9 +947,12 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } if (MiscUtil.isEmpty(authData.getCcc())) { - if (authData.getStorkAuthnRequest() != null) { - authData.setCcc(authData.getStorkAuthnRequest().getCitizenCountryCode()); - Logger.info("Can not extract country from certificate -> Use country from STORK request."); + String storkCCC = authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_CCC, String.class); + + if (MiscUtil.isNotEmpty(storkCCC)) { + authData.setCcc(storkCCC); + Logger.info("Can not extract country from certificate -> Use country:" + storkCCC + " from STORK request."); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SignatureVerificationUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SignatureVerificationUtils.java new file mode 100644 index 000000000..e321c9d05 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SignatureVerificationUtils.java @@ -0,0 +1,172 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.builder; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.id.auth.exception.ServiceException; +import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; +import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; + +/** + * @author tlenz + * + */ +public class SignatureVerificationUtils { + /** shortcut for XMLNS namespace URI */ + private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI; + /** shortcut for MOA namespace URI */ + private static final String MOA_NS_URI = Constants.MOA_NS_URI; + /** The DSIG-Prefix */ + private static final String DSIG = Constants.DSIG_PREFIX + ":"; + + /** The document containing the <code>VerifyXMLsignatureRequest</code> */ + private Document requestDoc_; + /** the <code>VerifyXMLsignatureRequest</code> root element */ + private Element requestElem_; + + + public SignatureVerificationUtils() throws BuildException { + try { + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + requestDoc_ = docBuilder.newDocument(); + requestElem_ = requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest"); + requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI); + requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX, Constants.DSIG_NS_URI); + requestDoc_.appendChild(requestElem_); + + } catch (Throwable t) { + throw new BuildException( + "builder.00", + new Object[] {"VerifyXMLSignatureRequest", t.toString()}, + t); + } + } + + public VerifyXMLSignatureResponse verify(byte[] signature, String trustProfileID) throws MOAIDException { + try { + //build signature-verification request + Element domVerifyXMLSignatureRequest = build(signature, trustProfileID); + + //send signature-verification to MOA-SP + Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker() + .verifyXMLSignature(domVerifyXMLSignatureRequest); + + // parses the <VerifyXMLSignatureResponse> + VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser( + domVerifyXMLSignatureResponse).parseData(); + + return verifyXMLSignatureResponse; + + } catch (ParseException e) { + Logger.error("Build signature-verification request FAILED." ,e); + throw e; + + } catch (ServiceException e) { + Logger.error("MOA-SP signature verification FAILED." ,e); + throw e; + + } + + } + + /** + * Builds a <code><VerifyXMLSignatureRequest></code> + * from an IdentityLink with a known trustProfileID which + * has to exist in MOA-SP + * @param signature - The XML signature as byte[] + * @param trustProfileID - a preconfigured TrustProfile at MOA-SP + * + * @return Element - The complete request as Dom-Element + * + * @throws ParseException + */ + private Element build(byte[] signature, String trustProfileID) + throws ParseException + { + try { + // build the request + Element verifiySignatureInfoElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo"); + requestElem_.appendChild(verifiySignatureInfoElem); + Element verifySignatureEnvironmentElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment"); + verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem); + Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content"); + verifySignatureEnvironmentElem.appendChild(base64ContentElem); + + // insert the base64 encoded signature + String base64EncodedAssertion = Base64Utils.encode(signature); + //replace all '\r' characters by no char. + StringBuffer replaced = new StringBuffer(); + for (int i = 0; i < base64EncodedAssertion.length(); i ++) { + char c = base64EncodedAssertion.charAt(i); + if (c != '\r') { + replaced.append(c); + } + } + base64EncodedAssertion = replaced.toString(); + Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion); + base64ContentElem.appendChild(base64Content); + + // specify the signature location + Element verifySignatureLocationElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation"); + verifiySignatureInfoElem.appendChild(verifySignatureLocationElem); + Node signatureLocation = requestDoc_.createTextNode(DSIG + "Signature"); + verifySignatureLocationElem.appendChild(signatureLocation); + + // signature manifest params + Element signatureManifestCheckParamsElem = + requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams"); + requestElem_.appendChild(signatureManifestCheckParamsElem); + signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false"); + + Element returnHashInputDataElem = + requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData"); + requestElem_.appendChild(returnHashInputDataElem); + + //add trustProfileID + Element trustProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID"); + trustProfileIDElem.appendChild(requestDoc_.createTextNode(trustProfileID)); + requestElem_.appendChild(trustProfileIDElem); + } catch (Throwable t) { + throw new ParseException("builder.00", + new Object[] { "VerifyXMLSignatureRequest (IdentityLink)" }, t); + } + + return requestElem_; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index 59482c4a8..ae3ec9a9b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -44,13 +44,15 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.map.HashedMap; -import eu.stork.peps.auth.commons.IPersonalAttributeList; -import eu.stork.peps.auth.commons.STORKAuthnRequest; +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; import at.gv.egovernment.moa.id.data.MISMandate; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.MiscUtil; /** * Session data to be stored between <code>AuthenticationServer</code> API calls. @@ -215,129 +217,28 @@ public class AuthenticationSession implements Serializable { * accept. The infobox identifiers are comma separated. */ private String pushInfobox; - - /** - * The STORK AuthRequest to be sent to the C-PEPS - */ - private STORKAuthnRequest storkAuthnRequest; - - private String storkAuthnResponse; - + // private AuthenticationData authData; // protocol selection private String action; private String modul; + private String processInstanceId; + private boolean authenticated; private boolean authenticatedUsed = false; private boolean ssoRequested = false; - + private String QAALevel = null; - -// private OAuth20SessionObject oAuth20SessionObject; - - // /** - // * Indicates if target from configuration is used or not - // */ - // private boolean useTargetFromConfig; - - // /** - // * Authentication data for the assertion - // */ - // private AuthenticationData assertionAuthData; - // - // /** - // * Persondata for the assertion - // */ - // private String assertionPrPerson; - // - // /** - // * Authblock for the assertion - // */ - // private String assertionAuthBlock; - // - // /** - // * Identitylink assertion for the (MOA) assertion - // */ - // private String assertionIlAssertion; - // - // /** - // * Signer certificate (base64 encoded) for the assertion - // */ - // private String assertionSignerCertificateBase64; - // - // /** - // * bussiness service for the assertion - // */ - // boolean assertionBusinessService; - // - // /** - // * timestamp logging when authentication session has been created - // */ - // private Date timestampStart; - // private CreateXMLSignatureResponse XMLCreateSignatureResponse; - + private VerifyXMLSignatureResponse XMLVerifySignatureResponse; private boolean isForeigner; - - private IPersonalAttributeList storkAttributes; + private Map<String, Object> genericSessionDataStorate = new HashedMap<String, Object>(); - //Temporary store SignRequest for local processing - private String signedDoc; - //Temporary store SAMLResponse for processing after user signed signedDoc locally - private String SAMLResponse; - // - private StringBuffer returnURL; - private IPersonalAttributeList authnResponseGetPersonalAttributeList; - private String authnContextClassRef; - // private String requestedProtocolURL = null; - - private String processInstanceId; - - public String getAuthnContextClassRef() { - return authnContextClassRef; - } - - public void setAuthnContextClassRef(String authnContextClassRef) { - this.authnContextClassRef = authnContextClassRef; - } - - public IPersonalAttributeList getAuthnResponseGetPersonalAttributeList() { - return authnResponseGetPersonalAttributeList; - } - - public void setAuthnResponseGetPersonalAttributeList(IPersonalAttributeList authnResponseGetPersonalAttributeList) { - this.authnResponseGetPersonalAttributeList = authnResponseGetPersonalAttributeList; - } - - public String getSAMLResponse() { - return SAMLResponse; - } - - public void setSAMLResponse(String samlResponse) { - SAMLResponse = samlResponse; - } - - public StringBuffer getReturnURL() { - return returnURL; - } - - public void setReturnURL(StringBuffer returnURL) { - this.returnURL = returnURL; - } - - public String getSignedDoc() { - return signedDoc; - } - - public void setSignedDoc(String signedDoc) { - this.signedDoc = signedDoc; - } - public String getModul() { return modul; } @@ -353,15 +254,7 @@ public class AuthenticationSession implements Serializable { public void setAction(String action) { this.action = action; } - - // public AuthenticationData getAuthData() { - // return authData; - // } - // - // public void setAuthData(AuthenticationData authData) { - // this.authData = authData; - // } - + public boolean isAuthenticatedUsed() { return authenticatedUsed; } @@ -378,14 +271,6 @@ public class AuthenticationSession implements Serializable { this.authenticated = authenticated; } - // public String getRequestedProtocolURL() { - // return requestedProtocolURL; - // } - // - // public void setRequestedProtocolURL(String requestedProtocolURL) { - // this.requestedProtocolURL = requestedProtocolURL; - // } - /** * Constructor for AuthenticationSession. * @@ -395,8 +280,7 @@ public class AuthenticationSession implements Serializable { public AuthenticationSession(String id, Date created) { sessionID = id; sessionCreated = created; - // setTimestampStart(); -// infoboxValidators = new ArrayList(); + } public X509Certificate getSignerCertificate() { @@ -760,98 +644,7 @@ public class AuthenticationSession implements Serializable { public void setIssueInstant(String issueInstant) { this.issueInstant = issueInstant; } - -// /** -// * Returns the iterator to the stored infobox validators. -// * -// * @return Iterator -// */ -// public Iterator getInfoboxValidatorIterator() { -// if (infoboxValidators == null) return null; -// return infoboxValidators.iterator(); -// } - - // /** - // * Adds an infobox validator class to the stored infobox validators. - // * - // * @param infoboxIdentifier - // * the identifier of the infobox the validator belongs to - // * @param infoboxFriendlyName - // * the friendly name of the infobox - // * @param infoboxValidator - // * the infobox validator to add - // */ - // public Iterator addInfoboxValidator(String infoboxIdentifier, - // String infoboxFriendlyName, InfoboxValidator infoboxValidator) { - // if (infoboxValidators == null) - // infoboxValidators = new ArrayList(); - // Vector v = new Vector(3); - // v.add(infoboxIdentifier); - // v.add(infoboxFriendlyName); - // v.add(infoboxValidator); - // infoboxValidators.add(v); - // return infoboxValidators.iterator(); - // } - -// /** -// * Tests for pending input events of the infobox validators. -// * -// * @return true if a validator has a form to show -// */ -// public boolean isValidatorInputPending() { -// boolean result = false; -// Iterator iter = getInfoboxValidatorIterator(); -// if (iter != null) { -// while (!result && iter.hasNext()) { -// Vector infoboxValidatorVector = (Vector) iter.next(); -// InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector.get(2); -// if (!ParepUtils.isEmpty(infoboxvalidator.getForm())) result = true; -// } -// } -// return result; -// } - - // /** - // * Returns the first pending infobox validator. - // * - // * @return the infobox validator class - // */ - // public InfoboxValidator getFirstPendingValidator() { - // Iterator iter = getInfoboxValidatorIterator(); - // if (iter != null) { - // while (iter.hasNext()) { - // Vector infoboxValidatorVector = (Vector) iter.next(); - // InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector - // .get(2); - // String form = infoboxvalidator.getForm(); - // if (!ParepUtils.isEmpty(form)) - // return infoboxvalidator; - // } - // } - // return null; - // } - - // /** - // * Returns the input form of the first pending infobox validator input - // * processor. - // * - // * @return the form to show - // */ - // public String getFirstValidatorInputForm() { - // Iterator iter = getInfoboxValidatorIterator(); - // if (iter != null) { - // while (iter.hasNext()) { - // Vector infoboxValidatorVector = (Vector) iter.next(); - // InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector - // .get(2); - // String form = infoboxvalidator.getForm(); - // if (!ParepUtils.isEmpty(form)) - // return form; - // } - // } - // return null; - // } - + /** * Returns domain identifier (the register and number in the register parameter). * <code>null</code> in the case of not a business service. @@ -954,26 +747,7 @@ public class AuthenticationSession implements Serializable { public void setMandateReferenceValue(String mandateReferenceValue) { this.mandateReferenceValue = mandateReferenceValue; } - - /** - * Gets the STORK SAML AuthnRequest - * - * @return STORK SAML AuthnRequest - */ - public STORKAuthnRequest getStorkAuthnRequest() { - return storkAuthnRequest; - } - - /** - * Sets the STORK SAML AuthnRequest - * - * @param storkAuthnRequest - * STORK SAML AuthnRequest - */ - public void setStorkAuthnRequest(STORKAuthnRequest storkAuthnRequest) { - this.storkAuthnRequest = storkAuthnRequest; - } - + public String getCcc() { return ccc; } @@ -1054,24 +828,8 @@ public class AuthenticationSession implements Serializable { } /** - * Memorizes the stork attribute list. - * - * @param personalAttributeList the new stork attributes - */ - public void setStorkAttributes(IPersonalAttributeList personalAttributeList) { - this.storkAttributes = personalAttributeList; - } - - /** - * Recalls the stork attribute list. - * - * @return the stork attributes - */ - public IPersonalAttributeList getStorkAttributes() { - return this.storkAttributes; - } - - /** + * eIDAS QAA level + * * @return the qAALevel */ public String getQAALevel() { @@ -1079,6 +837,8 @@ public class AuthenticationSession implements Serializable { } /** + * set QAA level in eIDAS form + * * @param qAALevel the qAALevel to set */ public void setQAALevel(String qAALevel) { @@ -1086,20 +846,6 @@ public class AuthenticationSession implements Serializable { } /** - * @return the storkAuthnResponse - */ - public String getStorkAuthnResponse() { - return storkAuthnResponse; - } - - /** - * @param storkAuthnResponse the storkAuthnResponse to set - */ - public void setStorkAuthnResponse(String storkAuthnResponse) { - this.storkAuthnResponse = storkAuthnResponse; - } - - /** * @return the sessionCreated */ public Date getSessionCreated() { @@ -1121,5 +867,89 @@ public class AuthenticationSession implements Serializable { public void setProcessInstanceId(String processInstanceId) { this.processInstanceId = processInstanceId; } + + public Map<String, Object> getGenericSessionDataStorage() { + return genericSessionDataStorate; + } + + /** + * Returns a generic session-data object with is stored with a specific identifier + * + * @param key The specific identifier of the session-data object + * @return The session-data object or null if no data is found with this key + */ + public Object getGenericDataFromSession(String key) { + if (MiscUtil.isNotEmpty(key)) { + return genericSessionDataStorate.get(key); + + } + + Logger.warn("Can not load generic session-data with key='null'"); + return null; + + } + + /** + * Returns a generic session-data object with is stored with a specific identifier + * + * @param key The specific identifier of the session-data object + * @param clazz The class type which is stored with this key + * @return The session-data object or null if no data is found with this key + */ + public <T> T getGenericDataFromSession(String key, final Class<T> clazz) { + if (MiscUtil.isNotEmpty(key)) { + Object data = genericSessionDataStorate.get(key); + + if (data == null) + return null; + + try { + @SuppressWarnings("unchecked") + T test = (T) data; + return test; + + } catch (Exception e) { + Logger.warn("Generic authentication-data object can not be casted to requsted type", e); + return null; + + } + + } + + Logger.warn("Can not load generic session-data with key='null'"); + return null; + + } + + /** + * Store a generic data-object to session with a specific identifier + * + * @param key Identifier for this data-object + * @param object Generic data-object which should be stored. This data-object had to be implement the 'java.io.Serializable' interface + * @throws SessionDataStorageException Error message if the data-object can not stored to generic session-data storage + */ + public void setGenericDataToSession(String key, Object object) throws SessionDataStorageException { + if (MiscUtil.isEmpty(key)) { + Logger.warn("Generic session-data can not be stored with a 'null' key"); + throw new SessionDataStorageException("Generic session-data can not be stored with a 'null' key", null); + + } + + if (object != null) { + if (!Serializable.class.isInstance(object)) { + Logger.warn("Generic session-data can only store objects which implements the 'Seralizable' interface"); + throw new SessionDataStorageException("Generic session-data can only store objects which implements the 'Seralizable' interface", null); + + } + } + + if (genericSessionDataStorate.containsKey(key)) + Logger.debug("Overwrite generic session-data with key:" + key); + else + Logger.trace("Add generic session-data with key:" + key + " to session."); + + genericSessionDataStorate.put(key, object); + } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSessionStorageConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSessionStorageConstants.java new file mode 100644 index 000000000..648dcf6f1 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSessionStorageConstants.java @@ -0,0 +1,42 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.data; + +/** + * @author tlenz + * + */ +public class AuthenticationSessionStorageConstants { + + public static final String PREFIX_STORK = "stork_"; + public static final String PREFIX_eIDAS = "eIDAS_"; + + public static final String STORK_ATTRIBUTELIST = PREFIX_STORK + "attributelist"; + public static final String STORK_REQUEST = PREFIX_STORK + "request"; + public static final String STORK_RESPONSE = PREFIX_STORK + "response"; + public static final String STORK_CCC = PREFIX_STORK + "ccc"; + + public static final String eIDAS_ATTRIBUTELIST = PREFIX_eIDAS + "attributeList"; + public static final String eIDAS_RESPONSE = PREFIX_eIDAS + "response"; +} + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/SessionDataStorageException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/SessionDataStorageException.java new file mode 100644 index 000000000..203be784e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/SessionDataStorageException.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.exception; + +/** + * @author tlenz + * + */ +public class SessionDataStorageException extends MOAIDException { + + /** + * + */ + private static final long serialVersionUID = 5743057708136365929L; + + /** + * @param messageId + * @param parameters + */ + public SessionDataStorageException(String messageId, Object[] parameters) { + super(messageId, parameters); + + } + +} diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java index 72a7d3ba1..72a7d3ba1 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java index 7bce406e0..7bce406e0 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java index 65dcc7bf3..1f9259696 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java @@ -25,6 +25,14 @@ public interface AuthConfiguration extends ConfigurationProvider{ public String getConfigurationWithKey(final String key); + /** + * Get a configuration value from basic file based MOA-ID configuration + * + * @param key configuration key + * @return configuration value + */ + public String getBasicMOAIDConfiguration(final String key); + public int getTransactionTimeOut(); public int getSSOCreatedTimeOut(); public int getSSOUpdatedTimeOut(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IGarbageCollectorProcessing.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IGarbageCollectorProcessing.java new file mode 100644 index 000000000..a1008e883 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IGarbageCollectorProcessing.java @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.config.auth; + +/** + * @author tlenz + * + */ +public interface IGarbageCollectorProcessing { + + /** + * This method gets executed by the MOA garbage collector at regular intervals. + * + */ + public void runGarbageCollector(); +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/MOAGarbageCollector.java index 1f43a0d8a..1072bec5c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/MOAGarbageCollector.java @@ -23,36 +23,53 @@ package at.gv.egovernment.moa.id.config.auth; -import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.logging.Logger; +import java.util.ArrayList; +import java.util.List; +import at.gv.egovernment.moa.logging.Logger; -public class AuthConfigLoader implements Runnable { +public class MOAGarbageCollector implements Runnable { - private static final long INTERVAL = 24 * 60 * 60; // 24 hours + private static final long INTERVAL = 24 * 60 * 60; // 24 hours + private static final List<IGarbageCollectorProcessing> processModules = + new ArrayList<IGarbageCollectorProcessing>(); public void run() { while (true) { try { - Thread.sleep(INTERVAL * 1000); - Logger.trace("Check consistence of PVP2X metadata"); - MOAMetadataProvider.reInitialize(); + Thread.sleep(INTERVAL * 1000); + + try { + for (IGarbageCollectorProcessing element : processModules) + element.runGarbageCollector(); - + } catch (Throwable e1) { + Logger.warn("Garbage collection FAILED in some module.", e1); + } + } catch (Throwable e) { - Logger.warn("MOA-ID Configuration validation is not possible, actually. Reuse old configuration.", e); + Logger.warn("MOA-ID garbage collection is not possible, actually.", e); } finally { - - + } } } - public static void start() { + /** + * Add a module to MOA internal garbage collector. Every module is executed once a day + * + * @param modul Module which should be executed by the garbage collector. + */ + public static void addModulForGarbageCollection(IGarbageCollectorProcessing modul) { + processModules.add(modul); + + } + + public static void start() { // start the session cleanup thread - Thread configLoader = new Thread(new AuthConfigLoader(), "ConfigurationChecker"); - configLoader.setName("ConfigurationChecker"); + Thread configLoader = new Thread(new MOAGarbageCollector(), "MOAGarbageCollector"); + configLoader.setName("MOAGarbageCollectorr"); configLoader.setDaemon(true); configLoader.setPriority(Thread.MIN_PRIORITY); configLoader.start(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java index 7b798f522..18926046c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java @@ -197,6 +197,11 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide } } + public String getBasicMOAIDConfiguration(final String key) { + return properties.getProperty(key); + + } + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.auth.AuthConfiguration#getPropertyWithKey(java.lang.String) */ diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java index e2892e70a..53be0881b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java @@ -29,13 +29,16 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.map.HashedMap; import org.w3c.dom.Element; -import eu.stork.peps.auth.commons.IPersonalAttributeList; -import eu.stork.peps.auth.commons.STORKAuthnRequest; - import at.gv.egovernment.moa.id.auth.data.IdentityLink; +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; +import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.DOMUtils; import at.gv.egovernment.moa.util.DateTimeUtils; @@ -122,9 +125,8 @@ public class AuthenticationData implements IAuthData, Serializable { * STORK attributes from response */ private String ccc = null; - private IPersonalAttributeList storkAttributes = null; - private String storkAuthnResponse; - private STORKAuthnRequest storkRequest = null; + + private Map<String, Object> genericDataStorate = new HashedMap<String, Object>(); private byte[] signerCertificate = null; @@ -397,23 +399,6 @@ public class AuthenticationData implements IAuthData, Serializable { this.identityLink = identityLink; } - - /** - * @return the storkAttributes - */ - public IPersonalAttributeList getStorkAttributes() { - return storkAttributes; - } - - - /** - * @param storkAttributes the storkAttributes to set - */ - public void setStorkAttributes(IPersonalAttributeList storkAttributes) { - this.storkAttributes = storkAttributes; - } - - /** * @return the signerCertificate */ @@ -495,9 +480,47 @@ public class AuthenticationData implements IAuthData, Serializable { * @return */ public String getQAALevel() { - return this.QAALevel; + if (this.QAALevel != null && + this.QAALevel.startsWith(PVPConstants.EIDAS_QAA_PREFIX)) { + String mappedQAA = PVPtoSTORKMapper.getInstance().mapeIDASQAAToSTORKQAA(this.QAALevel); + if (MiscUtil.isNotEmpty(mappedQAA)) + return mappedQAA; + + else { + Logger.error("eIDAS QAA-level:" + this.QAALevel + + " can not be mapped to STORK QAA-level! Use " + + PVPConstants.STORK_QAA_1_1 + " as default value."); + return PVPConstants.STORK_QAA_1_1; + + } + + + } else + return this.QAALevel; } + + public String getEIDASQAALevel() { + if (this.QAALevel != null && + this.QAALevel.startsWith(PVPConstants.STORK_QAA_PREFIX)) { + String mappedQAA = PVPtoSTORKMapper.getInstance().mapSTORKQAAToeIDASQAA(this.QAALevel); + if (MiscUtil.isNotEmpty(mappedQAA)) + return mappedQAA; + + else { + Logger.error("STORK QAA-level:" + this.QAALevel + + " can not be mapped to eIDAS QAA-level! Use " + + PVPConstants.EIDAS_QAA_LOW + " as default value."); + return PVPConstants.EIDAS_QAA_LOW; + + } + + + } else + return this.QAALevel; + + } + /** * @return @@ -516,13 +539,16 @@ public class AuthenticationData implements IAuthData, Serializable { /** + * Store QAA level in eIDAS format to authentication Data + * * @param qAALevel the qAALevel to set + * @throws AssertionAttributeExtractorExeption */ public void setQAALevel(String qAALevel) { - QAALevel = qAALevel; + QAALevel = qAALevel; + } - /** * @return the ssoSession */ @@ -539,35 +565,6 @@ public class AuthenticationData implements IAuthData, Serializable { } /** - * @param storkRequest the storkRequest to set - */ - public void setStorkRequest(STORKAuthnRequest storkRequest) { - this.storkRequest = storkRequest; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.IAuthData#getStorkAuthnRequest() - */ - @Override - public STORKAuthnRequest getStorkAuthnRequest() { - return this.storkRequest; - } - - /** - * @return the storkAuthnResponse - */ - public String getStorkAuthnResponse() { - return storkAuthnResponse; - } - - /** - * @param storkAuthnResponse the storkAuthnResponse to set - */ - public void setStorkAuthnResponse(String storkAuthnResponse) { - this.storkAuthnResponse = storkAuthnResponse; - } - - /** * @return the mandateReferenceValue */ public String getMandateReferenceValue() { @@ -743,5 +740,68 @@ public class AuthenticationData implements IAuthData, Serializable { public void setIsBusinessService(boolean flag) { this.businessService = flag; - } + } + + /** + * Returns a generic data-object with is stored with a specific identifier + * + * @param key The specific identifier of the data object + * @param clazz The class type which is stored with this key + * @return The data object or null if no data is found with this key + */ + public <T> T getGenericData(String key, final Class<T> clazz) { + if (MiscUtil.isNotEmpty(key)) { + Object data = genericDataStorate.get(key); + + if (data == null) + return null; + + try { + @SuppressWarnings("unchecked") + T test = (T) data; + return test; + + } catch (Exception e) { + Logger.warn("Generic authentication-data object can not be casted to requsted type", e); + return null; + + } + + } + + Logger.warn("Can not load generic session-data with key='null'"); + return null; + + } + + /** + * Store a generic data-object to session with a specific identifier + * + * @param key Identifier for this data-object + * @param object Generic data-object which should be stored. This data-object had to be implement the 'java.io.Serializable' interface + * @throws SessionDataStorageException Error message if the data-object can not stored to generic session-data storage + */ + public void setGenericData(String key, Object object) throws SessionDataStorageException { + if (MiscUtil.isEmpty(key)) { + Logger.warn("Generic session-data can not be stored with a 'null' key"); + throw new SessionDataStorageException("Generic data can not be stored with a 'null' key", null); + + } + + if (object != null) { + if (!Serializable.class.isInstance(object)) { + Logger.warn("Generic data can only store objects which implements the 'Seralizable' interface"); + throw new SessionDataStorageException("Generic data can only store objects which implements the 'Seralizable' interface", null); + + } + } + + if (genericDataStorate.containsKey(key)) + Logger.debug("Overwrite generic data with key:" + key); + else + Logger.trace("Add generic data with key:" + key + " to session."); + + genericDataStorate.put(key, object); + } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java index 09b0d7971..91d40fcc3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java @@ -27,9 +27,6 @@ import java.util.List; import org.w3c.dom.Element; -import eu.stork.peps.auth.commons.IPersonalAttributeList; -import eu.stork.peps.auth.commons.STORKAuthnRequest; - import at.gv.egovernment.moa.id.auth.data.IdentityLink; /** @@ -82,6 +79,7 @@ public interface IAuthData { String getMandateReferenceValue(); String getQAALevel(); + public String getEIDASQAALevel(); String getSessionIndex(); String getNameID(); @@ -89,8 +87,7 @@ public interface IAuthData { boolean isForeigner(); String getCcc(); - STORKAuthnRequest getStorkAuthnRequest(); - String getStorkAuthnResponse(); - IPersonalAttributeList getStorkAttributes(); + + public <T> T getGenericData(String key, final Class<T> clazz); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java index ece1a805d..acbb67b34 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java @@ -27,6 +27,7 @@ import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; import org.opensaml.ws.message.MessageContext; import org.opensaml.ws.message.encoder.MessageEncodingException; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.logging.Logger; /** @@ -45,6 +46,9 @@ public class MOAStringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder "Invalid message context type, this encoder only support SAMLMessageContext"); } + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext; String endpointURL = getEndpointURL(samlMsgCtx).buildURL(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/EIDSTORKTOKEN.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/EIDSTORKTOKEN.java index 84b791708..43a0458cb 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/EIDSTORKTOKEN.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/EIDSTORKTOKEN.java @@ -24,6 +24,7 @@ package at.gv.egovernment.moa.id.protocols.builder.attributes; import java.io.IOException; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.IAuthData; @@ -47,7 +48,8 @@ public class EIDSTORKTOKEN implements IPVPAttributeBuilder { throw new UnavailableAttributeException(EID_STORK_TOKEN_NAME); } else { - String storkResponse = authData.getStorkAuthnResponse(); + String storkResponse = authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_RESPONSE, String.class); if ( MiscUtil.isEmpty(storkResponse) ) { throw new UnavailableAttributeException(EID_STORK_TOKEN_NAME); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java index 168f2362a..dc0cab8c3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java @@ -41,6 +41,11 @@ public interface PVPConstants { public static final String STORK_QAA_1_3 = "http://www.stork.gov.eu/1.0/citizenQAALevel/3"; public static final String STORK_QAA_1_4 = "http://www.stork.gov.eu/1.0/citizenQAALevel/4"; + public static final String EIDAS_QAA_PREFIX = "http://eidas.europa.eu/LoA/"; + public static final String EIDAS_QAA_LOW = EIDAS_QAA_PREFIX + "low"; + public static final String EIDAS_QAA_SUBSTANTIAL = EIDAS_QAA_PREFIX + "substantial"; + public static final String EIDAS_QAA_HIGH = EIDAS_QAA_PREFIX + "high"; + public static final String STORK_ATTRIBUTE_PREFIX = "http://www.stork.gov.eu/"; public static final String URN_OID_PREFIX = "urn:oid:"; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java index 8a6b09376..b8f7e6d80 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.app.VelocityEngine; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; @@ -50,6 +51,7 @@ import org.opensaml.xml.security.x509.X509Credential; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; @@ -75,6 +77,9 @@ public class PostBinding implements IDecoder, IEncoder { X509Credential credentials = CredentialProvider .getIDPAssertionSigningCredential(); + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + VelocityEngine engine = VelocityProvider.getClassPathVelocityEngine(); HTTPPostEncoder encoder = new HTTPPostEncoder(engine, "resources/templates/pvp_postbinding_template.html"); @@ -110,6 +115,9 @@ public class PostBinding implements IDecoder, IEncoder { X509Credential credentials = CredentialProvider .getIDPAssertionSigningCredential(); + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + Logger.debug("create SAML POSTBinding response"); VelocityEngine engine = VelocityProvider.getClassPathVelocityEngine(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java index 0a459a9be..f48d216dd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletResponse; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder; import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; @@ -51,6 +52,7 @@ import org.opensaml.xml.security.x509.X509Credential; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; @@ -74,6 +76,9 @@ public class RedirectBinding implements IDecoder, IEncoder { X509Credential credentials = CredentialProvider .getIDPAssertionSigningCredential(); + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + Logger.debug("create SAML RedirectBinding response"); HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); @@ -104,6 +109,9 @@ public class RedirectBinding implements IDecoder, IEncoder { X509Credential credentials = CredentialProvider .getIDPAssertionSigningCredential(); + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + Logger.debug("create SAML RedirectBinding response"); HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java index 2ef861e20..c1e94ff36 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder; import org.opensaml.saml2.core.RequestAbstractType; @@ -47,6 +48,7 @@ import org.opensaml.xml.security.credential.Credential; import org.opensaml.xml.signature.SignableXMLObject; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; @@ -142,6 +144,9 @@ public class SoapBinding implements IDecoder, IEncoder { Credential credentials = CredentialProvider .getIDPAssertionSigningCredential(); + //load default PVP security configurations + MOADefaultBootstrap.initializeDefaultPVPConfiguration(); + HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder(); HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( resp, true); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/MOADefaultBootstrap.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/MOADefaultBootstrap.java index 80789cd12..b731e2a95 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/MOADefaultBootstrap.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/MOADefaultBootstrap.java @@ -50,7 +50,10 @@ public class MOADefaultBootstrap extends DefaultBootstrap { } - + public static void initializeDefaultPVPConfiguration() { + initializeGlobalSecurityConfiguration(); + + } /** * Initializes the default global security configuration. diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java index f33cadc41..03fa686f9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java @@ -55,18 +55,20 @@ import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing; +import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.InterfederatedIDPPublicServiceFilter; -import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MetadataFilterChain; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.PVPMetadataFilterChain; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.SchemaValidationFilter; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.MiscUtil; -public class MOAMetadataProvider implements ObservableMetadataProvider{ +public class MOAMetadataProvider implements ObservableMetadataProvider, IGarbageCollectorProcessing { private static MOAMetadataProvider instance = null; private static Object mutex = new Object(); @@ -77,18 +79,32 @@ public class MOAMetadataProvider implements ObservableMetadataProvider{ synchronized (mutex) { if (instance == null) { instance = new MOAMetadataProvider(); + + //add this to MOA garbage collector + MOAGarbageCollector.addModulForGarbageCollection(instance); + } } } return instance; } - public static void reInitialize() { + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector() + */ + @Override + public void runGarbageCollector() { + reInitialize(); + + } + + private static void reInitialize() { synchronized (mutex) { /**add new Metadataprovider or remove Metadataprovider which are not in use any more.**/ if (instance != null) - try { + try { + Logger.trace("Check consistence of PVP2X metadata"); instance.addAndRemoveMetadataProvider(); } catch (ConfigurationException e) { @@ -422,8 +438,8 @@ public class MOAMetadataProvider implements ObservableMetadataProvider{ internalProvider = chainProvider; } - private MetadataFilterChain buildMetadataFilterChain(OAAuthParameter oaParam, String metadataURL, byte[] certificate) throws CertificateException { - MetadataFilterChain filterChain = new MetadataFilterChain(metadataURL, certificate); + private PVPMetadataFilterChain buildMetadataFilterChain(OAAuthParameter oaParam, String metadataURL, byte[] certificate) throws CertificateException { + PVPMetadataFilterChain filterChain = new PVPMetadataFilterChain(metadataURL, certificate); filterChain.getFilters().add(new SchemaValidationFilter()); if (oaParam.isInderfederationIDP()) { @@ -435,7 +451,7 @@ public class MOAMetadataProvider implements ObservableMetadataProvider{ return filterChain; } - private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL, byte[] certificate, String oaName, MetadataFilterChain filter) { + private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL, byte[] certificate, String oaName, PVPMetadataFilterChain filter) { HTTPMetadataProvider httpProvider = null; Timer timer= null; MOAHttpClient httpClient = null; @@ -470,7 +486,7 @@ public class MOAMetadataProvider implements ObservableMetadataProvider{ //httpProvider.setRefreshDelayFactor(0.1F); if (filter == null) { - filter = new MetadataFilterChain(metadataURL, certificate); + filter = new PVPMetadataFilterChain(metadataURL, certificate); } httpProvider.setMetadataFilter(filter); httpProvider.initialize(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java index 26b3bfbd1..9c294245f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java @@ -38,9 +38,6 @@ import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.core.Subject; import org.opensaml.xml.XMLObject; -import eu.stork.peps.auth.commons.PersonalAttribute; -import eu.stork.peps.auth.commons.PersonalAttributeList; - import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; import at.gv.egovernment.moa.logging.Logger; @@ -50,7 +47,7 @@ public class AssertionAttributeExtractor { private Assertion assertion = null; private Map<String, List<String>> attributs = new HashMap<String, List<String>>(); - private PersonalAttributeList storkAttributes = new PersonalAttributeList(); + //private PersonalAttributeList storkAttributes = new PersonalAttributeList(); private final List<String> minimalAttributeNameList = Arrays.asList( PVPConstants.PRINCIPAL_NAME_NAME, @@ -77,9 +74,9 @@ public class AssertionAttributeExtractor { for (XMLObject el : attr.getAttributeValues()) storkAttrValues.add(el.getDOM().getTextContent()); - PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(), - false, storkAttrValues , "Available"); - storkAttributes.put(attr.getName(), storkAttr ); +// PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(), +// false, storkAttrValues , "Available"); +// storkAttributes.put(attr.getName(), storkAttr ); } else { List<String> attrList = new ArrayList<String>(); @@ -155,9 +152,9 @@ public class AssertionAttributeExtractor { } - public PersonalAttributeList getSTORKAttributes() { - return storkAttributes; - } +// public PersonalAttributeList getSTORKAttributes() { +// return storkAttributes; +// } public String getNameID() throws AssertionAttributeExtractorExeption { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/PVPMetadataFilterChain.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/PVPMetadataFilterChain.java new file mode 100644 index 000000000..4c1da747b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/PVPMetadataFilterChain.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata; + +import java.security.cert.CertificateException; + +import at.gv.egovernment.moa.id.saml2.MetadataFilterChain; + +/** + * @author tlenz + * + */ +public class PVPMetadataFilterChain extends MetadataFilterChain { + + + /** + * @throws CertificateException + * + */ + public PVPMetadataFilterChain(String url, byte[] certificate) throws CertificateException { + addDefaultFilters(url, certificate); + } + + public void addDefaultFilters(String url, byte[] certificate) throws CertificateException { + addFilter(new MetadataSignatureFilter(url, certificate)); + + } + + + + + + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataFilterChain.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/saml2/MetadataFilterChain.java index 4e1d939ff..e7412a0fc 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataFilterChain.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/saml2/MetadataFilterChain.java @@ -20,9 +20,8 @@ * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ -package at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata; +package at.gv.egovernment.moa.id.saml2; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; @@ -39,25 +38,23 @@ import at.gv.egovernment.moa.logging.Logger; public class MetadataFilterChain implements MetadataFilter { private List<MetadataFilter> filters = new ArrayList<MetadataFilter>(); - + /** - * @throws CertificateException + * Return all actually used Metadata filters * + * @return List of Metadata filters */ - public MetadataFilterChain(String url, byte[] certificate) throws CertificateException { - addDefaultFilters(url, certificate); - } - - public void addDefaultFilters(String url, byte[] certificate) throws CertificateException { - filters.add(new MetadataSignatureFilter(url, certificate)); - + public List<MetadataFilter> getFilters() { + return filters; } /** - * @return the filter + * Add a new Metadata filter to filterchain + * + * @param filter */ - public List<MetadataFilter> getFilters() { - return filters; + public void addFilter(MetadataFilter filter) { + filters.add(filter); } @@ -67,16 +64,10 @@ public class MetadataFilterChain implements MetadataFilter { @Override public void doFilter(XMLObject arg0) throws FilterException { for (MetadataFilter filter : filters) { - Logger.trace("Use MOAMetadatafilter " + filter.getClass().getName()); + Logger.trace("Use MOAMetadataFilter " + filter.getClass().getName()); filter.doFilter(arg0); } } - - - - - - } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java index 5ef9494f4..099a70470 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java @@ -37,10 +37,14 @@ public class PVPtoSTORKMapper { private static final String PVP_SECCLASS_PREFIX = "http://www.ref.gv.at/ns/names/agiz/pvp/"; private static final String STORK_QAA_PREFIX = "http://www.stork.gov.eu/1.0/"; + private static final String eIDAS_QAA_PREFIX = "http://eidas.europa.eu/"; private static final String MAPPING_RESOURCE = "resources/properties/pvp-stork_mapping.properties"; + private static final String MAPPING_SECCLASS_PREFIX = "secclass_"; + private static final String MAPPING_EIDAS_PREFIX = "eidas_"; + private Properties mapping = null; private static PVPtoSTORKMapper instance = null; @@ -68,6 +72,47 @@ public class PVPtoSTORKMapper { } + /** + * Map STORK QAA level to eIDAS QAA level + * + * @param storkQAA STORK QAA level + * @return + */ + public String mapSTORKQAAToeIDASQAA(String storkQAA) { + if (mapping != null) { + String input = storkQAA.substring(STORK_QAA_PREFIX.length()); + String mappedQAA = mapping.getProperty(MAPPING_EIDAS_PREFIX + input); + if (MiscUtil.isNotEmpty(mappedQAA)) { + Logger.info("Map STORK-QAA " + storkQAA + " to eIDAS-QAA " + mappedQAA); + return mappedQAA; + + } + } + Logger.warn("No eIDAS-QAA mapping for STORK-QAA " + storkQAA +" !"); + return null; + + } + + /** + * Map eIDAS QAA-level to STORK QAA-level + * + * @param qaaLevel eIDAS QAA-level + * @return STORK QAA-level + */ + public String mapeIDASQAAToSTORKQAA(String qaaLevel) { + if (mapping != null) { + String input = qaaLevel.substring(eIDAS_QAA_PREFIX.length()); + String mappedQAA = mapping.getProperty(input); + if (MiscUtil.isNotEmpty(mappedQAA)) { + Logger.info("Map eIDAS-QAA " + qaaLevel + " to STORK-QAA " + mappedQAA); + return mappedQAA; + + } + } + Logger.warn("No eIDAS-QAA mapping for eIDAS-QAA " + qaaLevel +" !"); + return null; + } + /**Map a STORK QAA level to PVP SecClass * * @param STORK-QAA level @@ -76,7 +121,7 @@ public class PVPtoSTORKMapper { public String mapToSecClass(String storkQAALevel) { if (mapping != null) { String input = storkQAALevel.substring(STORK_QAA_PREFIX.length()); - String mappedQAA = mapping.getProperty(input); + String mappedQAA = mapping.getProperty(MAPPING_SECCLASS_PREFIX + input); if (MiscUtil.isNotEmpty(mappedQAA)) { Logger.info("Map STORK-QAA " + storkQAALevel + " to PVP SecClass " + mappedQAA); return mappedQAA; @@ -125,4 +170,5 @@ public class PVPtoSTORKMapper { Logger.warn("NO mapping for PVPRole "+ el.getRoleName() + " !"); return null; } + } diff --git a/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties b/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties index ca12fada4..63a679db5 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties @@ -25,7 +25,19 @@ secclass/0-2=http://www.stork.gov.eu/1.0/citizenQAALevel/4 secclass/0-3=http://www.stork.gov.eu/1.0/citizenQAALevel/4 ##STORK-QAA to PVP SecClass mapping -citizenQAALevel/1=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0 -citizenQAALevel/2=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-1 -citizenQAALevel/3=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2 -citizenQAALevel/4=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2
\ No newline at end of file +secclass_citizenQAALevel/1=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0 +secclass_citizenQAALevel/2=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-1 +secclass_citizenQAALevel/3=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2 +secclass_citizenQAALevel/4=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2 + + +##STORK-QAA to eIDAS-QAA mapping +eidas_citizenQAALevel/1=http://eidas.europa.eu/LoA/low +eidas_citizenQAALevel/2=http://eidas.europa.eu/LoA/low +eidas_citizenQAALevel/3=http://eidas.europa.eu/LoA/substantial +eidas_citizenQAALevel/4=http://eidas.europa.eu/LoA/high + +##eIDAS-QAA to STORK-QAA mapping +LoA/low=http://www.stork.gov.eu/1.0/citizenQAALevel/1 +LoA/substantial=http://www.stork.gov.eu/1.0/citizenQAALevel/2 +LoA/high=http://www.stork.gov.eu/1.0/citizenQAALevel/4
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml new file mode 100644 index 000000000..b43efac9e --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/pom.xml @@ -0,0 +1,111 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>MOA.id.server.modules</groupId> + <artifactId>moa-id-modules</artifactId> + <version>${moa-id-version}</version> + </parent> + <artifactId>moa-id-module-eIDAS</artifactId> + <name>MOA-ID eIDAS Module</name> + <description>Inbound / outbound implemention of eIDAS protocol for MOA-ID</description> + + <properties> + <repositoryPath>${basedir}/../../../../repository</repositoryPath> + + <eidas-commons.version>eidas.1.0</eidas-commons.version> + <eidas-saml-engine.version>eidas.1.0</eidas-saml-engine.version> + + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <!-- eidas Commons --> + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>eidas-commons</artifactId> + <version>${eidas-commons.version}</version> + <!--scope>provided</scope--> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + <exclusion> + <artifactId>log4j-over-slf4j</artifactId> + <groupId>org.slf4j</groupId> + </exclusion> + </exclusions> + </dependency> + + <!-- eidas SAML Engine --> + <dependency> + <groupId>eu.eidas</groupId> + <artifactId>saml-engine</artifactId> + <version>${eidas-saml-engine.version}</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>xalan</groupId> + <artifactId>serializer</artifactId> + </exclusion> + <exclusion> + <groupId>xalan</groupId> + <artifactId>xalan</artifactId> + </exclusion> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>xml-resolver</groupId> + <artifactId>xml-resolver</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.52</version> + <!-- <scope>provided</scope> --> + </dependency> + + + </dependencies> + +</project>
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java new file mode 100644 index 000000000..5166f090d --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -0,0 +1,75 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas; + +/** + * @author tlenz + * + */ +public class Constants { + + public static final String eIDAS_SAML_ENGINE_NAME = "default"; + public static final String SSLSOCKETFACTORYNAME = "eIDASMetadataSSLSocketFactory"; + + //default keys for eIDAS SAML-engine configuration + public static final String eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG = "SamlEngineConf"; + public static final String eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG = "SignatureConf"; + public static final String eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG = "EncryptionConf"; + public static final String eIDAS_SAML_ENGINE_NAME_ID_CLASS = "class"; + + //default implementations for eIDAS SAML-engine functionality + public static final String SAML_SIGNING_IMPLENTATION = "eu.eidas.auth.engine.core.impl.SignSW"; + public static final String SAML_ENCRYPTION_IMPLENTATION = "eu.eidas.auth.engine.core.impl.EncryptionSW"; + + //configuration property keys + public static final String CONIG_PROPS_EIDAS_PREFIX="moa.id.protocols.eIDAS"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE="samlengine"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX=CONIG_PROPS_EIDAS_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".config.file"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN="sign"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT="enc"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." + + CONIG_PROPS_EIDAS_SAMLENGINE_SIGN + ".config.file"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." + + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file"; + public static final String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore"; + + //timeouts and clock skews + public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation + public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout + public static final long CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT = 7 * 24 * 60 * 60 * 1000; //remove unused eIDAS metadata after 7 days + + //eIDAS attribute names + public static final String eIDAS_ATTR_PERSONALIDENTIFIER = "PersonIdentifier"; + public static final String eIDAS_ATTR_DATEOFBIRTH = "DateOfBirth"; + public static final String eIDAS_ATTR_CURRENTGIVENNAME = "CurrentGivenName"; + public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "CurrentFamilyName"; + + //http endpoint descriptions + public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/sp/post"; + public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/sp/redirect"; + public static final String eIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/idp/post"; + public static final String eIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/idp/redirect"; + public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/metadata"; + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java new file mode 100644 index 000000000..9b634ff4d --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java @@ -0,0 +1,118 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.config; + +import java.util.HashMap; +import java.util.Map; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.config.ConfigurationException; +import eu.eidas.samlengineconfig.AbstractCertificateConfigurationManager; +import eu.eidas.samlengineconfig.EngineInstance; +import eu.eidas.samlengineconfig.SamlEngineConfiguration; +import eu.eidas.samlengineconfig.impl.SamlEngineConfigurationImpl; + +/** + * @author tlenz + * + */ +public class MOAIDCertificateManagerConfigurationImpl extends + AbstractCertificateConfigurationManager { + + private SamlEngineConfiguration samlEngineConfiguration =null; + + @Override + public boolean isActive() { + return true; + } + + /** + * + */ + public MOAIDCertificateManagerConfigurationImpl() { + try { + initalizeConfiguration(); + + } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) { + Logger.error("eIDAS SAML-engine initialization FAILED", e); + + } + } + + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#addConfiguration(java.lang.String, java.lang.String, java.util.Map, boolean) + */ + @Override + public void addConfiguration(String paramString1, String paramString2, + Map<String, String> paramMap, boolean paramBoolean) { + throw new ConfigurationException("","not yet implemented"); + + } + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getInstance(java.lang.String) + */ + @Override + public EngineInstance getInstance(String paramString) { + return getConfiguration().get(paramString); + + } + + /* (non-Javadoc) + * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getConfiguration() + */ + @Override + public Map<String, EngineInstance> getConfiguration() { + if(samlEngineConfiguration == null){ + try { + initalizeConfiguration(); + + } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) { + Logger.error("eIDAS SAML-engine initialization FAILED", e); + + } + + } + + return samlEngineConfiguration==null?new HashMap<String, EngineInstance>():((MOAeIDASSAMLEngineConfigurationImpl) samlEngineConfiguration).getInstanceMap(); + + } + + + /** + * Initialize eIDAS SAML-engine from MOA-ID configuration + * @throws at.gv.egovernment.moa.id.config.ConfigurationException + * + */ + private void initalizeConfiguration() throws at.gv.egovernment.moa.id.config.ConfigurationException { + //initialize configuration + MOAeIDASSAMLEngineConfigurationImpl tmp = new MOAeIDASSAMLEngineConfigurationImpl(); + tmp.initialize(); + + //set initialized configuration + samlEngineConfiguration = tmp; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java new file mode 100644 index 000000000..584910ea5 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java @@ -0,0 +1,268 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineConfigurationException; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.FileUtils; +import at.gv.egovernment.moa.util.MiscUtil; + +import eu.eidas.samlengineconfig.BinaryParameter; +import eu.eidas.samlengineconfig.ConfigurationParameter; +import eu.eidas.samlengineconfig.EngineInstance; +import eu.eidas.samlengineconfig.InstanceConfiguration; +import eu.eidas.samlengineconfig.PropsParameter; +import eu.eidas.samlengineconfig.SamlEngineConfiguration; + +/** + * @author tlenz + * + */ +public class MOAeIDASSAMLEngineConfigurationImpl extends + SamlEngineConfiguration { + + private static final String KEYSTORE_PATH="keystorePath"; + private static final String METADATA_KEYSTORE_PATH="metadata.keystorePath"; + private static final String ENCRYPTION_ACTIVATION="encryptionActivation"; + private static final String[] BINARY_PARAMETERS={KEYSTORE_PATH, ENCRYPTION_ACTIVATION,METADATA_KEYSTORE_PATH}; + + public List<EngineInstance> getInstances(){ + return super.getInstances(); + } + + @Override + public void setInstances(List<EngineInstance> engineInstances) { + super.setInstances(engineInstances); + + } + + public Map<String, EngineInstance> getInstanceMap() { + Map<String, EngineInstance> result = new HashMap<String, EngineInstance>(); + for(EngineInstance instance:getInstances()) { + + result.put(instance.getName(), instance); + } + + return result; + } + + //initialize + public void initialize() throws ConfigurationException { + //create an eIDAS SAML-engine instance + EngineInstance engineInst = new EngineInstance(); + engineInst.setName(Constants.eIDAS_SAML_ENGINE_NAME); + List<InstanceConfiguration> engineConfigs = new ArrayList<InstanceConfiguration>(); + + + //add configurations + + //add basic eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlBaseConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlBaseConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG); + samlBaseConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE)); + engineConfigs.add(samlBaseConfig); + + //add signing eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlSignConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlSignConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG); + samlSignConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, + Constants.SAML_SIGNING_IMPLENTATION); + + //TODO: load signing keys directly from MOA-ID configuration in finale version + samlSignConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE)); + engineConfigs.add(samlSignConfig); + + //add encryption eIDAS SAML-engine configuration + MOAeIDASSAMLInstanceConfigurationImpl samlEncConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); + samlEncConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG); + samlEncConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, + Constants.SAML_ENCRYPTION_IMPLENTATION); + + //TODO: load encryption keys directly from MOA-ID configuration in finale version + samlEncConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE)); + engineConfigs.add(samlEncConfig); + + engineInst.setConfigurations(engineConfigs); + super.addInstance(engineInst); + + } + + /** + * Load an external eIDAS SAML-engine configuration file, which is referenced from MOA-ID configuration + * + * @param key Configuration key, which is used in property based MOA-ID configuration file + * @return eIDAS SAML-engine configuration object + * @throws ConfigurationException + */ + + private ConfigurationParameter loadConfigurationFromExternalFile(String key) throws ConfigurationException { + String configFile = + AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(key); + if (MiscUtil.isEmpty(configFile)) { + Logger.warn("No eIDAS SAML-engine configuration key: " + + key + " found in MOA-ID properties configuration file."); + //throw new EIDASEngineConfigurationException("No eIDAS SAML-engine configuration property.", null); + return null; + } + + Properties inputProps = loadPropsFromXml(configFile); + return buildPropsParameter(inputProps, configFile); + + } + + + private PropsParameter buildPropsParameter(Properties inputProps, String fileName) throws EIDASEngineConfigurationException { + PropsParameter outputProps = new PropsParameter(); + outputProps.setFileName(fileName); + + //original eIDAS SAML-engine use this identifier + outputProps.setName("fileConfiguration"); + + outputProps.setValue(inputProps); + + //post-process special parameters + for(String key:BINARY_PARAMETERS) { + Object keystorePath = inputProps.get(key); + if (keystorePath != null) { + if (keystorePath instanceof String && + isBinaryParameter((String)keystorePath) ) { + BinaryParameter bp = new BinaryParameter(); + bp.setValue(loadBinaryFile(keystorePath.toString())); + bp.setName(key); + bp.setUrl(keystorePath.toString()); + inputProps.put(key, bp); + + } else { + Logger.warn("eIDAS SAML-engine keyStore parameter has an unsuspected type. +" + + "(Type: " + keystorePath.toString() + ")"); + + } + } + } + + return outputProps; + } + + private boolean isBinaryParameter(String parameter) { + if (MiscUtil.isNotEmpty(parameter)) { + String absoluteConfigFile; + try { + absoluteConfigFile = FileUtils.makeAbsoluteURL( + parameter, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + File file = new File(new URL(absoluteConfigFile).toURI()); + return file.exists(); + + } catch (ConfigurationException | MalformedURLException | URISyntaxException e) { + Logger.warn("Binary eIDAS SAML-engine configuration parameter: " + + parameter + " is not loadable."); + + } + + } + + return false; + + } + + private byte[] loadBinaryFile(String fileName) throws EIDASEngineConfigurationException{ + InputStream is = null; + byte data[]=null; + try { + String absoluteConfigFile = FileUtils.makeAbsoluteURL( + fileName, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + + File file = new File(new URL(absoluteConfigFile).toURI()); + is = new FileInputStream(file); + data=new byte[is.available()]; + is.read(data); + + } catch (ConfigurationException | URISyntaxException | IOException e) { + throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); + + } finally { + if (is != null) + try { + is.close(); + + } catch (IOException e) { + Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); + + } + + } + + return data; + + } + + private Properties loadPropsFromXml(String configFile) throws EIDASEngineConfigurationException { + Properties props = new Properties(); + InputStream is = null; + try { + String absoluteConfigFile = FileUtils.makeAbsoluteURL( + configFile, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + + File file = new File(new URL(absoluteConfigFile).toURI()); + is = new FileInputStream(file); + props.loadFromXML(is); + + } catch (ConfigurationException | URISyntaxException | IOException e) { + throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); + + } finally { + if (is != null) + try { + is.close(); + + } catch (IOException e) { + Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); + + } + + } + + return props; + + } + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java new file mode 100644 index 000000000..dccd39905 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.config; + +import java.util.ArrayList; +import java.util.List; + +import eu.eidas.samlengineconfig.ConfigurationParameter; +import eu.eidas.samlengineconfig.InstanceConfiguration; +import eu.eidas.samlengineconfig.StringParameter; + +/** + * @author tlenz + * + */ +public class MOAeIDASSAMLInstanceConfigurationImpl extends + InstanceConfiguration { + + public void addParameter(ConfigurationParameter param) { + if (param != null) { + List<ConfigurationParameter> paramList = super.getParameters(); + if (paramList == null) { + paramList = new ArrayList<ConfigurationParameter>(); + super.setParameters(paramList); + + } + + paramList.add(param); + } + } + + public void addParameter(String key, String value) { + StringParameter param = new StringParameter(); + param.setName(key); + param.setValue(value); + addParameter(param); + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java new file mode 100644 index 000000000..7b044522c --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * @author tlenz + * + */ +public class eIDASAuthenticationModulImpl implements AuthModule { + + private int priority = 1; + + @Override + public int getPriority() { + return priority; + } + + /** + * Sets the priority of this module. Default value is {@code 0}. + * @param priority The priority. + */ + public void setPriority(int priority) { + this.priority = priority; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + if (StringUtils.isNotBlank((String) context.get("ccc")) || + StringUtils.isNotBlank((String) context.get("CCC"))) + return "eIDASAuthentication"; + else + return null; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml" }; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java new file mode 100644 index 000000000..49f0451cb --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java @@ -0,0 +1,95 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringEscapeUtils; + +import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@WebServlet(urlPatterns = { "/eidas/sp/post", "/eidas/sp/redirect"}, loadOnStartup = 1) +public class eIDASSignalServlet extends ProcessEngineSignalServlet { + + private static final long serialVersionUID = 8215688005533754459L; + + public eIDASSignalServlet() { + super(); + Logger.debug("Registering servlet " + getClass().getName() + + " with mappings '/eidas/sp/post' and '/eidas/sp/redirect'."); + + } + + + @Override + /** + * Protocol specific implementation to get the sessionID + * from http request object + * + * @param request The http Servlet-Request object + * @return The SessionId + * + */ + public String getMoaSessionId(HttpServletRequest request) { + String sessionId = super.getMoaSessionId(request); + + try { + + // use SAML2 relayState + if (sessionId == null) { + sessionId = StringEscapeUtils.escapeHtml(request.getParameter("RelayState")); + } + + // take from InResponseTo attribute of SAMLResponse + if (sessionId == null) { + String base64SamlToken = request.getParameter("SAMLResponse"); + if (base64SamlToken != null && false) { +// byte[] samlToken = Base64Utils.decode(base64SamlToken, false); +// Document samlResponse = parseDocument(new ByteArrayInputStream(samlToken)); +// +// XPath xPath = XPathFactory.newInstance().newXPath(); +// SimpleNamespaceContext nsContext = new SimpleNamespaceContext(); +// nsContext.bindNamespaceUri("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol"); +// xPath.setNamespaceContext(nsContext); +// XPathExpression expression = xPath.compile("string(/saml2p:Response/@InResponseTo)"); +// sessionId = (String) expression.evaluate(samlResponse, XPathConstants.STRING); +// sessionId = StringEscapeUtils.escapeHtml(StringUtils.trimToNull(sessionId)); + } else { + Logger.warn("No parameter 'SAMLResponse'. Unable to retrieve MOA session id."); + } + } + + } catch (Exception e) { + Logger.warn("Unable to retrieve moa session id.", e); + } + + return sessionId; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java new file mode 100644 index 000000000..965abcde1 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -0,0 +1,370 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas.engine; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Timer; + +import javax.net.ssl.SSLHandshakeException; +import javax.xml.namespace.QName; + +import org.apache.commons.httpclient.MOAHttpClient; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider; +import org.opensaml.xml.XMLObject; + +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; +import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing; +import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; +import at.gv.egovernment.moa.id.saml2.MetadataFilterChain; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.engine.AbstractSAMLEngine; + +public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvider, IGarbageCollectorProcessing { + + private static MOAeIDASChainingMetadataProvider instance = null; + private static Object mutex = new Object(); + + private MetadataProvider internalProvider; + private Map<String, Date> lastAccess = null; + + + public static MOAeIDASChainingMetadataProvider getInstance() { + if (instance == null) { + synchronized (mutex) { + if (instance == null) { + instance = new MOAeIDASChainingMetadataProvider(); + MOAGarbageCollector.addModulForGarbageCollection(instance); + } + } + } + return instance; + } + + + private MOAeIDASChainingMetadataProvider() { + internalProvider = new ChainingMetadataProvider(); + lastAccess = new HashMap<String, Date>(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector() + */ + @Override + public void runGarbageCollector() { + if (!lastAccess.isEmpty()) { + Date now = new Date(); + Date expioredate = new Date(now.getTime() - + Constants.CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT); + Logger.debug("Starting eIDAS Metadata garbag collection (Expioredate:" + + expioredate + ")"); + + List<String> expiredEntities = new ArrayList<String>(); + + Iterator<Entry<String, Date>> lastAccessInterator = lastAccess.entrySet().iterator(); + while(lastAccessInterator.hasNext()) { + Entry<String, Date> element = lastAccessInterator.next(); + if (element.getValue().before(expioredate)) { + Logger.debug("Remove unused eIDAS Metadate: " + element.getKey()); + expiredEntities.add(element.getKey()); + + } + } + + if (!expiredEntities.isEmpty()) { + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + + //get all actually loaded metadata providers + Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders(); + + for (String expired : expiredEntities) { + if (loadedproviders.containsKey(expired)) { + HTTPMetadataProvider provider = loadedproviders.get(expired); + + //destroy metadata provider + provider.destroy(); + + //remove from map + loadedproviders.remove(expired); + + /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) + *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ + //chainProvider.removeMetadataProvider(provider); + Logger.info("Remove not used eIDAS MetadataProvider " + expired + + " after timeout."); + + } else + Logger.warn("eIDAS metadata for EntityID: " + expired + + " is marked as unsed, but no loaded metadata provider is found."); + + } + + try { + synchronized (chainProvider) { + chainProvider.setProviders(new ArrayList<MetadataProvider>(loadedproviders.values())); + + emitChangeEvent(); + } + + } catch (MetadataProviderException e) { + Logger.warn("ReInitalize eIDASA MetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy", e); + + } + } + } + } + + + + private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL) { + HTTPMetadataProvider httpProvider = null; + Timer timer= null; + MOAHttpClient httpClient = null; + try { + AuthConfiguration authConfig = AuthConfigurationProviderFactory.getInstance(); + + httpClient = new MOAHttpClient(); + + HttpClientParams httpClientParams = new HttpClientParams(); + httpClientParams.setSoTimeout(Constants.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); + httpClient.setParams(httpClientParams); + + if (metadataURL.startsWith("https:")) { + try { + MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( + Constants.SSLSOCKETFACTORYNAME, + authConfig.getCertstoreDirectory(), + authConfig.getTrustedCACertificates(), + null, + AuthConfiguration.DEFAULT_X509_CHAININGMODE, + authConfig.isTrustmanagerrevoationchecking()); + + httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); + + } catch (MOAHttpProtocolSocketFactoryException e) { + Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore."); + + } + } + + timer = new Timer(); + httpProvider = new HTTPMetadataProvider(timer, httpClient, + metadataURL); + httpProvider.setParserPool(AbstractSAMLEngine.getNewBasicSecuredParserPool()); + httpProvider.setRequireValidMetadata(true); + httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes + httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours + //httpProvider.setRefreshDelayFactor(0.1F); + + //add Metadata filters + MetadataFilterChain filter = new MetadataFilterChain(); + filter.addFilter(new MOAeIDASMetadataSignatureFilter( + authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE))); + httpProvider.setMetadataFilter(filter); + + httpProvider.initialize(); + + return httpProvider; + + } catch (Throwable e) { + if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { + Logger.warn("SSL-Server certificate for metadata " + + metadataURL + " not trusted.", e); + + } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { + Logger.warn("Signature verification for metadata" + + metadataURL + " FAILED.", e); + + } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { + Logger.warn("Schema validation for metadata " + + metadataURL + " FAILED.", e); + } + + Logger.error( + "Failed to add Metadata file for " + + metadataURL + "[ " + + e.getMessage() + " ]", e); + + if (httpProvider != null) { + Logger.debug("Destroy failed Metadata provider"); + httpProvider.destroy(); + } + + if (timer != null) { + Logger.debug("Destroy Timer."); + timer.cancel(); + } + + + } + + return null; + } + + private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() { + Map<String, HTTPMetadataProvider> loadedproviders = new HashMap<String, HTTPMetadataProvider>(); + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + + //make a Map of all actually loaded HTTPMetadataProvider + List<MetadataProvider> providers = chainProvider.getProviders(); + for (MetadataProvider provider : providers) { + if (provider instanceof HTTPMetadataProvider) { + HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; + loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); + + } + } + + return loadedproviders; + } + + public boolean refreshMetadataProvider(String metadataURL) { + try { + if (MiscUtil.isNotEmpty(metadataURL)) { + Map<String, HTTPMetadataProvider> actuallyLoadedProviders = getAllActuallyLoadedProviders(); + + // check if MetadataProvider is actually loaded + if (actuallyLoadedProviders.containsKey(metadataURL)) { + actuallyLoadedProviders.get(metadataURL).refresh(); + Logger.info("eIDAS metadata for " + + metadataURL + " is refreshed."); + return true; + + } else { + //load new Metadata Provider + ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; + HTTPMetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL); + chainProvider.addMetadataProvider(newMetadataProvider); + + emitChangeEvent(); + Logger.info("eIDAS metadata for " + + metadataURL + " is added."); + return true; + + } + + } else + Logger.debug("Can not refresh eIDAS metadata: NO eIDAS metadata URL."); + + } catch (MetadataProviderException e) { + Logger.warn("Refresh eIDAS metadata for " + + metadataURL + " FAILED.", e); + + } + + return false; + + } + + + public boolean requireValidMetadata() { + return internalProvider.requireValidMetadata(); + } + + public void setRequireValidMetadata(boolean requireValidMetadata) { + internalProvider.setRequireValidMetadata(requireValidMetadata); + } + + public MetadataFilter getMetadataFilter() { + return internalProvider.getMetadataFilter(); + } + + public void setMetadataFilter(MetadataFilter newFilter) + throws MetadataProviderException { + internalProvider.setMetadataFilter(newFilter); + } + + public XMLObject getMetadata() throws MetadataProviderException { + return internalProvider.getMetadata(); + } + + public EntitiesDescriptor getEntitiesDescriptor(String entitiesID) + throws MetadataProviderException { + Logger.warn("eIDAS metadata not support 'EntitiesDescriptor' elements!"); + return null; + + } + + public EntityDescriptor getEntityDescriptor(String entityID) + throws MetadataProviderException { + EntityDescriptor entityDesc = null; + try { + entityDesc = internalProvider.getEntityDescriptor(entityID); + if (entityDesc == null) { + Logger.debug("Can not find eIDAS metadata for entityID: " + entityID + + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } else { + if (!entityDesc.isValid()) + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } + + + } catch (MetadataProviderException e) { + Logger.debug("Can not find eIDAS metadata for entityID: " + entityID + + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) + entityDesc = internalProvider.getEntityDescriptor(entityID); + + } + + if (entityDesc != null) + lastAccess.put(entityID, new Date()); + + return entityDesc; + } + + public List<RoleDescriptor> getRole(String entityID, QName roleName) + throws MetadataProviderException { + return internalProvider.getRole(entityID, roleName); + } + + public RoleDescriptor getRole(String entityID, QName roleName, + String supportedProtocol) throws MetadataProviderException { + return internalProvider.getRole(entityID, roleName, supportedProtocol); + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers() + */ + @Override + public List<Observer> getObservers() { + return ((ChainingMetadataProvider) internalProvider).getObservers(); + } + + protected void emitChangeEvent() { + if ((getObservers() == null) || (getObservers().size() == 0)) { + return; + } + + List<Observer> tempObserverList = new ArrayList<Observer>(getObservers()); + for (ObservableMetadataProvider.Observer observer : tempObserverList) + if (observer != null) + observer.onEvent(this); + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java new file mode 100644 index 000000000..e3ae5c046 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java @@ -0,0 +1,120 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.engine; + +import java.security.KeyStore; + +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; + +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataProcessorI; +import eu.eidas.engine.exceptions.SAMLEngineException; + +/** + * @author tlenz + * + */ +public class MOAeIDASMetadataProviderDecorator implements MetadataProcessorI { + + private MetadataProvider metadataprovider = null; + + /** + * + */ + public MOAeIDASMetadataProviderDecorator(MetadataProvider metadataprovider) { + this.metadataprovider = metadataprovider; + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getEntityDescriptor(java.lang.String) + */ + @Override + public EntityDescriptor getEntityDescriptor(String url) + throws SAMLEngineException { + try { + return this.metadataprovider.getEntityDescriptor(url); + + } catch (MetadataProviderException e) { + throw new SAMLEngineException("eIDAS Metadata processing FAILED.", e); + + } + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getSPSSODescriptor(java.lang.String) + */ + @Override + public SPSSODescriptor getSPSSODescriptor(String url) + throws SAMLEngineException { + return getFirstRoleDescriptor(getEntityDescriptor(url), SPSSODescriptor.class); + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getIDPSSODescriptor(java.lang.String) + */ + @Override + public IDPSSODescriptor getIDPSSODescriptor(String url) + throws SAMLEngineException { + return getFirstRoleDescriptor(getEntityDescriptor(url), IDPSSODescriptor.class); + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, eu.eidas.auth.engine.EIDASSAMLEngine) + */ + @Override + public void checkValidMetadataSignature(String url, EIDASSAMLEngine engine) + throws SAMLEngineException { + //Do nothing, because metadata signature is already validated during + //metadata provider initialization + + } + + /* (non-Javadoc) + * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, java.security.KeyStore) + */ + @Override + public void checkValidMetadataSignature(String url, KeyStore trustStore) + throws SAMLEngineException { + //Do nothing, because metadata signature is already validated during + //metadata provider initialization + + } + + protected <T extends RoleDescriptor> T getFirstRoleDescriptor(EntityDescriptor entityDescriptor, final Class<T> clazz){ + for(RoleDescriptor rd:entityDescriptor.getRoleDescriptors()){ + if(clazz.isInstance(rd)){ + return (T)rd; + } + } + return null; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java new file mode 100644 index 000000000..c9f3e5bcd --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java @@ -0,0 +1,132 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.engine; + +import java.io.IOException; +import java.io.StringWriter; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.provider.FilterException; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.xml.XMLObject; + +import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils; +import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class MOAeIDASMetadataSignatureFilter implements MetadataFilter { + + private String trustProfileID = null; + + /** + * + */ + public MOAeIDASMetadataSignatureFilter(String trustProfileID) { + this.trustProfileID = trustProfileID; + + } + + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) + */ + @Override + public void doFilter(XMLObject metadata) throws FilterException { + if (metadata instanceof EntityDescriptor) { + if (((EntityDescriptor) metadata).isSigned()) { + EntityDescriptor entityDes = (EntityDescriptor) metadata; + //check signature; + try { + Transformer transformer = TransformerFactory.newInstance() + .newTransformer(); + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + DOMSource source = new DOMSource(metadata.getDOM()); + transformer.transform(source, sr); + sw.close(); + String metadataXML = sw.toString(); + + SignatureVerificationUtils sigVerify = + new SignatureVerificationUtils(); + VerifyXMLSignatureResponse result = sigVerify.verify( + metadataXML.getBytes(), trustProfileID); + + //check signature-verification result + if (result.getSignatureCheckCode() != 0) { + Logger.warn("eIDAS Metadata signature-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getSignatureCheckCode()); + throw new FilterException("eIDAS Metadata signature-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getSignatureCheckCode()); + + } + + if (result.getCertificateCheckCode() != 0) { + Logger.warn("eIDAS Metadata certificate-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getCertificateCheckCode()); + throw new FilterException("eIDAS Metadata certificate-verification FAILED!" + + " Metadata: " + entityDes.getEntityID() + + " StatusCode:" + result.getCertificateCheckCode()); + + } + + + } catch (MOAIDException | TransformerFactoryConfigurationError | TransformerException | IOException e) { + Logger.error("eIDAS Metadata verification has an interal error.", e); + throw new FilterException("eIDAS Metadata verification has an interal error." + + " Message:" + e.getMessage()); + + } + + + } else { + Logger.warn("eIDAS Metadata root-element MUST be signed."); + throw new FilterException("eIDAS Metadata root-element MUST be signed.'"); + + } + + } else { + Logger.warn("eIDAS Metadata root-element is not of type 'EntityDescriptor'"); + throw new FilterException("eIDAS Metadata root-element is not of type 'EntityDescriptor'"); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java new file mode 100644 index 000000000..98bc559d2 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.exceptions; + +import at.gv.egovernment.moa.id.config.ConfigurationException; + +/** + * @author tlenz + * + */ +public class EIDASEngineConfigurationException extends ConfigurationException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param messageId + * @param parameters + * @param wrapped + */ + public EIDASEngineConfigurationException(String messageId, + Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + } + + /** + * @param string + * @param object + */ + public EIDASEngineConfigurationException(String string, Object[] object) { + super(string, object); + } + + + + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java new file mode 100644 index 000000000..95690bbeb --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.exceptions; + + +/** + * @author tlenz + * + */ +public class EIDASEngineException extends Exception { + + /** + * @param string + * @param e + */ + public EIDASEngineException(String string, Throwable e) { + super(string, e); + } + + /** + * + */ + private static final long serialVersionUID = 1559812927427153879L; + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java new file mode 100644 index 000000000..7840ae2e6 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.exceptions; + +/** + * @author tlenz + * + */ +public class eIDASAttributeException extends Exception { + + private static final long serialVersionUID = 1L; + + public eIDASAttributeException(String message) { + super(message); + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java new file mode 100644 index 000000000..f4d6c4ad4 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java @@ -0,0 +1,185 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import eu.eidas.auth.commons.IPersonalAttributeList; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; +import at.gv.egovernment.moa.id.auth.data.IdentityLink; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException; +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestStorage; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * @author tlenz + * + */ +public class CreateIdentityLinkTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try{ + String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID); + String pendingRequestID = (String) executionContext.get("pendingRequestID"); + + //load pending request + IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure."); + throw new MOAIDException("auth.28", new Object[]{pendingRequestID}); + + } + + //load MOASession object and OA-configuration + AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid); + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + + //get eIDAS attributes from MOA-Session + IPersonalAttributeList eIDASAttributes = moasession.getGenericDataFromSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + IPersonalAttributeList.class); + + AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); + IdentityLink identityLink = null; + + //connect SZR-Gateway + //TODO: implement SZR-Gateway communication!!!! + if(true) { + + // create fake IdL + // - fetch IdL template from resources + InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); + Element idlTemplate = DOMUtils.parseXmlValidating(s); + + identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); + + // replace data + Element idlassertion = identityLink.getSamlAssertion(); + + // - set bpk/wpbk; + Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)) + throw new eIDASAttributeException("PersonalIdentifier is missing"); + String eIdentifier = eIDASAttributes.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).getValue().get(0); + prIdentification.getFirstChild().setNodeValue(eIdentifier); + + // - set last name + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTFAMILYNAME)) + throw new eIDASAttributeException("currentFamilyName is missing"); + String familyName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME).getValue().get(0); + prFamilyName.getFirstChild().setNodeValue(familyName); + + // - set first name + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTGIVENNAME)) + throw new eIDASAttributeException("currentGivenName is missing"); + String givenName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME).getValue().get(0); + prGivenName.getFirstChild().setNodeValue(givenName); + + // - set date of birth + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_DATEOFBIRTH)) + throw new eIDASAttributeException("dateOfBirth is missing"); + String dateOfBirth = eIDASAttributes.get(Constants.eIDAS_ATTR_DATEOFBIRTH).getValue().get(0); + dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(dateOfBirth)); + prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth); + + identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + + //resign IDL + IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); + Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey()); + identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink(); + + } else { + //contact SZR Gateway + Logger.debug("Starting connecting SZR Gateway"); + + //TODO:!!!!!! + + } + + Logger.debug("SZR communication was successfull"); + + if (identityLink == null) { + Logger.error("SZR Gateway did not return an identity link."); + throw new MOAIDException("stork.10", null); + } + + MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED); + moasession.setForeigner(true); + moasession.setIdentityLink(identityLink); + moasession.setBkuURL("Not applicable (eIDASAuthentication)"); + + //store MOA-session to database + AuthenticationSessionStoreage.storeSession(moasession); + + } catch (ParseException | MOAIDException | MOADatabaseException | ParserConfigurationException | SAXException | IOException e) { + throw new TaskExecutionException("IdentityLink generation for foreign person FAILED.", e); + + } catch (eIDASAttributeException e) { + throw new TaskExecutionException("Minimum required eIDAS attributeset not found.", e); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java new file mode 100644 index 000000000..06643ec53 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java @@ -0,0 +1,210 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.config.stork.CPEPS; +import at.gv.egovernment.moa.id.config.stork.StorkAttribute; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestStorage; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.commons.EIDASAuthnRequest; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.EidasLoaCompareType; +import eu.eidas.auth.commons.EidasLoaLevels; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.PersonalAttributeList; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.core.eidas.SPType; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; + +/** + * @author tlenz + * + */ +public class GenerateAuthnRequestTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + + try{ + String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID); + String pendingRequestID = (String) executionContext.get("pendingRequestID"); + + //load pending request + IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + Logger.info("No PendingRequest with Id: '{}' Maybe, a transaction timeout occure.", new Object[] {pendingRequestID}); + throw new MOAIDException("auth.28", new Object[]{pendingRequestID}); + + } + + //load MOASession object, configuration and OA-configuration + AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid); + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + AuthConfiguration moaconfig = AuthConfigurationProviderFactory.getInstance(); + + // get target country + String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC); + + if (StringUtils.isEmpty(citizenCountryCode)) { + // illegal state; task should not have been executed without a selected country + throw new AuthenticationException("stork.22", new Object[] { moasessionid }); + } + + CPEPS cpeps = moaconfig.getStorkConfig().getCPEPS(citizenCountryCode); + if(null == cpeps) { + Logger.error("PEPS unknown for country", new Object[] {citizenCountryCode}); + throw new AuthenticationException("Unknown PEPS for citizen country '{}'", new Object[] {citizenCountryCode}); + } + Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode); + String destination = cpeps.getPepsURL().toString().split(";")[1].trim(); // FIXME convenience for metadata url and assertion destination + String metadataUrl = cpeps.getPepsURL().toString().split(";")[0].trim(); + + // assemble requested attributes + Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes(); + + // - prepare attribute list + IPersonalAttributeList pAttList = new PersonalAttributeList(); + + // - fill container + for (StorkAttribute current : attributesFromConfig) { + PersonalAttribute newAttribute = new PersonalAttribute(); + newAttribute.setName(current.getName()); + + boolean globallyMandatory = false; + for (StorkAttribute currentGlobalAttribute : moaconfig.getStorkConfig().getStorkAttributes()) + if (current.getName().equals(currentGlobalAttribute.getName())) { + globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory()); + break; + } + + newAttribute.setIsRequired(current.getMandatory() || globallyMandatory); + pAttList.add(newAttribute); + } + + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //build eIDAS AuthnRequest + EIDASAuthnRequest authnRequest = new EIDASAuthnRequest(); + authnRequest.setProviderName(pendingReq.getAuthURL()); + authnRequest.setPersonalAttributeList(pAttList); + + authnRequest.setIssuer(moaconfig.getPublicURLPrefix() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); + + authnRequest.setDestination(destination); + authnRequest.setEidasNameidFormat(EIDASAuthnRequest.NAMEID_FORMAT_UNSPECIFIED); + authnRequest.setEidasLoA(EidasLoaLevels.LOW.stringValue()); + authnRequest.setEidasLoACompareType(EidasLoaCompareType.MINIMUM.stringValue()); + authnRequest.setSPType(SPType.DEFAULT_VALUE); + + engine.initRequestedAttributes(pAttList); + authnRequest = engine.generateEIDASAuthnRequest(authnRequest); + + //encode AuthnRequest + byte[] token = authnRequest.getTokenSaml(); + String SAMLRequest = EIDASUtil.encodeSAMLToken(token); + + + //send + try { + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm"); + VelocityContext context = new VelocityContext(); + + String actionType = "SAMLRequest"; + context.put(actionType, SAMLRequest); + Logger.debug("Encoded " + actionType + " original: " + SAMLRequest); + + context.put("RelayState", moasessionid); + + Logger.debug("Using assertion consumer url as action: " + destination); + context.put("action", destination); + + Logger.debug("Starting template merge"); + StringWriter writer = new StringWriter(); + + Logger.debug("Doing template merge"); + template.merge(context, writer); + Logger.debug("Template merge done"); + + Logger.debug("Sending html content: " + writer.getBuffer().toString()); + + response.setContentType("text/html;charset=UTF-8"); + response.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8")); + + } catch (IOException e) { + Logger.error("Velocity IO error: " + e.getMessage()); + throw new MOAIDException("stork.15", null); // TODO + } catch (Exception e) { + Logger.error("Velocity general error: " + e.getMessage()); + throw new MOAIDException("stork.15", null); // TODO + } + + }catch (EIDASSAMLEngineException e){ + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", + new EIDASEngineException("Could not generate token for Saml Request", e)); + + } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", e); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java new file mode 100644 index 000000000..693807d63 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java @@ -0,0 +1,109 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import eu.eidas.auth.commons.EIDASAuthnResponse; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestStorage; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { + + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { + + try{ + String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID); + String pendingRequestID = (String) executionContext.get("pendingRequestID"); + + //load pending request + IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure."); + throw new MOAIDException("auth.28", new Object[]{pendingRequestID}); + + } + + //load MOASession object and OA-configuration + AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid); + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + + //get SAML Response and decode it + String base64SamlToken = request.getParameter("SAMLResponse"); + if (MiscUtil.isEmpty(base64SamlToken)) { + Logger.warn("No eIDAS SAMLReponse found in http request."); + throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null); + + } + byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken); + + //get eIDAS SAML-engine + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //validate SAML token + EIDASAuthnResponse samlResp = engine.validateEIDASAuthnResponse(decSamlToken, + request.getRemoteHost(), Constants.CONFIG_PROPS_SKEWTIME); + + boolean encryptedResponse=engine.isEncryptedSamlResponse(decSamlToken); + if (encryptedResponse) { + Logger.info("Received encrypted eIDAS SAML-Response."); + //TODO: check if additional decryption operation is required + + } + + //MOA-ID specific response validation + //TODO: implement MOA-ID specific response validation + + //update MOA-Session data with received information + Logger.debug("Store eIDAS response information into MOA-session."); + moasession.setQAALevel(samlResp.getAssuranceLevel()); + moasession.setCcc(samlResp.getCountry()); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, + new MOAPersonalAttributeList(samlResp.getPersonalAttributeList())); + + moasession.setGenericDataToSession( + AuthenticationSessionStorageConstants.eIDAS_RESPONSE, + decSamlToken); + + //set general information to MOA-Session + moasession.setAuthURL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/"); + + //store MOA-session to database + AuthenticationSessionStoreage.storeSession(moasession); + + }catch (EIDASSAMLEngineException e) { + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException("eIDAS Response processing FAILED.", + new EIDASEngineException("Could not validate eIDAS response", e)); + + } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException("eIDAS Response processing FAILED.", e); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java new file mode 100644 index 000000000..573163af0 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.utils; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.PersonalAttributeList; + + +/** + * @author tlenz + * + */ +public class MOAOrderedAttributeIterator implements Iterator<PersonalAttribute> { + + private MOAPersonalAttributeList pal; + private Iterator<String> keyIterator; + + public MOAOrderedAttributeIterator(MOAPersonalAttributeList palArg) { + this.pal = palArg; + keyIterator = palArg.getInsertOrder().iterator(); + } + + @Override + public boolean hasNext() { + return keyIterator.hasNext(); + } + + @Override + public PersonalAttribute next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return pal.get(keyIterator.next()); + } + + @Override + public void remove() { + Logger.error("Not implemented"); + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java new file mode 100644 index 000000000..5cc100b70 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java @@ -0,0 +1,343 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.utils; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.lang.StringUtils; + +import at.gv.egovernment.moa.logging.Logger; + +import eu.eidas.auth.commons.AttributeConstants; +import eu.eidas.auth.commons.AttributeUtil; +import eu.eidas.auth.commons.EIDASErrors; +import eu.eidas.auth.commons.EIDASParameters; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.EIDASValues; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.commons.exceptions.InternalErrorEIDASException; + +/** + * @author tlenz + * + */ +public final class MOAPersonalAttributeList extends + ConcurrentHashMap<String, PersonalAttribute> implements IPersonalAttributeList { + + /** + * + */ + private static final long serialVersionUID = -4488124133022713089L; + + public MOAPersonalAttributeList(IPersonalAttributeList eIDASAttributeList) { + super(); + Iterator<PersonalAttribute> element = eIDASAttributeList.iterator(); + while(element.hasNext()) + add(element.next()); + + } + + /** + * Hash with the latest fetched attribute name alias. + */ + private Map<String, Integer> latestAttrAlias = + new HashMap<String, Integer>(); + + /** + * Hash with mapping number of alias or the attribute name. + */ + private Map<String, Integer> attrAliasNumber = + new HashMap<String, Integer>(); + private List<String> insertOrder = new ArrayList<String>(); + + /** + * Obtain the insertOrder Collection + * + * @return defensive copy of the collection + */ + List<String> getInsertOrder() { + return Collections.unmodifiableList(this.insertOrder); + } + + /** + * Default constructor. + */ + public MOAPersonalAttributeList() { + super(); + + } + + /** + * Constructor with initial capacity for the PersonalAttributeList size. + * + * @param capacity The initial capacity for the PersonalAttributeList. + */ + public MOAPersonalAttributeList(final int capacity) { + super(capacity); + } + + /** + * {@inheritDoc} + */ + public Iterator<PersonalAttribute> iterator() { + return new MOAOrderedAttributeIterator(this); + } + + /** + * {@inheritDoc} + */ + public PersonalAttribute get(final Object key) { + String attrName = (String) key; + + if (this.latestAttrAlias == null) + this.latestAttrAlias = new HashMap<String, Integer>(); + + if (this.attrAliasNumber == null) + this.attrAliasNumber = new HashMap<String, Integer>(); + + if (this.latestAttrAlias.containsKey(key)) { + attrName = attrName + this.latestAttrAlias.get(key); + } else { + if (this.attrAliasNumber.containsKey(key)) { + this.latestAttrAlias.put(attrName, this.attrAliasNumber.get(key)); + } + } + return super.get(attrName); + } + + /** + * {@inheritDoc} + */ + public void add(final PersonalAttribute value) { + if (value != null) { + this.put(value.getName(), value); + } + } + + /** + * {@inheritDoc} + */ + public PersonalAttribute put(final String key, final PersonalAttribute val) { + if (StringUtils.isNotEmpty(key) && val != null) { + // Validate if attribute name already exists! + String attrAlias = key; + if (this.containsKey(attrAlias)) { + if (this.attrAliasNumber == null) + this.attrAliasNumber = new HashMap<String, Integer>(); + if (!val.isEmptyValue() && StringUtils.isNumeric(val.getValue().get(0))) { + final String attrValue = val.getValue().get(0); + attrAlias = key + attrValue; + this.attrAliasNumber.put(key, Integer.valueOf(attrValue)); + } else { + final PersonalAttribute attr = super.get(key); + if (!attr.isEmptyValue() + && StringUtils.isNumeric(attr.getValue().get(0))) { + attrAlias = key + attr.getValue().get(0); + super.put(key, (PersonalAttribute) attr); + this.attrAliasNumber.put(key, null); + } + } + } else { + if (insertOrder == null) + insertOrder = new ArrayList<String>(); + + insertOrder.add(key); + } + return super.put(attrAlias, val); + } else { + return null; + } + } + + @Override + public PersonalAttribute remove(Object key) { + insertOrder.remove(key); + return super.remove(key); + } + + /** + * {@inheritDoc} + */ + public void populate(final String attrList) { + final StringTokenizer strToken = + new StringTokenizer(attrList, EIDASValues.ATTRIBUTE_SEP.toString()); + + while (strToken.hasMoreTokens()) { + final PersonalAttribute persAttr = new PersonalAttribute(); + String[] tuples = + strToken.nextToken().split(EIDASValues.ATTRIBUTE_TUPLE_SEP.toString(), + AttributeConstants.NUMBER_TUPLES.intValue()); + + // Convert to the new format if needed! + tuples = convertFormat(tuples); + + if (AttributeUtil.hasValidTuples(tuples)) { + final int attrValueIndex = + AttributeConstants.ATTR_VALUE_INDEX.intValue(); + final String tmpAttrValue = + tuples[attrValueIndex].substring(1, + tuples[attrValueIndex].length() - 1); + final String[] vals = + tmpAttrValue.split(EIDASValues.ATTRIBUTE_VALUE_SEP.toString()); + + persAttr.setName(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]); + persAttr.setIsRequired(Boolean + .valueOf(tuples[AttributeConstants.ATTR_TYPE_INDEX.intValue()])); + // check if it is a complex value + if (tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()] + .equals(EIDASParameters.COMPLEX_ADDRESS_VALUE.toString())) { + persAttr.setComplexValue(createComplexValue(vals)); + } else { + persAttr.setValue(createValues(vals)); + } + + if (tuples.length == AttributeConstants.NUMBER_TUPLES.intValue()) { + persAttr.setStatus(tuples[AttributeConstants.ATTR_STATUS_INDEX + .intValue()]); + } + this.put(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()], + persAttr); + + } else { + Logger.info("BUSINESS EXCEPTION : Invalid personal attribute list tuples"); + } + + } + } + + /** + * Returns a copy of this <tt>IPersonalAttributeList</tt> instance. + * + * @return The copy of this IPersonalAttributeList. + */ + public Object clone() { + try { + MOAPersonalAttributeList theClone= (MOAPersonalAttributeList)super.clone(); + theClone.insertOrder=new ArrayList<String>(insertOrder); + return theClone; + + } catch (CloneNotSupportedException e) { + throw new InternalErrorEIDASException( + EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorCode()), + EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorMessage()), e); + } + } + + /** + * Creates a string in the following format. + * + * attrName:attrType:[attrValue1,attrValue2=attrComplexValue]:attrStatus; + * + * @return {@inheritDoc} + */ + @Override + public String toString() { + final StringBuilder strBuilder = new StringBuilder(); + final Iterator<String> iteratorInsertOrder = insertOrder.iterator(); + while (iteratorInsertOrder.hasNext()) { + String key = iteratorInsertOrder.next(); + final PersonalAttribute attr = get(key); + strBuilder.append(attr.toString()); + if (isNumberAlias(key)) { + strBuilder.append(get(key).toString()); + } + } + return strBuilder.toString(); + } + + /** + * Validates and creates the attribute's complex values. + * + * @param values The complex values. + * @return The {@link Map} with the complex values. + * @see Map + */ + private Map<String, String> createComplexValue(final String[] values) { + final Map<String, String> complexValue = new HashMap<String, String>(); + for (final String val : values) { + final String[] tVal = val.split("="); + if (StringUtils.isNotEmpty(val) && tVal.length == 2) { + complexValue.put(tVal[0], AttributeUtil.unescape(tVal[1])); + } + } + return complexValue; + } + + /** + * Validates and creates the attribute values. + * + * @param vals The attribute values. + * @return The {@link List} with the attribute values. + * @see List + */ + private List<String> createValues(final String[] vals) { + final List<String> values = new ArrayList<String>(); + for (final String val : vals) { + if (StringUtils.isNotEmpty(val)) { + values.add(AttributeUtil.unescape(val)); + } + } + return values; + } + + ////////////////// + /** + * Converts the attribute tuple (attrName:attrType...) to the new format. + * + * @param tuples The attribute tuples to convert. + * @return The attribute tuples in the new format. + */ + private String[] convertFormat(final String[] tuples) { + final String[] newFormatTuples = + new String[AttributeConstants.NUMBER_TUPLES.intValue()]; + if (tuples != null) { + System.arraycopy(tuples, 0, newFormatTuples, 0, tuples.length); + + for (int i = tuples.length; i < newFormatTuples.length; i++) { + if (i == AttributeConstants.ATTR_VALUE_INDEX.intValue()) { + newFormatTuples[i] = "[]"; + } else { + newFormatTuples[i] = ""; + } + } + } + return newFormatTuples; + } + + public boolean isNumberAlias(String key) { + return this.attrAliasNumber.containsKey(key); + } + + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java new file mode 100644 index 000000000..8e46f0ef1 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -0,0 +1,71 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.utils; + +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; +import eu.eidas.samlengineconfig.CertificateConfigurationManager; + +/** + * @author tlenz + * + */ +public class SAMLEngineUtils { + + private static EIDASSAMLEngine eIDASEngine = null; + + public static synchronized EIDASSAMLEngine createSAMLEngine() throws EIDASEngineException{ + + if (eIDASEngine == null) { + try { + //get eIDAS SAMLengine configuration from MOA-ID configuration + CertificateConfigurationManager configManager = new MOAIDCertificateManagerConfigurationImpl(); + + //initial eIDAS SAMLengine + EIDASSAMLEngine engine = EIDASSAMLEngine.createSAMLEngine(Constants.eIDAS_SAML_ENGINE_NAME, + configManager); + + //set Metadata managment to eIDAS SAMLengine + engine.setMetadataProcessor( + new MOAeIDASMetadataProviderDecorator( + MOAeIDASChainingMetadataProvider.getInstance())); + + eIDASEngine = engine; + + } catch (EIDASSAMLEngineException e) { + Logger.error("eIDAS SAMLengine initialization FAILED!", e); + throw new EIDASEngineException("eIDAS SAMLengine initialization FAILED!", e); + + } + } + + return eIDASEngine; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java new file mode 100644 index 000000000..5040f1fe3 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.eidas; + +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Map.Entry; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.springframework.http.MediaType; + +import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.eidas.auth.commons.EIDASAuthnResponse; +import eu.eidas.auth.commons.EIDASStatusCode; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.PersonalAttribute; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataUtil; + + +/** + * Second request step - after authentication of the user is done and moasession obtained, + * process request and forward the user further to PEPS and/or other entities + * + * @author bsuzic + */ + +public class AuthenticationRequest implements IAction { + + @Override + public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { + EIDASData eidasRequest; + if(req instanceof EIDASData) + eidasRequest = (EIDASData) req; + else + throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()}); + + + // gather attributes + MOAPersonalAttributeList resultingAttributeList = (MOAPersonalAttributeList) eidasRequest.getEidasRequestedAttributes().clone(); + + for(Entry<String, PersonalAttribute> current : resultingAttributeList.entrySet()) { + String newValue = ""; + + // TODO make use of proper builder + switch(current.getKey()) { + case Constants.eIDAS_ATTR_DATEOFBIRTH: newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); break; + case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: newValue = authData.getFamilyName();break; + case Constants.eIDAS_ATTR_CURRENTGIVENNAME: newValue = authData.getGivenName();break; + case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: newValue = new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), + eidasRequest.getTarget()); break; + } + + if("".equals(newValue)) + current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString()); + else { + current.getValue().getValue().clear(); + current.getValue().getValue().add(newValue); + current.getValue().setStatus(EIDASStatusCode.STATUS_AVAILABLE.toString()); + } + } + + // construct eIDaS response + EIDASAuthnResponse response = new EIDASAuthnResponse(); + response.setPersonalAttributeList(resultingAttributeList); + + // - create metadata url + String pubURLPrefix = req.getAuthURL(); + String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA; + response.setIssuer(metadata_url); + + response.setAssuranceLevel(authData.getEIDASQAALevel()); + + String token = null; + try { + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + // check if we have the destination available, supply it if not + if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { + String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( + new MOAeIDASMetadataProviderDecorator(MOAeIDASChainingMetadataProvider.getInstance()), + engine, + eidasRequest.getEidasRequest()); + eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl); + } + + response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true); + + + token = EIDASUtil.encodeSAMLToken(response.getTokenSaml()); + } catch(Exception e) { + e.printStackTrace(); + } + + // send the response + try { + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html"); + VelocityContext context = new VelocityContext(); + + context.put("SAMLResponse", token); + Logger.debug("SAMLResponse original: " + token); + + Logger.debug("Putting assertion consumer url as action: " + eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()); + context.put("action", eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()); + Logger.trace("Starting template merge"); + StringWriter writer = new StringWriter(); + + Logger.trace("Doing template merge"); + template.merge(context, writer); + Logger.trace("Template merge done"); + + Logger.trace("Sending html content : " + new String(writer.getBuffer())); + + httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8")); + httpResp.setContentType(MediaType.TEXT_HTML_VALUE); + + } catch (Exception e) { + Logger.error("Velocity error: " + e.getMessage()); + } + + return null; + } + + @Override + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { + return true; + } + + @Override + public String getDefaultActionName() { + return "eIDAS_AuthnRequest"; + } + + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java new file mode 100644 index 000000000..374c3df30 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java @@ -0,0 +1,96 @@ +package at.gv.egovernment.moa.id.protocols.eidas; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.opensaml.saml2.core.Attribute; + +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import eu.eidas.auth.commons.EIDASAuthnRequest; + +public class EIDASData extends RequestImpl { + + /** + * @param req + * @throws ConfigurationException + */ + public EIDASData(HttpServletRequest req) throws ConfigurationException { + super(req); + + } + + /** The Constant serialVersionUID. */ + private static final long serialVersionUID = 8765755670214923910L; + + /** The attributes requested by the eIDaS. */ + private MOAPersonalAttributeList attributes; + + /** The incoming eIDaS SAML2 AuthnRequest. */ + private EIDASAuthnRequest authnRequest; + + /** The ip address of the requester. */ + private String remoteIPAddress; + + @Override + public List<Attribute> getRequestedAttributes() { + // TODO Auto-generated method stub + return null; + } + + /** + * Gets the eidas requested attributes. + * + * @return the requested attributes + */ + public MOAPersonalAttributeList getEidasRequestedAttributes() { + return (MOAPersonalAttributeList) attributes.clone(); + } + + /** + * Sets the eidas requested attributes. + * + * @param personalAttributeList the requested attributes + */ + public void setEidasRequestedAttributes(MOAPersonalAttributeList personalAttributeList) { + attributes = personalAttributeList; + } + + /** + * Gets the eidas request. + * + * @return the eidas request + */ + public EIDASAuthnRequest getEidasRequest() { + return authnRequest; + } + + /** + * Sets the eidas request. + * + * @param request the new eidas request + */ + public void setEidasRequest(EIDASAuthnRequest request) { + authnRequest = request; + } + + /** + * Gets the remote address. + * + * @return the remote address + */ + public String getRemoteAddress() { + return remoteIPAddress; + } + + /** + * Sets the remote address. + * + * @param remoteIP the new remote address + */ + public void setRemoteAddress(String remoteIP) { + remoteIPAddress = remoteIP; + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java new file mode 100644 index 000000000..b652503f8 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.eidas; + +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IModulInfo; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.EIDASAuthnRequest; +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.engine.EIDASSAMLEngine; + +/** + * Stork 2 Protocol Support + * + * @author bsuzic + */ +public class EIDASProtocol extends MOAIDAuthConstants implements IModulInfo { + + public static final String NAME = EIDASProtocol.class.getName(); + public static final String PATH = "eidas"; + + public static final String AUTHENTICATIONREQUEST = "AuthenticationRequest"; + public static final String METADATAREQUEST = "MetadataRequest"; + + private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); + + static { + actions.put(AUTHENTICATIONREQUEST, new AuthenticationRequest()); + actions.put(METADATAREQUEST, new EidasMetaDataRequest()); + + } + + public String getName() { + return NAME; + } + + public String getPath() { + return PATH; + } + + public IAction getAction(String action) { + return actions.get(action); + } + + public EIDASProtocol() { + super(); + } + + /* + First request step - send it to BKU selection for user authentication. After the user credentials + and other info are obtained, in the second step the request will be processed and the user redirected + */ + public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action, + String sessionId, String transactionId) throws MOAIDException { + + Logger.info("received an eIDaS request"); + + //get SAML Response and decode it + String base64SamlToken = request.getParameter("SAMLRequest"); + if (MiscUtil.isEmpty(base64SamlToken)) { + Logger.warn("No eIDAS SAMLRequest found in http request."); + throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null); + } + byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken); + + try { + //get eIDAS SAML-engine + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + //validate SAML token + EIDASAuthnRequest samlReq = engine.validateEIDASAuthnRequest(decSamlToken); + + // memorize important stuff + EIDASData result = new EIDASData(request); + + // - memorize remote ip + result.setRemoteAddress(request.getRemoteAddr()); + + // - memorize country code of target country + result.setTarget(samlReq.getCountry()); + + // - memorize requested attributes + result.setEidasRequestedAttributes(new MOAPersonalAttributeList(samlReq.getPersonalAttributeList())); + + // - memorize whole request + samlReq.setPersonalAttributeList(result.getEidasRequestedAttributes()); // circumvent non-serializable eidas personal attribute list + result.setEidasRequest(samlReq); + + // - memorize OA url + result.setOAURL(samlReq.getIssuer()); + + // - memorize OA config + OAAuthParameter oaConfig = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(result.getOAURL()); + if (oaConfig == null) + throw new AuthenticationException("stork.12", new Object[]{result.getOAURL()}); + result.setOnlineApplicationConfiguration(oaConfig); + + return result; + } catch(Exception e) { + Logger.error("error in preprocessing step", e); + throw new MOAIDException("error in preprocessing step", null); + } + } + + public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) { + return null; + } + + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable { + return false; + } + + public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { + return false; + } +} + + diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java new file mode 100644 index 000000000..31594f515 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright 2015 e-SENS project + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be + * approved by the European Commission - subsequent versions of + * the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.eidas; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.springframework.http.MediaType; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import eu.eidas.auth.engine.EIDASSAMLEngine; +import eu.eidas.auth.engine.metadata.MetadataConfigParams; +import eu.eidas.auth.engine.metadata.MetadataGenerator; +import eu.eidas.engine.exceptions.SAMLEngineException; + + +/** + * First version to provide some valid metadata to an asking eIDaS node + */ +public class EidasMetaDataRequest implements IAction { + private Logger logger = org.slf4j.LoggerFactory.getLogger(EidasMetaDataRequest.class); + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) + */ + @Override + public SLOInformationInterface processRequest(IRequest req, + HttpServletRequest httpReq, HttpServletResponse httpResp, + IAuthData authData) throws MOAIDException { + + try { + logger.debug("EidasMetaDataServlet GET"); + + String pubURLPrefix = req.getAuthURL(); + + String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA; + + String sp_return_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_SP_POST; + String metaData = generateMetadata(metadata_url, sp_return_url); + + logger.trace(metaData); + + httpResp.setContentType(MediaType.TEXT_XML_VALUE); + httpResp.getWriter().print(metaData); + httpResp.flushBuffer(); + } catch (Exception e) { + e.printStackTrace(); + } + + + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, + HttpServletResponse httpResp) { + return false; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + @Override + public String getDefaultActionName() { + return "eIDAS-Metadata Action"; + + } + + public String generateMetadata(String metadata_url, String sp_return_url) throws SAMLEngineException, EIDASEngineException{ + String metadata="invalid metadata"; + + EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + + MetadataGenerator generator = new MetadataGenerator(); + MetadataConfigParams mcp=new MetadataConfigParams(); + generator.setConfigParams(mcp); + generator.initialize(engine); + mcp.setEntityID(metadata_url); + + generator.addSPRole(); + String returnUrl = sp_return_url; + mcp.setAssertionConsumerUrl(returnUrl); + + generator.addIDPRole(); + mcp.setAssuranceLevel("http://eidas.europa.eu/LoA/substantial"); // TODO make configurable + + metadata = generator.generateMetadata(); + return metadata; + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo new file mode 100644 index 000000000..31d15951c --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo @@ -0,0 +1 @@ +at.gv.egovernment.moa.id.protocols.eidas.EIDASProtocol
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml new file mode 100644 index 000000000..f24ff1c28 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition id="eIDASAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"> + + + <pd:Task id="createAuthnRequest" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.GenerateAuthnRequestTask" /> + <pd:Task id="receiveAuthnResponse" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.ReceiveAuthnResponseTask" async="true" /> + <pd:Task id="finalizeAuthentication" class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.FinalizeAuthenticationTask" /> + <pd:Task id="generateIdentityLink" class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.CreateIdentityLinkTask" /> + + <pd:StartEvent id="start" /> + <pd:Transition from="start" to="createAuthnRequest" /> + <pd:Transition from="createAuthnRequest" to="receiveAuthnResponse" /> + <pd:Transition from="receiveAuthnResponse" to="generateIdentityLink" /> + <pd:Transition from="generateIdentityLink" to="finalizeAuthentication" /> + <pd:Transition from="finalizeAuthentication" to="end" /> + <pd:EndEvent id="end" /> + +</pd:ProcessDefinition> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml new file mode 100644 index 000000000..0e1b60fe7 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.authmodule.beans.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:annotation-config /> + + <bean id="eIDASAuthModule" class="at.gv.egovernment.moa.id.auth.modules.eidas.eIDASAuthenticationModulImpl"> + <property name="priority" value="1" /> + </bean> + +</beans> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm new file mode 100644 index 000000000..3bd225b00 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm @@ -0,0 +1,41 @@ +## +## Velocity Template for SAML 2 HTTP-POST binding +## +## Velocity context may contain the following properties +## action - String - the action URL for the form +## RelayState - String - the relay state for the message +## SAMLRequest - String - the Base64 encoded SAML Request +## SAMLResponse - String - the Base64 encoded SAML Response +## Contains target attribute to delegate PEPS authentication out of iFrame + +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + </head> + + <body onload="document.forms[0].submit()"> + <noscript> + <p> + <strong>Note:</strong> Since your browser does not support JavaScript, + you must press the Continue button once to proceed. + </p> + </noscript> + + <form action="${action}" method="post" target="_top"> + <div> + #if($RelayState)<input type="hidden" name="RelayState" value="${RelayState}"/>#end + + #if($SAMLRequest)<input type="hidden" name="SAMLRequest" value="${SAMLRequest}"/>#end + + #if($SAMLResponse)<input type="hidden" name="SAMLResponse" value="${SAMLResponse}"/>#end + + </div> + <noscript> + <div> + <input type="submit" value="Continue"/> + </div> + </noscript> + </form> + + </body> +</html>
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml new file mode 100644 index 000000000..09084a34f --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID13456264458587874" IssueInstant="2012-08-22T11:07:25+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> + <saml:AttributeStatement> + <saml:Subject> + <saml:SubjectConfirmation> + <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> + <saml:SubjectConfirmationData> + <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>wJO/bvDJjUysG0yARn7I6w==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>XXXRúùd</pr:GivenName><pr:FamilyName primary="undefined">XXXVàn Nisteĺrooy</pr:FamilyName></pr:Name><pr:DateOfBirth>1969-02-13</pr:DateOfBirth></pr:Person> + </saml:SubjectConfirmationData> + </saml:SubjectConfirmation> + </saml:Subject> + <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="22280299907126338788314199678167217078072953115254374209747379168424021905237" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="40387096985250872237992703378062984723606079359080588656963239072881568409170" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><dsig:RSAKeyValue><dsig:Modulus>4Y4FL09VhczsfYQgFPuycP8quJNZBAAu1R1rFXNodI2711B6BTMjAGQn6xuFWfd3/nyFav/MLTr/ +t2VazvANS4TRFxJAcWyIx7xbxCdzZr6gJ+FCmq4g5JPrQvt50v3JX+wKSYft1gHBOWlDn90Ia4Gm +P8MVuze21T+VVKM6ZklmS6d5PT1er/uYQFydGErmJ17xlSQG6Fi5xuftopBDyJxG1tL1KIebpLFg +gaM2EyuB1HxH8/+Mfqa4UgeqIH65</dsig:Modulus><dsig:Exponent>AQAB</dsig:Exponent></dsig:RSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement> + <dsig:Signature> + <dsig:SignedInfo> + <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> + <dsig:Reference URI=""> + <dsig:Transforms> + <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> + <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> + </dsig:Transform> + <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + </dsig:Transforms> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>KEQEPY2O3Z3IRaISSSoRZVPzsHE=</dsig:DigestValue> + </dsig:Reference> + <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>gzGhjH1kdmPcPbgen0xojNIoJLk=</dsig:DigestValue> + </dsig:Reference> + </dsig:SignedInfo> + <dsig:SignatureValue> + 06wqWHgplwpu3N5HMhzb6QC5NkXMO1z4N4oc1L6eDqwZlvFJ9X1XGW//QqviKO9oog3il7IzdfJwnjygR4trgGCIqx+JYCDHJCrG9l8zlxlSW0ZqfsygGXthutcQ1aeUpfO6jYuhnWOUywa8BgzukRtWT+AOJBQZPRYTb8IBmey+uAwlhFLni94eMOd81l+efCvkWi3jRajwsG8ZOaNxSZT3aEV5vj+32Aqtx2MPEVzQWtIA7GqZi+EzcdSdHQvHhg7UB+8kqbU70ENAJbEMTANFZYvLOJ0Om9KfDtPf/+R2TvTc360fNo9RnPl04pHPhCIjcGZhFZorBpUhXFwd2Q== + </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIF3TCCBMWgAwIBAgIDByniMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMB4XDTEwMDcyODExMzY0M1oXDTE1MDcyODExMzY0M1owgbYxCzAJBgNVBAYTAkFUMR4wHAYDVQQKDBVEYXRlbnNjaHV0emtvbW1pc3Npb24xIjAgBgNVBAsMGVN0YW1temFobHJlZ2lzdGVyYmVob2VyZGUxLjAsBgNVBAMMJVNpZ25hdHVyc2VydmljZSBEYXRlbnNjaHV0emtvbW1pc3Npb24xFTATBgNVBAUTDDMyNTkyODMyMzk5ODEcMBoGCSqGSIb3DQEJARYNZHNrQGRzay5ndi5hdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+dBSEBGj2jUXIK1Mp3lVxc/Za+pJMiyKrX3G1ZxgX/ikx7D9scsPYMt473LlAWl9cmCbHbJK+PV2XNNdURLMUCIX+4vUNs2MHeDTQtX8BXjJFpwJYSoaRJQ39FVS/1r5sWcra9Hhdm7w5Gtx/2ukyDX0kdkxawkhP4EQEzi/SI+Fugn+WqgQ1nAdlbxb/dcBw5w1h9b3lmuwUf4z3ooQWUD2DgA/kKd1KejNR43mLUsmvSzevPxT9zs78pOR1OacB7IszTVJPXeOEaaNZHnnB/UeO3g8LEV/3OkXcUgcMkbIIiaBHlll71Pq0COj9kqjXoe7OrRjLY5i3KwOpa6TMCAwEAAaOCAgcwggIDMBMGA1UdIwQMMAqACEkcWDpP6A0DMH8GCCsGAQUFBwEBBHMwcTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMEYGCCsGAQUFBzAChjpodHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMmEuY3J0MFQGA1UdIARNMEswSQYGKigAEQESMD8wPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cuYS10cnVzdC5hdC9kb2NzL2NwL2Etc2lnbi1BbXRzc2lnbmF0dXIwgZ4GA1UdHwSBljCBkzCBkKCBjaCBioaBh2xkYXA6Ly9sZGFwLmEtdHJ1c3QuYXQvb3U9YS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQITAgOnhr0tbowDgYDVR0PAQH/BAQDAgSwMCAGA1UdEQQZMBeBFW1hcmN1cy5oaWxkQGRzay5ndi5hdDAJBgNVHRMEAjAAMA4GByooAAoBBwEEAwEB/zAUBgcqKAAKAQEBBAkMB0JTQi1EU0swDQYJKoZIhvcNAQEFBQADggEBAHTklnvPCH/bJSOlIPbLUEkSGuFHsektSZ8Vr22x/Yv7EzsxoQrJIiz2mQ2gQqFuExdWYxvsowjiSbiis9iUf1c0zscvDS3mIZxGs4M89XHsjHnIyb+Fuwnamw65QrFvM1tNB1ZMjxJ3x+YmHLHdtT3BEBcr3/NCRHd2S0HoBspNz9HVgJaZY1llR7poKBvnAc4g1i+QTvyVb00PtKxR9Lw/9ABInX/1pzpxqrPy7Ib2OP8z6dd3WHmIsCiSHUaj0Dxwwln6fYJjhxZ141SnbovlCLYtrsZLXoi9ljIqX4xO0PwMI2RfNc9cXxTRrRS6rEOvX7PpvgXiDXhp592Yyp4=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo> + <dsig:Object> + <dsig:Manifest Id="manifest"> + <dsig:Reference URI=""> + <dsig:Transforms> + <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> + <dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> + </dsig:Transform> + </dsig:Transforms> + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <dsig:DigestValue>8e7RjLnA4Mgltq5ruIJzheKGxu0=</dsig:DigestValue> + </dsig:Reference> + </dsig:Manifest> + </dsig:Object> + </dsig:Signature> +</saml:Assertion>
\ No newline at end of file diff --git a/id/server/modules/moa-id-modules-saml1/pom.xml b/id/server/modules/moa-id-modules-saml1/pom.xml index 9c43ae277..b5d5a1f8f 100644 --- a/id/server/modules/moa-id-modules-saml1/pom.xml +++ b/id/server/modules/moa-id-modules-saml1/pom.xml @@ -24,7 +24,19 @@ <artifactId>moa-id-lib</artifactId> <scope>test</scope> <type>test-jar</type> - <version>3.0.3-Snapshot</version> + <version>${moa-id-version}</version> + </dependency> + + <dependency> + <groupId>MOA.id.server</groupId> + <artifactId>moa-id-lib</artifactId> + </dependency> + + <!-- Only for development to use SAML1 protocol + SAML1 is removed from official OPB release --> + <dependency> + <groupId>MOA.id.server.modules</groupId> + <artifactId>moa-id-module-eIDAS</artifactId> </dependency> <dependency> diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java index d4e73690f..7f3c353f1 100644 --- a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; @@ -40,6 +41,7 @@ import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.URLEncoder; +import eu.eidas.auth.commons.IPersonalAttributeList; public class GetArtifactAction implements IAction { @@ -71,8 +73,11 @@ public class GetArtifactAction implements IAction { SAML1AuthenticationServer saml1server = SAML1AuthenticationServer.getInstace(); // add other stork attributes to MOA assertion if available - if(null != authData.getStorkAttributes()) { - List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = SAML1AuthenticationServer.addAdditionalSTORKAttributes(authData.getStorkAttributes()); + IPersonalAttributeList storkAttributes = authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); + if(null != storkAttributes) { + List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = SAML1AuthenticationServer.addAdditionalSTORKAttributes(storkAttributes); authData.getExtendedSAMLAttributesOA().addAll(moaExtendedSAMLAttibutes); Logger.info("MOA assertion assembled and SAML Artifact generated."); } diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java index eb869756e..af5dada54 100644 --- a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java @@ -38,9 +38,6 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import eu.stork.peps.auth.commons.IPersonalAttributeList; -import eu.stork.peps.auth.commons.PersonalAttribute; - import at.gv.egovernment.moa.id.auth.AuthenticationServer; import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder; import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; @@ -64,7 +61,6 @@ import at.gv.egovernment.moa.id.config.auth.data.SAML1ConfigurationParameters; import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.storage.AssertionStorage; -//import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; @@ -77,6 +73,11 @@ import at.gv.util.xsd.persondata.IdentificationType.Value; import at.gv.util.xsd.persondata.PersonNameType; import at.gv.util.xsd.persondata.PersonNameType.FamilyName; import at.gv.util.xsd.persondata.PhysicalPersonType; +import eu.eidas.auth.commons.IPersonalAttributeList; +import eu.eidas.auth.commons.PersonalAttribute; +//import eu.stork.peps.auth.commons.IPersonalAttributeList; +//import eu.stork.peps.auth.commons.PersonalAttribute; +//import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; public class SAML1AuthenticationServer extends AuthenticationServer { diff --git a/id/server/modules/module-stork/pom.xml b/id/server/modules/module-stork/pom.xml index b52c10391..2fec7f519 100644 --- a/id/server/modules/module-stork/pom.xml +++ b/id/server/modules/module-stork/pom.xml @@ -61,6 +61,50 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>eu.stork</groupId> + <artifactId>oasis-dss-api</artifactId> + <version>1.0.0-RELEASE</version> + <exclusions> + <exclusion> + <groupId>org.apache.commons</groupId> + <artifactId>commons-io</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- <dependency> + <groupId>eu.stork</groupId> + <artifactId>Commons</artifactId> + <version>1.4.0</version> + </dependency> --> + <dependency> + <groupId>eu.stork</groupId> + <artifactId>SamlEngine</artifactId> + <version>1.5.1</version> + </dependency> + + <dependency> + <groupId>eu.stork</groupId> + <artifactId>DocumentService</artifactId> + <version>0.0.1-SNAPSHOT</version> + <classifier>classes</classifier> + <exclusions> + <exclusion> + <artifactId>axis</artifactId> + <groupId>org.apache.axis</groupId> + </exclusion> + <exclusion> + <artifactId>bcprov-jdk16</artifactId> + <groupId>org.bouncycastle</groupId> + </exclusion> + <exclusion> + <artifactId>jaxws-tools</artifactId> + <groupId>com.sun.xml.ws</groupId> + </exclusion> + </exclusions> + </dependency> + </dependencies> </project> diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java index 41384690e..ecb568635 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java @@ -28,7 +28,11 @@ public class STORKAuthModuleImpl implements AuthModule { @Override
public String selectProcess(ExecutionContext context) {
- return StringUtils.isNotBlank((String) context.get("ccc")) ? "STORKAuthentication" : null;
+ if (StringUtils.isNotBlank((String) context.get("ccc")) ||
+ StringUtils.isNotBlank((String) context.get("CCC")))
+ return "STORKAuthentication";
+ else
+ return null;
}
@Override
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java index 939390847..ee4961d5e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java @@ -21,6 +21,7 @@ import org.apache.commons.io.IOUtils; import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.data.IdentityLink;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.BKUException;
@@ -113,7 +114,9 @@ public abstract class AbstractPepsConnectorWithLocalSigningTask extends Abstract moaSession.setIdentityLink(identityLink);
Logger.debug("Adding addtional STORK attributes to MOA session");
- moaSession.setStorkAttributes(personalAttributeList);
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ personalAttributeList);
// We don't have BKUURL, setting from null to "Not applicable"
moaSession.setBkuURL("Not applicable (STORK Authentication)");
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java index 138776976..c0422e06e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java @@ -26,11 +26,27 @@ import org.opensaml.common.IdentifierGenerator; import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.w3c.dom.DOMException;
-import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
-import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;
+import eu.stork.oasisdss.api.AdditionalProfiles;
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.api.Profiles;
+import eu.stork.oasisdss.api.QualityLevels;
+import eu.stork.oasisdss.api.SignatureTypes;
+import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
+import eu.stork.oasisdss.profile.AnyType;
+import eu.stork.oasisdss.profile.DocumentType;
+import eu.stork.oasisdss.profile.SignRequest;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.PersonalAttributeList;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.auth.engine.core.CitizenCountryCode;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.builder.CreateXMLSignatureRequestBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
@@ -124,7 +140,10 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { AuthenticationSession moasession = BaseAuthenticationServer.getSession(sessionID);
IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
- if (StringUtils.isEmpty(ccc)) {
+ // bugfix: the new task system fails to initialize the CCC - set it here
+ moasession.setCcc((String) executionContext.get(MOAIDAuthConstants.PARAM_CCC));
+
+ if (StringUtils.isEmpty(moasession.getCcc())) {
// illegal state; task should not have been executed without a selected country
throw new AuthenticationException("stork.22", new Object[] { sessionID });
@@ -265,7 +284,7 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { //attributeList.add(newAttribute);
//store SignRequest for later...
- moasession.setSignedDoc(signedDoc);
+ moasession.setGenericDataToSession("STORK_signDoc", signedDoc);
acsURL = issuerValue + AbstractPepsConnectorWithLocalSigningTask.PEPSCONNECTOR_SERVLET_URL_PATTERN;
// TODO[branch]: STORK AuthReq acsURL "/PEPSConnectorWithLocalSigning"
@@ -340,7 +359,9 @@ public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask { Logger.debug("STORK AuthnRequest successfully internally validated.");
//send
- moasession.setStorkAuthnRequest(authnRequest);
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ authnRequest);
// do PEPS-conform logging for easier evaluation
try {
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java index 7b9fa3f12..f872241ae 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java @@ -22,6 +22,7 @@ import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
@@ -142,7 +143,10 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec moaSession.setXMLVerifySignatureResponse(tmp);
executionContext.put("identityLinkAvailable", false);
try {
- IPersonalAttributeList personalAttributeList = moaSession.getAuthnResponseGetPersonalAttributeList();
+ IPersonalAttributeList personalAttributeList =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ IPersonalAttributeList.class);
// Add SignResponse TODO Add signature (extracted from signResponse)?
List<String> values = new ArrayList<String>();
values.add(signResponseString);
@@ -151,7 +155,8 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, "Available");
personalAttributeList.add(signedDocAttribute);
- String authnContextClassRef = moaSession.getAuthnContextClassRef();
+ String authnContextClassRef = moaSession.getGenericDataFromSession(
+ "STORK_authContextClass", String.class);
SZRGInsertion(moaSession, personalAttributeList, authnContextClassRef, citizenSignature);
executionContext.put("identityLinkAvailable", true);
} catch (STORKException e) {
@@ -187,8 +192,9 @@ public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnec }
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
- // authnResponse?
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED);
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java index e84c33d5d..0ac26f45f 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java @@ -2,18 +2,15 @@ package at.gv.egovernment.moa.id.auth.modules.stork.tasks; import iaik.x509.X509Certificate;
-import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
-import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.Template;
@@ -24,6 +21,7 @@ import org.opensaml.saml2.core.StatusCode; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
@@ -207,7 +205,10 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep Logger.debug("MOA session is still valid");
- STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+ STORKAuthnRequest storkAuthnRequest =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ STORKAuthnRequest.class);
if (storkAuthnRequest == null) {
Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
@@ -266,11 +267,15 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep } else {
// store SAMLResponse
- moaSession.setSAMLResponse(request.getParameter("SAMLResponse"));
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
// store authnResponse
// moaSession.setAuthnResponse(authnResponse);//not serializable
- moaSession.setAuthnResponseGetPersonalAttributeList(attributeList);
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ attributeList);
String authnContextClassRef = null;
try {
@@ -280,12 +285,12 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
}
- moaSession.setAuthnContextClassRef(authnContextClassRef);
- moaSession.setReturnURL(request.getRequestURL());
+ moaSession.setGenericDataToSession("STORK_authContextClass", authnContextClassRef);
+ moaSession.setGenericDataToSession("STORK_returnURL", request.getRequestURL());
// load signedDoc
- String signRequest = moaSession.getSignedDoc();
-
+ String signRequest = moaSession.getGenericDataFromSession("STORK_signDoc", String.class);
+
// session is implicit stored in changeSessionID!!!!
String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
@@ -383,9 +388,11 @@ public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPep }
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
- // authnResponse?
-
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
+
+
// session is implicit stored in changeSessionID!!!!
String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java index b505605ab..8322d1a02 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java @@ -2,7 +2,6 @@ package at.gv.egovernment.moa.id.auth.modules.stork.tasks; import iaik.x509.X509Certificate;
-import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
@@ -11,7 +10,6 @@ import java.util.ArrayList; import java.util.Arrays;
import java.util.Date;
import java.util.List;
-import java.util.Properties;
import javax.activation.DataSource;
import javax.servlet.http.HttpServletRequest;
@@ -39,6 +37,7 @@ import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.data.IdentityLink;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
@@ -243,7 +242,10 @@ public class PepsConnectorTask extends AbstractAuthServletTask { Logger.debug("MOA session is still valid");
- STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+ STORKAuthnRequest storkAuthnRequest =
+ moaSession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.STORK_REQUEST,
+ STORKAuthnRequest.class);
if (storkAuthnRequest == null) {
Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
@@ -575,10 +577,15 @@ public class PepsConnectorTask extends AbstractAuthServletTask { moaSession.setIdentityLink(identityLink);
Logger.debug("Adding addtional STORK attributes to MOA session");
- moaSession.setStorkAttributes(attributeList);
-
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST,
+ attributeList);
+
Logger.debug("Add full STORK AuthnResponse to MOA session");
- moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));
+ moaSession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.STORK_RESPONSE,
+ request.getParameter("SAMLResponse"));
+
// We don't have BKUURL, setting from null to "Not applicable"
moaSession.setBkuURL("Not applicable (STORK Authentication)");
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java index 9a0598cf6..fb9172f6e 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/STORKAttributHelper.java @@ -24,8 +24,7 @@ package at.gv.egovernment.moa.id.protocols.builder.attributes; import eu.stork.peps.auth.commons.IPersonalAttributeList; import eu.stork.peps.auth.commons.PersonalAttribute; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; -import at.gv.egovernment.moa.id.auth.stork.STORKConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.UnavailableAttributeException; import at.gv.egovernment.moa.logging.Logger; @@ -43,7 +42,10 @@ public class STORKAttributHelper { throw new UnavailableAttributeException(attributName); } else { - IPersonalAttributeList storkAttributes = authSession.getStorkAttributes(); + IPersonalAttributeList storkAttributes = + authSession.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); if ( storkAttributes == null ) { throw new UnavailableAttributeException(attributName); diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java index 2c7e5b539..f9f38e2d5 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java @@ -23,6 +23,7 @@ package at.gv.egovernment.moa.id.protocols.stork2; import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.data.AuthenticationRole; import at.gv.egovernment.moa.id.data.IAuthData; @@ -30,6 +31,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +import eu.stork.peps.auth.commons.IPersonalAttributeList; import eu.stork.peps.auth.commons.PersonalAttribute; import eu.stork.peps.auth.commons.PersonalAttributeList; import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType; @@ -83,12 +85,17 @@ public class MOAAttributeProvider { public void populateAttribute(PersonalAttributeList attributeList, PersonalAttribute requestedAttribute ) { String storkAttribute = requestedAttribute.getName(); - + + IPersonalAttributeList storkAttributes = + authData.getGenericData( + AuthenticationSessionStorageConstants.STORK_ATTRIBUTELIST, + IPersonalAttributeList.class); + // TODO: check if authData gets populated with stork attributtes during previous steps; it seems it is not - if (null != authData && null != authData.getStorkAttributes() && authData.getStorkAttributes().containsKey(requestedAttribute.getName())) { + if (null != authData && null != storkAttributes && storkAttributes.containsKey(requestedAttribute.getName())) { Logger.debug("Trying to get value for attribute directly from STORK2 response [" + storkAttribute + "]"); try { - PersonalAttribute tmp = authData.getStorkAttributes().get(requestedAttribute.getName()); + PersonalAttribute tmp = storkAttributes.get(requestedAttribute.getName()); attributeList.add((PersonalAttribute) tmp.clone()); } catch(Exception e) { Logger.error("Could not retrieve attribute from STORK2 response: " + storkAttribute); diff --git a/id/server/modules/pom.xml b/id/server/modules/pom.xml index c164252c7..69cd7c217 100644 --- a/id/server/modules/pom.xml +++ b/id/server/modules/pom.xml @@ -25,6 +25,7 @@ <module>moa-id-modules-saml1</module> <module>moa-id-module-openID</module> <module>moa-id-modul-citizencard_authentication</module> + <module>moa-id-module-eIDAS</module> </modules> <dependencies> |