diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_idp')
39 files changed, 2767 insertions, 1319 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml index 69028266..ffda330d 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml @@ -5,10 +5,10 @@ <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_pvp2_idp</artifactId> - <name>eaaf_module_pvp2_core</name> + <name>eaaf_module_pvp2_idp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -32,6 +32,29 @@ <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_module_pvp2_core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> </dependencies> <build> @@ -49,21 +72,20 @@ </plugin> <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - <argLine>--add-modules java.xml.bind</argLine> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> </plugins> </build> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java deleted file mode 100644 index d50c5ee4..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import at.gv.egiz.components.spring.api.SpringResourceProvider; - -public class PVP2SProfileIDPSpringResourceProvider implements SpringResourceProvider { - - @Override - public String getName() { - return "EAAF PVP2 S-Profile IDP SpringResourceProvider"; - } - - @Override - public String[] getPackagesToScan() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Resource[] getResourcesToLoad() { - ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml", PVP2SProfileIDPSpringResourceProvider.class); - - return new Resource[] {sl20AuthConfig}; - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java new file mode 100644 index 00000000..7e572d70 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class Pvp2SProfileIdpSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "EAAF PVP2 S-Profile IDP SpringResourceProvider"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml", + Pvp2SProfileIdpSpringResourceProvider.class); + + return new Resource[] { sl20AuthConfig }; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java index 90662f48..fd04e38f 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java @@ -1,45 +1,39 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.api.builder; import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; public interface ISubjectNameIdGenerator { - /** - * Generates a SAML2 subjectNameId from authentication data - * - * @param authData Authentication data for the current pending request - * @param spConfig Service provider configuration - * @return Pair of subjectNameId and NameIdFormat - * @throws PVP2Exception - */ - public Pair<String, String> generateSubjectNameId(IAuthData authData, ISPConfiguration spConfig) throws PVP2Exception; + /** + * Generates a SAML2 subjectNameId from authentication data. + * + * @param authData Authentication data for the current pending request + * @param spConfig Service provider configuration + * @return Pair of subjectNameId and NameIdFormat + * @throws Pvp2Exception In case of an error + */ + Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig) + throws Pvp2Exception; } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java index 42424726..a7e05664 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java @@ -1,54 +1,46 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class InvalidAssertionConsumerServiceException extends Pvp2Exception { -public class InvalidAssertionConsumerServiceException extends PVP2Exception { + private static final long serialVersionUID = 7861790149343943091L; - public InvalidAssertionConsumerServiceException(int idx) { - super("pvp2.28", new Object[]{idx}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } + public InvalidAssertionConsumerServiceException(final int idx) { + super("pvp2.28", new Object[] { idx }); + this.statusCodeValue = StatusCode.REQUESTER; + } - /** - * - */ - public InvalidAssertionConsumerServiceException(String wrongURL) { - super("pvp2.23", new Object[]{wrongURL}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - - } + /** + * Invalid assertion consumer-service URL. + * + * @param wrongUrl invalid URL + */ + public InvalidAssertionConsumerServiceException(final String wrongUrl) { + super("pvp2.23", new Object[] { wrongUrl }); + this.statusCodeValue = StatusCode.REQUESTER; - /** - * - */ - private static final long serialVersionUID = 7861790149343943091L; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java index 55c94df1..89179ff6 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java @@ -1,42 +1,35 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import org.opensaml.saml.saml2.core.StatusCode; -public class InvalidAssertionEncryptionException extends PVP2Exception { +public class InvalidAssertionEncryptionException extends Pvp2Exception { - private static final long serialVersionUID = 6513388841485355549L; + private static final long serialVersionUID = 6513388841485355549L; - public InvalidAssertionEncryptionException() { - super("pvp2.16", new Object[]{}); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } + public InvalidAssertionEncryptionException() { + super("pvp2.16", new Object[] {}); + this.statusCodeValue = StatusCode.RESPONDER; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java index 6109c78d..cf4ac8d1 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java @@ -1,45 +1,35 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import org.opensaml.saml.saml2.core.StatusCode; -public class RequestDeniedException extends PVP2Exception { +public class RequestDeniedException extends Pvp2Exception { - public RequestDeniedException() { - super("pvp2.14", null); - this.statusCodeValue = StatusCode.REQUEST_DENIED_URI; - } + private static final long serialVersionUID = 4415896615794730553L; - /** - * - */ - private static final long serialVersionUID = 4415896615794730553L; + public RequestDeniedException() { + super("pvp2.14", null); + this.statusCodeValue = StatusCode.REQUEST_DENIED; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java index 7f565c00..e6cdf8f1 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java @@ -1,50 +1,40 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class ResponderErrorException extends Pvp2Exception { -public class ResponderErrorException extends PVP2Exception { + private static final long serialVersionUID = -425416760138285446L; - /** - * - */ - private static final long serialVersionUID = -425416760138285446L; + public ResponderErrorException(final String messageId, final Object[] parameters, + final Throwable wrapped) { + super(messageId, parameters, wrapped); + this.statusCodeValue = StatusCode.RESPONDER; + } - public ResponderErrorException(String messageId, Object[] parameters, - Throwable wrapped) { - super(messageId, parameters, wrapped); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } - - public ResponderErrorException(String messageId, Object[] parameters) { - super(messageId, parameters); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } + public ResponderErrorException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + this.statusCodeValue = StatusCode.RESPONDER; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java deleted file mode 100644 index a0fad363..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; - -public class SAMLRequestNotSignedException extends PVP2Exception { - - public SAMLRequestNotSignedException() { - super("pvp2.07", null); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - public SAMLRequestNotSignedException(Throwable e) { - super("pvp2.07", null, e); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java deleted file mode 100644 index e59ebe0a..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; - - -public class SAMLRequestNotSupported extends PVP2Exception { - - public SAMLRequestNotSupported() { - super("pvp2.09", null); - this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED_URI; - } - - /** - * - */ - private static final long serialVersionUID = 1244883178458802767L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java new file mode 100644 index 00000000..add2103b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.exception; + +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class SamlRequestNotSignedException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; + + public SamlRequestNotSignedException() { + super("pvp2.07", null); + this.statusCodeValue = StatusCode.REQUESTER; + } + + public SamlRequestNotSignedException(final Throwable e) { + super("pvp2.07", null, e); + this.statusCodeValue = StatusCode.REQUESTER; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java new file mode 100644 index 00000000..d672f457 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.exception; + +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class SamlRequestNotSupported extends Pvp2Exception { + + private static final long serialVersionUID = 1244883178458802767L; + + public SamlRequestNotSupported() { + super("pvp2.09", null); + this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java index 0dfda55f..3a56b414 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java @@ -1,43 +1,34 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class UnprovideableAttributeException extends Pvp2Exception { -public class UnprovideableAttributeException extends PVP2Exception { - /** - * - */ - private static final long serialVersionUID = 3972197758163647157L; + private static final long serialVersionUID = 3972197758163647157L; - public UnprovideableAttributeException(String attributeName) { - super("pvp2.10", new Object[] {attributeName}); - this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE_URI; - } + public UnprovideableAttributeException(final String attributeName) { + super("pvp2.10", new Object[] { attributeName }); + this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java new file mode 100644 index 00000000..597d3c22 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java @@ -0,0 +1,549 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl; + +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.ws.security.SecurityPolicyException; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.SignableXMLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.IModulInfo; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.SLOException; +import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController; +import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPVPRequestException; +import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException; +import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EAAFURICompare; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SAMLVerificationEngine; + +public abstract class AbstractPVP2XProtocol extends AbstractController implements IModulInfo { + private static final Logger log = LoggerFactory.getLogger(AbstractPVP2XProtocol.class); + + @Autowired(required=true) protected IPVP2BasicConfiguration pvpBasicConfiguration; + @Autowired(required=true) protected IPVPMetadataProvider metadataProvider; + @Autowired(required=true) protected SAMLVerificationEngine samlVerificationEngine; + @Autowired(required=false) protected List<IAuthnRequestPostProcessor> authRequestPostProcessors; + + private AbstractCredentialProvider pvpIDPCredentials; + + + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * @param pvpIDPCredentials credential provider + */ + public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { + this.pvpIDPCredentials = pvpIDPCredentials; + + } + + public boolean generateErrorMessage(Throwable e, + HttpServletRequest request, HttpServletResponse response, + IRequest protocolRequest) throws Throwable { + + if(protocolRequest == null) { + throw e; + } + + if(!(protocolRequest instanceof PVPSProfilePendingRequest) ) { + throw e; + } + PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest)protocolRequest; + + Response samlResponse = + SAML2Utils.createSAMLObject(Response.class); + Status status = SAML2Utils.createSAMLObject(Status.class); + StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); + StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); + + String moaError = null; + + if(e instanceof NoPassivAuthenticationException) { + statusCode.setValue(StatusCode.NO_PASSIVE_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + + } else if (e instanceof NameIDFormatNotSupportedException) { + statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + + } else if (e instanceof SLOException) { + //SLOExecpetions only occurs if session information is lost + return false; + + } else if(e instanceof PVP2Exception) { + PVP2Exception ex = (PVP2Exception) e; + statusCode.setValue(ex.getStatusCodeValue()); + String statusMessageValue = ex.getStatusMessageValue(); + if(statusMessageValue != null) { + statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue)); + } + moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId()); + + } else { + statusCode.setValue(StatusCode.RESPONDER_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + moaError = statusMessager.getResponseErrorCode(e); + } + + + if (StringUtils.isNotEmpty(moaError)) { + StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class); + moaStatusCode.setValue(moaError); + statusCode.setStatusCode(moaStatusCode); + } + + status.setStatusCode(statusCode); + if(statusMessage.getMessage() != null) { + status.setStatusMessage(statusMessage); + } + samlResponse.setStatus(status); + String remoteSessionID = SAML2Utils.getSecureIdentifier(); + samlResponse.setID(remoteSessionID); + + samlResponse.setIssueInstant(new DateTime()); + Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); + nissuer.setValue(pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL())); + nissuer.setFormat(NameID.ENTITY); + samlResponse.setIssuer(nissuer); + + IEncoder encoder = null; + + if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class); + + } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class); + + } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) { + encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class); + } + + if(encoder == null) { + // default to redirect binding + encoder = new RedirectBinding(); + } + + String relayState = null; + if (pvpRequest.getRequest() != null) + relayState = pvpRequest.getRequest().getRelayState(); + + X509Credential signCred = pvpIDPCredentials.getIDPAssertionSigningCredential(); + + encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), + relayState, signCred, protocolRequest); + return true; + } + + public boolean validate(HttpServletRequest request, + HttpServletResponse response, IRequest pending) { + + return true; + } + + protected void pvpMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + //create pendingRequest object + PVPSProfilePendingRequest pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class); + metadataAction.processRequest(pendingReq, + req, resp, null); + + } + + protected void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + PVPSProfilePendingRequest pendingReq = null; + + try { + //create pendingRequest object + pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new PostBinding().decode( + req, resp, metadataProvider, false, + new EAAFURICompare(pvpBasicConfiguration.getIDPSSOPostService(pendingReq.getAuthURL()))); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); + + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (EAAFException e) { + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw e; + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e); + } + } + + protected void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + PVPSProfilePendingRequest pendingReq = null; + try { + //create pendingRequest object + pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new RedirectBinding().decode( + req, resp, metadataProvider, false, + new EAAFURICompare(pvpBasicConfiguration.getIDPSSORedirectService(pendingReq.getAuthURL()))); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); + + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (EAAFException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.info("Receive INVALID protocol request: " + samlRequest); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw e; + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e); + } + } + + + + /** + * + * + * @param request + * @param response + * @param msg + * @return true if preprocess can handle this request type, otherwise false + * @throws Throwable + */ + abstract protected boolean childPreProcess(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable; + + protected void preProcess(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable { + + InboundMessage msg = pendingReq.getRequest(); + + if (StringUtils.isEmpty(msg.getEntityID())) { + throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); + + } + + if(!msg.isVerified()) { + samlVerificationEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + msg.setVerified(true); + + } + + revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE, getAuthProtocolIdentifier()); + + if (msg instanceof PVPSProfileRequest && + ((PVPSProfileRequest)msg).getSamlRequest() instanceof AuthnRequest) + preProcessAuthRequest(request, response, pendingReq); + + else if (childPreProcess(request, response, pendingReq)) + log.debug("Find protocol handler in child implementation"); + + else { + log.error("Receive unsupported PVP21 message of type: " + ((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()); + throw new InvalidPVPRequestException("pvp2.09", + new Object[] {((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()}); + } + + + + //switch to session authentication + protAuthService.performAuthentication(request, response, pendingReq); + } + + + /** + * PreProcess Authn request + * @param request + * @param response + * @param pendingReq + * @throws Throwable + */ + private void preProcessAuthRequest(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable { + + PVPSProfileRequest moaRequest = ((PVPSProfileRequest)pendingReq.getRequest()); + SignableXMLObject samlReq = moaRequest.getSamlRequest(); + + if(!(samlReq instanceof AuthnRequest)) { + throw new InvalidPVPRequestException("Unsupported request", new Object[] {}); + } + + EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider); + if(metadata == null) { + throw new NoMetadataInformationException(); + } + SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + + AuthnRequest authnRequest = (AuthnRequest)samlReq; + + if (authnRequest.getIssueInstant() == null) { + log.warn("Unsupported request: No IssueInstant Attribute found."); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Unsupported request: No IssueInstant Attribute found"}, + pendingReq); + + } + + if (authnRequest.getIssueInstant().minusMinutes(EAAFConstants.ALLOWED_TIME_JITTER).isAfterNow()) { + log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore."); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."}, + pendingReq); + + } + + //parse AssertionConsumerService + AssertionConsumerService consumerService = null; + if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) && + StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) { + //use AssertionConsumerServiceURL from request + + //check requested AssertionConsumingService URL against metadata + List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices(); + for (AssertionConsumerService service : metadataAssertionServiceList) { + if (authnRequest.getProtocolBinding().equals(service.getBinding()) + && authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) { + consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); + consumerService.setBinding(authnRequest.getProtocolBinding()); + consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL()); + log.debug("Requested AssertionConsumerServiceURL is valid."); + } + } + + if (consumerService == null) { + throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL()); + + } + + + } else { + //use AssertionConsumerServiceIndex and select consumerService from metadata + Integer aIdx = authnRequest.getAssertionConsumerServiceIndex(); + int assertionidx = 0; + + if(aIdx != null) { + assertionidx = aIdx.intValue(); + + } else { + assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor); + + } + consumerService = spSSODescriptor.getAssertionConsumerServices().get(assertionidx); + + if (consumerService == null) { + throw new InvalidAssertionConsumerServiceException(aIdx); + + } + } + + + //validate AuthnRequest + AuthnRequest authReq = (AuthnRequest) samlReq; + String oaURL = moaRequest.getEntityMetadata(metadataProvider).getEntityID(); + log.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding()); + + pendingReq.setSPEntityId(StringEscapeUtils.escapeHtml(oaURL)); + pendingReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(pendingReq.getSPEntityId())); + pendingReq.setBinding(consumerService.getBinding()); + pendingReq.setRequest(moaRequest); + pendingReq.setConsumerURL(consumerService.getLocation()); + + //parse AuthRequest + pendingReq.setPassiv(authReq.isPassive()); + pendingReq.setForce(authReq.isForceAuthn()); + + //AuthnRequest needs authentication + pendingReq.setNeedAuthentication(true); + + //set protocol action, which should be executed after authentication + pendingReq.setAction(AuthenticationAction.class.getName()); + + // do post-processing if required + log.trace("Starting extended AuthnRequest validation and processing ... "); + if (authRequestPostProcessors != null) { + for (final IAuthnRequestPostProcessor processor : authRequestPostProcessors) { + log.trace("Post-process AuthnRequest with module: {}", processor.getClass().getSimpleName()); + processor.process(request, pendingReq, authReq, spSSODescriptor); + + } + } + + log.debug("Extended AuthnRequest validation and processing finished"); + + //write revisionslog entry + revisionsLogger.logEvent(pendingReq, PVPEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST, authReq.getID()); + + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIDPCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java index cbbed659..f9d7767f 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl; import javax.annotation.PostConstruct; @@ -31,14 +24,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.joda.time.DateTime; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,137 +40,139 @@ import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IAction; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.impl.data.SLOInformationImpl; -import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl; +import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.BindingNotSupportedException; import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; -import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; @Service("PVPAuthenticationRequestAction") public class AuthenticationAction implements IAction { - private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class); - - private static final String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "protocols.pvp2.assertion.encryption.active"; - - @Autowired(required=true) private IPVPMetadataProvider metadataProvider; - @Autowired(required=true) ApplicationContext springContext; - @Autowired(required=true) IConfiguration authConfig; - @Autowired(required=true) PVP2AssertionBuilder assertionBuilder; - @Autowired(required=true) IPVP2BasicConfiguration pvpBasicConfiguration; - @Autowired(required=true) IRevisionLogger revisionsLogger; - - private AbstractCredentialProvider pvpIDPCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * @param pvpIDPCredentials credential provider - */ - public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { - this.pvpIDPCredentials = pvpIDPCredentials; - - } - - @Override - public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp, IAuthData authData) throws ResponderErrorException { - final PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest) req; - try { - //get basic information - final PVPSProfileRequest moaRequest = (PVPSProfileRequest) pvpRequest.getRequest(); - final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); - final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider); - - final AssertionConsumerService consumerService = - SAML2Utils.createSAMLObject(AssertionConsumerService.class); - consumerService.setBinding(pvpRequest.getBinding()); - consumerService.setLocation(pvpRequest.getConsumerURL()); - - final DateTime date = new DateTime(); - final SLOInformationImpl sloInformation = new SLOInformationImpl(); - final String issuerEntityID = pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL()); - - //build Assertion - final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest, authnRequest, authData, - peerEntity, date, consumerService, sloInformation); - - final Response authResponse = AuthResponseBuilder.buildResponse( - metadataProvider, issuerEntityID, authnRequest, - date, assertion, authConfig.getBasicConfigurationBoolean( - CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)); - - IEncoder binding = null; - - if (consumerService.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); - - } else if (consumerService.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); - - } - - if (binding == null) { - throw new BindingNotSupportedException(consumerService.getBinding()); - } - - binding.encodeRespone(httpReq, httpResp, authResponse, - consumerService.getLocation(), moaRequest.getRelayState(), - pvpIDPCredentials.getIDPAssertionSigningCredential(), req); - - revisionsLogger.logEvent(req, 3105, authResponse.getID()); - - //set protocol type - sloInformation.setProtocolType(req.requestedModule()); - sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier()); - return sloInformation; - - } catch (MessageEncodingException | SecurityException e) { - log.warn("Message Encoding exception", e); - throw new ResponderErrorException("pvp2.01", null, e); - - } catch (final EAAFException e) { - log.info("Response generation error: Msg: ", e.getMessage()); - throw new ResponderErrorException(e.getErrorId(), e.getParams(), e); - - } catch (final Exception e) { - log.warn("Response generation error", e); - throw new ResponderErrorException("pvp2.01", null, e); - - } - - } - - @Override - public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp) { - return true; - } - - @Override - public String getDefaultActionName() { - return "PVPAuthenticationRequestAction"; - - } - - @PostConstruct - private void verifyInitialization() { - if (pvpIDPCredentials == null) { - log.error("No SAML2 credentialProvider injected!"); - throw new RuntimeException("No SAML2 credentialProvider injected!"); - - } - } + private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class); + + @Autowired(required = true) + private IPvp2MetadataProvider metadataProvider; + @Autowired(required = true) + ApplicationContext springContext; + @Autowired(required = true) + IConfiguration authConfig; + @Autowired(required = true) + Pvp2AssertionBuilder assertionBuilder; + @Autowired(required = true) + IPvp2BasicConfiguration pvpBasicConfiguration; + @Autowired(required = true) + IRevisionLogger revisionsLogger; + + private IPvp2CredentialProvider pvpIdpCredentials; + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * + * @param pvpIdpCredentials credential provider + */ + public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) { + this.pvpIdpCredentials = pvpIdpCredentials; + + } + + @Override + public SloInformationInterface processRequest(final IRequest req, + final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IAuthData authData) throws ResponderErrorException { + final PvpSProfilePendingRequest pvpRequest = (PvpSProfilePendingRequest) req; + try { + // get basic information + final PvpSProfileRequest moaRequest = (PvpSProfileRequest) pvpRequest.getRequest(); + final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); + final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider); + + final AssertionConsumerService consumerService = + Saml2Utils.createSamlObject(AssertionConsumerService.class); + consumerService.setBinding(pvpRequest.getBinding()); + consumerService.setLocation(pvpRequest.getConsumerUrl()); + + final DateTime date = new DateTime(); + final SloInformationImpl sloInformation = new SloInformationImpl(); + final String issuerEntityID = pvpBasicConfiguration.getIdpEntityId(pvpRequest.getAuthUrl()); + + // build Assertion + final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest, + authnRequest, authData, peerEntity, date, consumerService, sloInformation); + + final Response authResponse = AuthResponseBuilder.buildResponse(metadataProvider, + issuerEntityID, authnRequest, date, assertion, + authConfig); + + IEncoder binding = null; + + if (consumerService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); + + } else if (consumerService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = springContext.getBean("PvpPostBinding", PostBinding.class); + + } + + if (binding == null) { + throw new BindingNotSupportedException(consumerService.getBinding()); + } + + binding.encodeResponse(httpReq, httpResp, authResponse, consumerService.getLocation(), + moaRequest.getRelayState(), pvpIdpCredentials.getMessageSigningCredential(), req); + + revisionsLogger.logEvent(req, 3105, authResponse.getID()); + + // set protocol type + sloInformation.setProtocolType(req.requestedModule()); + sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier()); + return sloInformation; + + } catch (final SecurityException e) { + log.warn("Message Encoding exception", e); + throw new ResponderErrorException("pvp2.01", null, e); + + } catch (final EaafException e) { + log.info("Response generation error: Msg: ", e.getMessage()); + throw new ResponderErrorException(e.getErrorId(), e.getParams(), e); + + } catch (final Exception e) { + log.warn("Response generation error", e); + throw new ResponderErrorException("pvp2.01", null, e); + + } + + } + + @Override + public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) { + return true; + } + + @Override + public String getDefaultActionName() { + return "PVPAuthenticationRequestAction"; + + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIdpCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java index 6b957522..0b344ba3 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java @@ -1,123 +1,120 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.IAction; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.modules.pvp2.PvpEventConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.idp.IAction; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; -import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - @Service("pvpMetadataService") public class MetadataAction implements IAction { - private static final Logger log = LoggerFactory.getLogger(MetadataAction.class); - - @Autowired private IRevisionLogger revisionsLogger; - @Autowired private PVPMetadataBuilder metadatabuilder; - @Autowired private IPVPMetadataConfigurationFactory configFactory; - - private AbstractCredentialProvider pvpIDPCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * @param pvpIDPCredentials credential provider - */ - public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { - this.pvpIDPCredentials = pvpIDPCredentials; - - } - - public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp, IAuthData authData) throws PVP2MetadataException { - try { - revisionsLogger.logEvent(req, PVPEventConstants.AUTHPROTOCOL_PVP_METADATA); - - //build metadata - IPVPMetadataBuilderConfiguration metadataConfig = - configFactory.generateMetadataBuilderConfiguration( - req.getAuthURLWithOutSlash(), - pvpIDPCredentials); - - ; - - String metadataXML = metadatabuilder.buildPVPMetadata(metadataConfig); - log.debug("METADATA: " + metadataXML); - - byte[] content = metadataXML.getBytes("UTF-8"); - httpResp.setStatus(HttpServletResponse.SC_OK); - httpResp.setContentLength(content.length); - httpResp.setContentType(MediaType.APPLICATION_XML_VALUE); - httpResp.getOutputStream().write(content); - return null; - - } catch (Exception e) { - log.error("Failed to generate metadata", e); - throw new PVP2MetadataException("pvp2.27", null); - } - } - - 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 "IDP - PVP Metadata action"; - } - - @PostConstruct - private void verifyInitialization() { - if (pvpIDPCredentials == null) { - log.error("No SAML2 credentialProvider injected!"); - throw new RuntimeException("No SAML2 credentialProvider injected!"); - - } - } - + private static final Logger log = LoggerFactory.getLogger(MetadataAction.class); + + @Autowired + private IRevisionLogger revisionsLogger; + @Autowired + private PvpMetadataBuilder metadatabuilder; + @Autowired + private IPvpMetadataConfigurationFactory configFactory; + + private IPvp2CredentialProvider pvpIdpCredentials; + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * + * @param pvpIdpCredentials credential provider + */ + public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) { + this.pvpIdpCredentials = pvpIdpCredentials; + + } + + @Override + public SloInformationInterface processRequest(final IRequest req, + final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IAuthData authData) throws Pvp2MetadataException { + try { + revisionsLogger.logEvent(req, PvpEventConstants.AUTHPROTOCOL_PVP_METADATA); + + // build metadata + final IPvpMetadataBuilderConfiguration metadataConfig = configFactory + .generateMetadataBuilderConfiguration(req.getAuthUrlWithOutSlash(), pvpIdpCredentials); + + final String metadataXml = metadatabuilder.buildPvpMetadata(metadataConfig); + log.trace("METADATA: " + metadataXml); + + final byte[] content = metadataXml.getBytes("UTF-8"); + httpResp.setStatus(HttpServletResponse.SC_OK); + httpResp.setContentLength(content.length); + httpResp.setContentType(MediaType.APPLICATION_XML_VALUE); + httpResp.getOutputStream().write(content); + return null; + + } catch (final Exception e) { + log.error("Failed to generate metadata", e); + throw new Pvp2MetadataException("pvp2.27", null); + } + } + + @Override + public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) { + return false; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + @Override + public String getDefaultActionName() { + return "IDP - PVP Metadata action"; + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIdpCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java deleted file mode 100644 index 7f086ff6..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.impl; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; - -@Component("PVPSProfilePendingRequest") -@Scope(value = BeanDefinition.SCOPE_PROTOTYPE) -public class PVPSProfilePendingRequest extends RequestImpl { - private static final long serialVersionUID = 4889919265919638188L; - - InboundMessage request; - String binding; - String consumerURL; - - public InboundMessage getRequest() { - return request; - } - - public void setRequest(InboundMessage request) { - this.request = request; - } - - public String getBinding() { - return binding; - } - - public void setBinding(String binding) { - this.binding = binding; - } - - public String getConsumerURL() { - return consumerURL; - } - - public void setConsumerURL(String consumerURL) { - this.consumerURL = consumerURL; - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java new file mode 100644 index 00000000..26e04881 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl; + +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component("PVPSProfilePendingRequest") +@Scope(value = BeanDefinition.SCOPE_PROTOTYPE) +public class PvpSProfilePendingRequest extends RequestImpl { + private static final long serialVersionUID = 4889919265919638188L; + + InboundMessage request; + String binding; + String consumerUrl; + + public InboundMessage getRequest() { + return request; + } + + public void setRequest(final InboundMessage request) { + this.request = request; + } + + public String getBinding() { + return binding; + } + + public void setBinding(final String binding) { + this.binding = binding; + } + + public String getConsumerUrl() { + return consumerUrl; + } + + public void setConsumerUrl(final String consumerUrl) { + this.consumerUrl = consumerUrl; + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java index 07423c19..482a2a09 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java @@ -1,153 +1,215 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; import java.util.ArrayList; import java.util.List; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + import org.joda.time.DateTime; -import org.opensaml.Configuration; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.EncryptedAssertion; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.encryption.Encrypter; -import org.opensaml.saml2.encryption.Encrypter.KeyPlacement; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.MetadataCredentialResolver; -import org.opensaml.security.MetadataCriteria; -import org.opensaml.xml.encryption.EncryptionException; -import org.opensaml.xml.encryption.EncryptionParameters; -import org.opensaml.xml.encryption.KeyEncryptionParameters; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory; -import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.encryption.Encrypter; +import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.X509Credential; +import org.opensaml.xmlsec.SecurityConfigurationSupport; +import org.opensaml.xmlsec.encryption.support.DataEncryptionParameters; +import org.opensaml.xmlsec.encryption.support.EncryptionException; +import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory; +import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; /** + * Authentication response builder. + * * @author tlenz * */ public class AuthResponseBuilder { - private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class); - - public static Response buildResponse(MetadataProvider metadataProvider, String issuerEntityID, RequestAbstractType req, DateTime date, Assertion assertion, boolean enableEncryption) throws InvalidAssertionEncryptionException { - Response authResponse = SAML2Utils.createSAMLObject(Response.class); - - Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); - - nissuer.setValue(issuerEntityID); - nissuer.setFormat(NameID.ENTITY); - authResponse.setIssuer(nissuer); - authResponse.setInResponseTo(req.getID()); - - //set responseID - String remoteSessionID = SAML2Utils.getSecureIdentifier(); - authResponse.setID(remoteSessionID); - - - //SAML2 response required IssueInstant - authResponse.setIssueInstant(date); - - authResponse.setStatus(SAML2Utils.getSuccessStatus()); - - //check, if metadata includes an encryption key - MetadataCredentialResolver mdCredResolver = - new MetadataCredentialResolver(metadataProvider); - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add( new EntityIDCriteria(req.getIssuer().getValue()) ); - criteriaSet.add( new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) ); - criteriaSet.add( new UsageCriteria(UsageType.ENCRYPTION) ); - - X509Credential encryptionCredentials = null; - try { - encryptionCredentials = (X509Credential) mdCredResolver.resolveSingle(criteriaSet); - - } catch (SecurityException e2) { - log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); - throw new InvalidAssertionEncryptionException(); - - } - - if (encryptionCredentials != null && enableEncryption) { - //encrypt SAML2 assertion - - try { - - EncryptionParameters dataEncParams = new EncryptionParameters(); - dataEncParams.setAlgorithm(PVPConstants.DEFAULT_SYM_ENCRYPTION_METHODE); - - List<KeyEncryptionParameters> keyEncParamList = new ArrayList<KeyEncryptionParameters>(); - KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); - - keyEncParam.setEncryptionCredential(encryptionCredentials); - keyEncParam.setAlgorithm(PVPConstants.DEFAULT_ASYM_ENCRYPTION_METHODE); - KeyInfoGeneratorFactory kigf = Configuration.getGlobalSecurityConfiguration() - .getKeyInfoGeneratorManager().getDefaultManager() - .getFactory(encryptionCredentials); - keyEncParam.setKeyInfoGenerator(kigf.newInstance()); - keyEncParamList.add(keyEncParam); - - Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); - //samlEncrypter.setKeyPlacement(KeyPlacement.INLINE); - samlEncrypter.setKeyPlacement(KeyPlacement.PEER); - - EncryptedAssertion encryptAssertion = null; - - encryptAssertion = samlEncrypter.encrypt(assertion); - - authResponse.getEncryptedAssertions().add(encryptAssertion); - - } catch (EncryptionException e1) { - log.warn("Can not encrypt the PVP2 assertion", e1); - throw new InvalidAssertionEncryptionException(); - - } - - } else { - authResponse.getAssertions().add(assertion); - - } - - return authResponse; - } + private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class); + + /** + * Build PVP2 S-Profile authentication response. + * + * @param metadataProvider Service-Provider metadata + * @param issuerEntityID IDP entityId + * @param req current pending request + * @param date Timestamp + * @param assertion PVP2 S-Profil Assertion + * @param authConfig {@link IConfiguration} + * @return PVP2 S-Profile authentication response + * @throws InvalidAssertionEncryptionException In case of an error + */ + public static Response buildResponse(final IPvp2MetadataProvider metadataProvider, + final String issuerEntityID, final RequestAbstractType req, final DateTime date, + final Assertion assertion, IConfiguration authConfig) + throws InvalidAssertionEncryptionException { + final Response authResponse = Saml2Utils.createSamlObject(Response.class); + + final Issuer nissuer = Saml2Utils.createSamlObject(Issuer.class); + + nissuer.setValue(issuerEntityID); + nissuer.setFormat(NameIDType.ENTITY); + authResponse.setIssuer(nissuer); + authResponse.setInResponseTo(req.getID()); + + // set responseID + final String remoteSessionID = Saml2Utils.getSecureIdentifier(); + authResponse.setID(remoteSessionID); + + // SAML2 response required IssueInstant + authResponse.setIssueInstant(date); + + authResponse.setStatus(Saml2Utils.getSuccessStatus()); + + // check, if metadata includes an encryption key + final X509Credential encryptionCredentials = resolveEncryptionCredential(req, metadataProvider); + + if (encryptionCredentials != null + && authConfig.getBasicConfigurationBoolean( + PvpConstants.CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)) { + authResponse.getEncryptedAssertions().add( + doEncryption(assertion, encryptionCredentials, authConfig)); + + } else { + authResponse.getAssertions().add(assertion); + + } + + return authResponse; + } + + private static EncryptedAssertion doEncryption(Assertion assertion, + X509Credential encryptionCredentials, IConfiguration authConfig) + throws InvalidAssertionEncryptionException { + try { + final String keyEncAlg = Saml2Utils.getKeyOperationAlgorithmFromCredential( + encryptionCredentials, + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA), + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + final DataEncryptionParameters dataEncParams = new DataEncryptionParameters(); + dataEncParams.setAlgorithm(authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_DATA, PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE)); + + final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); + final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); + keyEncParam.setEncryptionCredential(encryptionCredentials); + keyEncParam.setAlgorithm(keyEncAlg); + + final KeyInfoGeneratorFactory kigf = + SecurityConfigurationSupport.getGlobalEncryptionConfiguration() + .getKeyTransportKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); + keyEncParam.setKeyInfoGenerator(kigf.newInstance()); + keyEncParamList.add(keyEncParam); + + final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); + samlEncrypter.setKeyPlacement(KeyPlacement.PEER); + + final Element assertionElement = XMLObjectProviderRegistrySupport.getMarshallerFactory() + .getMarshaller(assertion).marshall(assertion); + assertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); + + return samlEncrypter.encrypt((Assertion) + XMLObjectSupport.getUnmarshaller(assertionElement).unmarshall(assertionElement)); + + } catch (final EncryptionException | SamlSigningException | MarshallingException | UnmarshallingException e1) { + log.warn("Can not encrypt the PVP2 assertion", e1); + throw new InvalidAssertionEncryptionException(); + + } + + } + + private static X509Credential resolveEncryptionCredential(RequestAbstractType req, + IPvp2MetadataProvider metadataProvider) throws InvalidAssertionEncryptionException { + try { + final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( + metadataProvider); + roleDescriptorResolver.setRequireValidMetadata(true); + roleDescriptorResolver.initialize(); + + final MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver(); + mdCredResolver.setRoleDescriptorResolver(roleDescriptorResolver); + mdCredResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); + mdCredResolver.initialize(); + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); + + return (X509Credential) mdCredResolver.resolveSingle(criteriaSet); + + } catch (final SecurityException | ComponentInitializationException | ResolverException e2) { + log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); + throw new InvalidAssertionEncryptionException(); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java deleted file mode 100644 index 2ccc2c9e..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java +++ /dev/null @@ -1,459 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; - -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeQuery; -import org.opensaml.saml2.core.AttributeStatement; -import org.opensaml.saml2.core.Audience; -import org.opensaml.saml2.core.AudienceRestriction; -import org.opensaml.saml2.core.AuthnContext; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.Conditions; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.core.impl.AuthnRequestImpl; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.AttributeConsumingService; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.NameIDFormat; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.QAANotSupportedException; -import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException; -import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QAALevelVerifier; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; - -@Service("PVP2AssertionBuilder") -public class PVP2AssertionBuilder implements PVPConstants { - - private static final Logger log = LoggerFactory.getLogger(PVP2AssertionBuilder.class); - @Autowired private ILoALevelMapper loaLevelMapper; - @Autowired private ISubjectNameIdGenerator subjectNameIdGenerator; - - - /** - * Build a PVP assertion as response for a SAML2 AttributeQuery request - * - * @param issuerEntityID EnitiyID, which should be used for this IDP response - * @param attrQuery AttributeQuery request from Service-Provider - * @param attrList List of PVP response attributes - * @param now Current time - * @param validTo ValidTo time of the assertion - * @param qaaLevel QAA level of the authentication - * @param sessionIndex SAML2 SessionIndex, which should be included * - * @return PVP 2.1 Assertion - * @throws PVP2Exception - */ - public Assertion buildAssertion(String issuerEntityID, AttributeQuery attrQuery, - List<Attribute> attrList, DateTime now, DateTime validTo, String qaaLevel, String sessionIndex) throws PVP2Exception { - - AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - authnContextClassRef.setAuthnContextClassRef(qaaLevel); - - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat()); - subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue()); - - SubjectConfirmationData subjectConfirmationData = null; - - return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now, - authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, - validTo); - } - - - /** - * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest - * - * @param issuerEntityID EnitiyID, which should be used for this IDP response - * @param pendingReq Current processed pendingRequest DAO - * @param authnRequest Current processed PVP AuthnRequest - * @param authData AuthenticationData of the user, which is already authenticated - * @param peerEntity SAML2 EntityDescriptor of the service-provider, which receives the response - * @param date TimeStamp - * @param assertionConsumerService SAML2 endpoint of the service-provider, which should be used - * @param sloInformation Single LogOut information DAO - * @return - * @throws PVP2Exception - */ - public Assertion buildAssertion(String issuerEntityID, PVPSProfilePendingRequest pendingReq, AuthnRequest authnRequest, - IAuthData authData, EntityDescriptor peerEntity, DateTime date, - AssertionConsumerService assertionConsumerService, SLOInformationInterface sloInformation) - throws PVP2Exception { - - ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - //check if authn. request contains LoA - RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext(); - if (reqAuthnContext == null) { - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } else { - //authn. request requests LoA levels. To LoA validation - List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs(); - - //get matching mode from authn. request - String loaMatchingMode = EAAFConstants.EIDAS_LOA_MATCHING_MINIMUM; - if (reqAuthnContext.getComparison() != null && - StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString())) - loaMatchingMode = reqAuthnContext.getComparison().toString(); - - //get requested LoAs - if (reqAuthnContextClassRefIt.size() == 0) { - QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(), - oaParam.getRequiredLoA(), loaMatchingMode); - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } else { - List<String> eIDASLoaFromRequest = new ArrayList<String>(); - for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { - String qaa_uri = authnClassRef.getAuthnContextClassRef(); - - if (!qaa_uri.trim().startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) { - if (loaLevelMapper != null) { - log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... " ); - eIDASLoaFromRequest.add(loaLevelMapper.mapToeIDASLoA(qaa_uri.trim())); - - } else - log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore " - + "'" + qaa_uri.trim() + "'"); - } else - eIDASLoaFromRequest.add(qaa_uri.trim()); - - } - - //stop process if no supported LoA scheme is requested - if (eIDASLoaFromRequest.isEmpty()) { - log.info("Authn. request contains no supported LoA level. Stop authentication process ... "); - throw new QAANotSupportedException("No supported LoA in Authn. request"); - - } - - //verifiy LoAs from request to authentication LoA - QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(), eIDASLoaFromRequest , loaMatchingMode); - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } - } - - - //load SPSS decriptor from service-provider metadata - SPSSODescriptor spSSODescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); - - //add Attributes to Assertion - List<Attribute> attrList = new ArrayList<Attribute>(); - if (spSSODescriptor.getAttributeConsumingServices() != null && - spSSODescriptor.getAttributeConsumingServices().size() > 0) { - - Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); - int idx = 0; - - AttributeConsumingService attributeConsumingService = null; - if (aIdx != null) { - idx = aIdx.intValue(); - attributeConsumingService = spSSODescriptor - .getAttributeConsumingServices().get(idx); - - } else { - List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices(); - for (AttributeConsumingService el : attrConsumingServiceList) { - if (el.isDefault()) - attributeConsumingService = el; - } - } - - /* - * TODO: maybe use first AttributeConsumingService if no is selected - * in request or on service is marked as default - * - */ - if (attributeConsumingService == null ) { - List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices(); - if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty()) - attributeConsumingService = attrConsumingServiceList.get(0); - - } - - - if (attributeConsumingService != null) { - Iterator<RequestedAttribute> it = attributeConsumingService - .getRequestAttributes().iterator(); - while (it.hasNext()) { - RequestedAttribute reqAttribut = it.next(); - try { - Attribute attr = PVPAttributeBuilder.buildAttribute( - reqAttribut.getName(), oaParam, authData); - if (attr == null) { - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - } else { - attrList.add(attr); - } - - } catch (UnavailableAttributeException e) { - log.info( - "Attribute generation for " - + reqAttribut.getFriendlyName() + " not possible."); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - - } catch (PVP2Exception e) { - log.info( - "Attribute generation failed! for " - + reqAttribut.getFriendlyName()); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - } catch (Exception e) { - log.warn( - "General Attribute generation failed! for " - + reqAttribut.getFriendlyName(), e); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - } - } - } - } - - //generate subjectNameId - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - Pair<String, String> subjectNameIdPair = subjectNameIdGenerator.generateSubjectNameId(authData, oaParam); - subjectNameID.setValue(subjectNameIdPair.getFirst()); - subjectNameID.setNameQualifier(subjectNameIdPair.getSecond()); - - //get NameIDFormat from request - String nameIDFormat = NameID.TRANSIENT; - AuthnRequest authnReq = (AuthnRequestImpl) authnRequest; - if (authnReq.getNameIDPolicy() != null && - StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) { - nameIDFormat = authnReq.getNameIDPolicy().getFormat(); - - } else { - //get NameIDFormat from metadata - List<NameIDFormat> metadataNameIDFormats = spSSODescriptor.getNameIDFormats(); - - if (metadataNameIDFormats != null) { - - for (NameIDFormat el : metadataNameIDFormats) { - if (NameID.PERSISTENT.equals(el.getFormat())) { - nameIDFormat = NameID.PERSISTENT; - break; - - } else if (NameID.TRANSIENT.equals(el.getFormat()) || - NameID.UNSPECIFIED.equals(el.getFormat())) - break; - - } - } - } - - if (NameID.TRANSIENT.equals(nameIDFormat) || NameID.UNSPECIFIED.equals(nameIDFormat)) { - String random = Random.nextHexRandom32(); - String nameID = subjectNameID.getValue(); - - try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1")); - subjectNameID.setValue(Base64Utils.encodeToString(hash)); - subjectNameID.setNameQualifier(null); - subjectNameID.setFormat(NameID.TRANSIENT); - - } catch (Exception e) { - log.warn("PVP2 subjectNameID error", e); - throw new ResponderErrorException("internal.03", null, e); - - } - - } else - subjectNameID.setFormat(nameIDFormat); - - - String sessionIndex = null; - - //if request is a reauthentication and NameIDFormat match reuse old session information - if (StringUtils.isNotEmpty(authData.getNameID()) && - StringUtils.isNotEmpty(authData.getNameIDFormat()) && - nameIDFormat.equals(authData.getNameIDFormat())) { - subjectNameID.setValue(authData.getNameID()); - sessionIndex = authData.getSessionIndex(); - - } - - // - if (StringUtils.isEmpty(sessionIndex)) - sessionIndex = SAML2Utils.getSecureIdentifier(); - - SubjectConfirmationData subjectConfirmationData = SAML2Utils - .createSAMLObject(SubjectConfirmationData.class); - subjectConfirmationData.setInResponseTo(authnRequest.getID()); - subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime())); - - //set 'recipient' attribute in subjectConformationData - subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); - - //set IP address of the user machine as 'Address' attribute in subjectConformationData - String usersIPAddress = pendingReq.getRawData( - RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class); - if (StringUtils.isNotEmpty(usersIPAddress)) - subjectConfirmationData.setAddress(usersIPAddress); - - //set SLO information - sloInformation.setUserNameIdentifier(subjectNameID.getValue()); - sloInformation.setNameIDFormat(subjectNameID.getFormat()); - sloInformation.setSessionIndex(sessionIndex); - - return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); - } - - /** - * - * @param issuer IDP EntityID - * @param entityID Service Provider EntityID - * @param date - * @param authnContextClassRef - * @param attrList - * @param subjectNameID - * @param subjectConfirmationData - * @param sessionIndex - * @param isValidTo - * @return - * @throws ConfigurationException - */ - - public Assertion buildGenericAssertion(String issuer, String entityID, DateTime date, - AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, - NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, - String sessionIndex, DateTime isValidTo) throws ResponderErrorException { - Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class); - - AuthnContext authnContext = SAML2Utils - .createSAMLObject(AuthnContext.class); - authnContext.setAuthnContextClassRef(authnContextClassRef); - - AuthnStatement authnStatement = SAML2Utils - .createSAMLObject(AuthnStatement.class); - - authnStatement.setAuthnInstant(date); - authnStatement.setSessionIndex(sessionIndex); - authnStatement.setAuthnContext(authnContext); - - assertion.getAuthnStatements().add(authnStatement); - - AttributeStatement attributeStatement = SAML2Utils - .createSAMLObject(AttributeStatement.class); - attributeStatement.getAttributes().addAll(attrList); - if (attributeStatement.getAttributes().size() > 0) { - assertion.getAttributeStatements().add(attributeStatement); - } - - Subject subject = SAML2Utils.createSAMLObject(Subject.class); - subject.setNameID(subjectNameID); - - SubjectConfirmation subjectConfirmation = SAML2Utils - .createSAMLObject(SubjectConfirmation.class); - subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); - subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); - - subject.getSubjectConfirmations().add(subjectConfirmation); - - Conditions conditions = SAML2Utils.createSAMLObject(Conditions.class); - AudienceRestriction audienceRestriction = SAML2Utils - .createSAMLObject(AudienceRestriction.class); - Audience audience = SAML2Utils.createSAMLObject(Audience.class); - - audience.setAudienceURI(entityID); - audienceRestriction.getAudiences().add(audience); - conditions.setNotBefore(date); - conditions.setNotOnOrAfter(isValidTo); - - conditions.getAudienceRestrictions().add(audienceRestriction); - - assertion.setConditions(conditions); - - Issuer issuerObj = SAML2Utils.createSAMLObject(Issuer.class); - - if (issuer.endsWith("/")) - issuer = issuer.substring(0, issuer.length()-1); - issuerObj.setValue(issuer); - issuerObj.setFormat(NameID.ENTITY); - - assertion.setIssuer(issuerObj); - assertion.setSubject(subject); - assertion.setID(SAML2Utils.getSecureIdentifier()); - assertion.setIssueInstant(date); - - return assertion; - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java new file mode 100644 index 00000000..b7b18f0f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java @@ -0,0 +1,469 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; + +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.naming.ConfigurationException; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotSupportedException; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QaaLevelVerifier; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeQuery; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.Audience; +import org.opensaml.saml.saml2.core.AudienceRestriction; +import org.opensaml.saml.saml2.core.AuthnContext; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.AuthnStatement; +import org.opensaml.saml.saml2.core.Conditions; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameID; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.Subject; +import org.opensaml.saml.saml2.core.SubjectConfirmation; +import org.opensaml.saml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.NameIDFormat; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Base64Utils; + +@Service("PVP2AssertionBuilder") +public class Pvp2AssertionBuilder implements PvpConstants { + + private static final Logger log = LoggerFactory.getLogger(Pvp2AssertionBuilder.class); + @Autowired + private ILoALevelMapper loaLevelMapper; + @Autowired + private ISubjectNameIdGenerator subjectNameIdGenerator; + + /** + * Build a PVP assertion as response for a SAML2 AttributeQuery request. + * + * @param issuerEntityID EnitiyID, which should be used for this IDP response + * @param attrQuery AttributeQuery request from Service-Provider + * @param attrList List of PVP response attributes + * @param now Current time + * @param validTo ValidTo time of the assertion + * @param qaaLevel QAA level of the authentication + * @param sessionIndex SAML2 SessionIndex, which should be included * + * @return PVP 2.1 Assertion + * @throws Pvp2Exception In case of an error + */ + public Assertion buildAssertion(final String issuerEntityID, final AttributeQuery attrQuery, + final List<Attribute> attrList, final DateTime now, final DateTime validTo, + final String qaaLevel, final String sessionIndex) throws Pvp2Exception { + + final AuthnContextClassRef authnContextClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + authnContextClassRef.setAuthnContextClassRef(qaaLevel); + + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat()); + subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue()); + + final SubjectConfirmationData subjectConfirmationData = null; + + return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now, + authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, + validTo); + } + + /** + * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest. + * + * @param issuerEntityID EnitiyID, which should be used for this IDP + * response + * @param pendingReq Current processed pendingRequest DAO + * @param authnRequest Current processed PVP AuthnRequest + * @param authData AuthenticationData of the user, which is + * already authenticated + * @param peerEntity SAML2 EntityDescriptor of the + * service-provider, which receives the response + * @param date TimeStamp + * @param assertionConsumerService SAML2 endpoint of the service-provider, which + * should be used + * @param sloInformation Single LogOut information DAO + * @return PVP2 S-Profil Assertion + * @throws Pvp2Exception In case of an error + */ + public Assertion buildAssertion(final String issuerEntityID, + final PvpSProfilePendingRequest pendingReq, final AuthnRequest authnRequest, + final IAuthData authData, final EntityDescriptor peerEntity, final DateTime date, + final AssertionConsumerService assertionConsumerService, + final SloInformationInterface sloInformation) throws Pvp2Exception { + + final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + final AuthnContextClassRef authnContextClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + + // check if authn. request contains LoA + final RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext(); + if (reqAuthnContext == null) { + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } else { + // authn. request requests LoA levels. To LoA validation + final List<AuthnContextClassRef> reqAuthnContextClassRefIt = + reqAuthnContext.getAuthnContextClassRefs(); + + // get matching mode from authn. request + String loaMatchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + if (reqAuthnContext.getComparison() != null + && StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString())) { + loaMatchingMode = reqAuthnContext.getComparison().toString(); + } + + // get requested LoAs + if (reqAuthnContextClassRefIt.size() == 0) { + QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), oaParam.getRequiredLoA(), + loaMatchingMode); + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } else { + final List<String> eidasLoaFromRequest = new ArrayList<>(); + for (final AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { + final String qaa_uri = authnClassRef.getAuthnContextClassRef(); + + if (!qaa_uri.trim().startsWith(EaafConstants.EIDAS_LOA_PREFIX)) { + if (loaLevelMapper != null) { + log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... "); + eidasLoaFromRequest.add(loaLevelMapper.mapToEidasLoa(qaa_uri.trim())); + + } else { + log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore " + "'" + + qaa_uri.trim() + "'"); + } + } else { + eidasLoaFromRequest.add(qaa_uri.trim()); + } + + } + + // stop process if no supported LoA scheme is requested + if (eidasLoaFromRequest.isEmpty()) { + log.info( + "Authn. request contains no supported LoA level. Stop authentication process ... "); + throw new QaaNotSupportedException("No supported LoA in Authn. request"); + + } + + // verifiy LoAs from request to authentication LoA + QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), eidasLoaFromRequest, + loaMatchingMode); + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } + } + + // load SPSS decriptor from service-provider metadata + final SPSSODescriptor spSsoDescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + + // add Attributes to Assertion + final List<Attribute> attrList = new ArrayList<>(); + if (spSsoDescriptor.getAttributeConsumingServices() != null + && spSsoDescriptor.getAttributeConsumingServices().size() > 0) { + + final Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); + int idx = 0; + + AttributeConsumingService attributeConsumingService = null; + if (aIdx != null) { + idx = aIdx; + attributeConsumingService = spSsoDescriptor.getAttributeConsumingServices().get(idx); + + } else { + final List<AttributeConsumingService> attrConsumingServiceList = + spSsoDescriptor.getAttributeConsumingServices(); + for (final AttributeConsumingService el : attrConsumingServiceList) { + if (el.isDefault()) { + attributeConsumingService = el; + } + } + } + + /* + * TODO: maybe use first AttributeConsumingService if no is selected in request + * or on service is marked as default + * + */ + if (attributeConsumingService == null) { + final List<AttributeConsumingService> attrConsumingServiceList = + spSsoDescriptor.getAttributeConsumingServices(); + if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty()) { + attributeConsumingService = attrConsumingServiceList.get(0); + } + + } + + if (attributeConsumingService != null) { + final Iterator<RequestedAttribute> it = + attributeConsumingService.getRequestAttributes().iterator(); + while (it.hasNext()) { + final RequestedAttribute reqAttribut = it.next(); + try { + final Attribute attr = + PvpAttributeBuilder.buildAttribute(reqAttribut.getName(), oaParam, authData); + if (attr == null) { + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + } else { + attrList.add(attr); + } + + } catch (final UnavailableAttributeException e) { + log.info( + "Attribute generation for " + reqAttribut.getFriendlyName() + " not possible."); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } catch (final Pvp2Exception e) { + log.info("Attribute generation failed! for " + reqAttribut.getFriendlyName()); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } catch (final Exception e) { + log.warn("General Attribute generation failed! for " + reqAttribut.getFriendlyName(), + e); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } + } + } + } + + // generate subjectNameId + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + final Pair<String, String> subjectNameIdPair = + subjectNameIdGenerator.generateSubjectNameId(authData, oaParam); + subjectNameID.setValue(subjectNameIdPair.getFirst()); + subjectNameID.setNameQualifier(subjectNameIdPair.getSecond()); + + // get NameIDFormat from request + String nameIdFormat = NameIDType.TRANSIENT; + final AuthnRequest authnReq = authnRequest; + if (authnReq.getNameIDPolicy() != null + && StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) { + nameIdFormat = authnReq.getNameIDPolicy().getFormat(); + + } else { + // get NameIDFormat from metadata + final List<NameIDFormat> metadataNameIdFormats = spSsoDescriptor.getNameIDFormats(); + + if (metadataNameIdFormats != null) { + + for (final NameIDFormat el : metadataNameIdFormats) { + if (NameIDType.PERSISTENT.equals(el.getFormat())) { + nameIdFormat = NameIDType.PERSISTENT; + break; + + } else if (NameIDType.TRANSIENT.equals(el.getFormat()) + || NameIDType.UNSPECIFIED.equals(el.getFormat())) { + break; + } + + } + } + } + + if (NameIDType.TRANSIENT.equals(nameIdFormat) || NameIDType.UNSPECIFIED.equals(nameIdFormat)) { + final String random = Random.nextHexRandom32(); + final String nameID = subjectNameID.getValue(); + + try { + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + final byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1")); + subjectNameID.setValue(Base64Utils.encodeToString(hash)); + subjectNameID.setNameQualifier(null); + subjectNameID.setFormat(NameIDType.TRANSIENT); + + } catch (final Exception e) { + log.warn("PVP2 subjectNameID error", e); + throw new ResponderErrorException("internal.03", null, e); + + } + + } else { + subjectNameID.setFormat(nameIdFormat); + } + + String sessionIndex = null; + + // if request is a reauthentication and NameIDFormat match reuse old session + // information + if (StringUtils.isNotEmpty(authData.getNameID()) + && StringUtils.isNotEmpty(authData.getNameIdFormat()) + && nameIdFormat.equals(authData.getNameIdFormat())) { + subjectNameID.setValue(authData.getNameID()); + sessionIndex = authData.getSessionIndex(); + + } + + // + if (StringUtils.isEmpty(sessionIndex)) { + sessionIndex = Saml2Utils.getSecureIdentifier(); + } + + final SubjectConfirmationData subjectConfirmationData = + Saml2Utils.createSamlObject(SubjectConfirmationData.class); + subjectConfirmationData.setInResponseTo(authnRequest.getID()); + subjectConfirmationData + .setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime())); + + // set 'recipient' attribute in subjectConformationData + subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); + + // set IP address of the user machine as 'Address' attribute in + // subjectConformationData + final String usersIpAddress = + pendingReq.getRawData(RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class); + if (StringUtils.isNotEmpty(usersIpAddress)) { + subjectConfirmationData.setAddress(usersIpAddress); + } + + // set SLO information + sloInformation.setUserNameIdentifier(subjectNameID.getValue()); + sloInformation.setNameIdFormat(subjectNameID.getFormat()); + sloInformation.setSessionIndex(sessionIndex); + + return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date, + authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, + subjectConfirmationData.getNotOnOrAfter()); + } + + /** + * Build generic part of PVP S-Profile Assertion. + * + * @param issuer IDP EntityID + * @param entityID Service Provider EntityID + * @param date Timestamp + * @param authnContextClassRef SAML2 AuthnContextClassReference + * @param attrList List of attributes + * @param subjectNameID SubjectNameId + * @param subjectConfirmationData SubjectConfirmationInformation + * @param sessionIndex SessionIndex + * @param isValidTo ValidTo Timestamp + * @return PVP S-Profile Assertion + * @throws ConfigurationException In case on an error + */ + + public Assertion buildGenericAssertion(String issuer, final String entityID, final DateTime date, + final AuthnContextClassRef authnContextClassRef, final List<Attribute> attrList, + final NameID subjectNameID, final SubjectConfirmationData subjectConfirmationData, + final String sessionIndex, final DateTime isValidTo) throws ResponderErrorException { + final Assertion assertion = Saml2Utils.createSamlObject(Assertion.class); + + final AuthnContext authnContext = Saml2Utils.createSamlObject(AuthnContext.class); + authnContext.setAuthnContextClassRef(authnContextClassRef); + + final AuthnStatement authnStatement = Saml2Utils.createSamlObject(AuthnStatement.class); + + authnStatement.setAuthnInstant(date); + authnStatement.setSessionIndex(sessionIndex); + authnStatement.setAuthnContext(authnContext); + + assertion.getAuthnStatements().add(authnStatement); + + final AttributeStatement attributeStatement = + Saml2Utils.createSamlObject(AttributeStatement.class); + attributeStatement.getAttributes().addAll(attrList); + if (attributeStatement.getAttributes().size() > 0) { + assertion.getAttributeStatements().add(attributeStatement); + } + + final Subject subject = Saml2Utils.createSamlObject(Subject.class); + subject.setNameID(subjectNameID); + + final SubjectConfirmation subjectConfirmation = + Saml2Utils.createSamlObject(SubjectConfirmation.class); + subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); + subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); + + subject.getSubjectConfirmations().add(subjectConfirmation); + + final Conditions conditions = Saml2Utils.createSamlObject(Conditions.class); + final AudienceRestriction audienceRestriction = + Saml2Utils.createSamlObject(AudienceRestriction.class); + final Audience audience = Saml2Utils.createSamlObject(Audience.class); + + audience.setAudienceURI(entityID); + audienceRestriction.getAudiences().add(audience); + conditions.setNotBefore(date); + conditions.setNotOnOrAfter(isValidTo); + + conditions.getAudienceRestrictions().add(audienceRestriction); + + assertion.setConditions(conditions); + + final Issuer issuerObj = Saml2Utils.createSamlObject(Issuer.class); + + if (issuer.endsWith("/")) { + issuer = issuer.substring(0, issuer.length() - 1); + } + issuerObj.setValue(issuer); + issuerObj.setFormat(NameIDType.ENTITY); + + assertion.setIssuer(issuerObj); + assertion.setSubject(subject); + assertion.setID(Saml2Utils.getSecureIdentifier()); + assertion.setIssueInstant(date); + + return assertion; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider index cda12a62..c3c68e20 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -1 +1 @@ -at.gv.egiz.eaaf.modules.pvp2.idp.PVP2SProfileIDPSpringResourceProvider
\ No newline at end of file +at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml index b01a09ff..d29b5aba 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml @@ -1,22 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- - --> - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xmlns:tx="http://www.springframework.org/schema/tx" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - - <bean id="PVP2AssertionBuilder" - class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder" /> - - <bean id="PVPSProfilePendingRequest" - class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest" - scope="prototype"/> - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="PVP2AssertionBuilder" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder" /> + + <bean id="PVPSProfilePendingRequest" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest" + scope="prototype" /> + </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java new file mode 100644 index 00000000..a88fa869 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java @@ -0,0 +1,226 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.util.Date; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class AuthenticationActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private AuthenticationAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private PvpSProfilePendingRequest pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new PvpSProfilePendingRequest(); + + } + + @Test + public void checkNeedAuthFlag() { + Assert.assertTrue("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } + + @Test + public void noAuthnRequestInPendingRequest() { + + IAuthData authData = generateAuthData(); + + try { + action.processRequest(pendingReq, httpReq, httpResp, authData); + Assert.fail("No SAML requst not detected"); + + } catch (ResponderErrorException e) { + Assert.assertEquals("Wrong errorCode", "pvp2.01", e.getErrorId()); + } + + } + + private IAuthData generateAuthData() { + return new IAuthData() { + + @Override + public boolean isSsoSession() { + return false; + } + + @Override + public boolean isForeigner() { + return false; + } + + @Override + public boolean isBaseIdTransferRestrication() { + return true; + } + + @Override + public Date getSsoSessionValidTo() { + return null; + + } + + @Override + public String getSessionIndex() { + return null; + + } + + @Override + public String getNameIdFormat() { + return null; + + } + + @Override + public String getNameID() { + return null; + + } + + @Override + public IIdentityLink getIdentityLink() { + return null; + + } + + @Override + public String getIdentificationValue() { + return null; + + } + + @Override + public String getIdentificationType() { + return null; + + } + + @Override + public String getGivenName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public <T> T getGenericData(String key, Class<T> clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getFormatedDateOfBirth() { + return DateFormatUtils.format(getDateOfBirth(), "yyyy-MM-dd"); + } + + @Override + public String getFamilyName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getEncryptedSourceIdType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEncryptedSourceId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEidasQaaLevel() { + return EaafConstants.EIDAS_LOA_LOW; + } + + @Override + public Date getDateOfBirth() { + return new Date(); + + } + + @Override + public String getCiticenCountryCode() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBpkType() { + return EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2); + } + + @Override + public String getBpk() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssuer() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssueInstantString() { + return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(getAuthenticationIssueInstant()); + } + + @Override + public Date getAuthenticationIssueInstant() { + return new Date(); + } + }; + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java new file mode 100644 index 00000000..b2e528c4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java @@ -0,0 +1,156 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.binding.PostBindingTest; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class AuthnResponseBuilderTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + @Test + public void encryptedAssertion() throws InvalidAssertionEncryptionException, Pvp2MetadataException, + XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException { + final String issuerEntityID = RandomStringUtils.randomAlphabetic(15); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10)); + + final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml")); + + //build response + final DateTime now = DateTime.now(); + final Response response = AuthResponseBuilder.buildResponse( + metadataProvider, issuerEntityID, authnReq, + now, assertion, authConfig); + + + //validate + Assert.assertNotNull("SAML2 response is null", response); + Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty()); + Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions()); + Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty()); + Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size()); + + Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo()); + Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue()); + Assert.assertNotNull("ResponseId is null", response.getID()); + Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty()); + + final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response); + final String xmlResp = DomUtils.serializeNode(responseElement); + Assert.assertNotNull("XML response is null", xmlResp); + Assert.assertFalse("XML response is empty", xmlResp.isEmpty()); + + } + + @Test + public void encryptedAssertionWithDecryption() throws InvalidAssertionEncryptionException, Pvp2MetadataException, + XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException, + SamlAssertionValidationExeption, CredentialsNotAvailableException { + final String issuerEntityID = RandomStringUtils.randomAlphabetic(15); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10)); + + final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml")); + + //build response + final DateTime now = DateTime.now(); + final Response response = AuthResponseBuilder.buildResponse( + metadataProvider, issuerEntityID, authnReq, + now, assertion, authConfig); + + + //validate + Assert.assertNotNull("SAML2 response is null", response); + Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty()); + Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions()); + Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty()); + Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size()); + + Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo()); + Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue()); + Assert.assertNotNull("ResponseId is null", response.getID()); + Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty()); + + final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response); + final String xmlResp = DomUtils.serializeNode(responseElement); + Assert.assertNotNull("XML response is null", xmlResp); + Assert.assertFalse("XML response is empty", xmlResp.isEmpty()); + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + "https://demo.egiz.gv.at/demoportal_demologin/", "jUnitTest", false); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java new file mode 100644 index 00000000..8436a43d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java @@ -0,0 +1,67 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class MetadataActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; + @Autowired private MetadataAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private TestRequestImpl pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void checkNeedAuthFlag() { + Assert.assertFalse("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java new file mode 100644 index 00000000..f9aafea9 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileIdpSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileIdpSpringResourceProvider test = + new Pvp2SProfileIdpSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileIdpSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java new file mode 100644 index 00000000..004df86d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java @@ -0,0 +1,25 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; + +public class DummyLoALevelMapper implements ILoALevelMapper { + + @Override + public String mapToEidasLoa(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapToSecClass(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapEidasQaaToStorkQaa(String eidasqaaLevel) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java new file mode 100644 index 00000000..c5fc0f13 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java @@ -0,0 +1,52 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; + +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; +import org.springframework.beans.factory.annotation.Autowired; + +public class DummyPvpConfiguration implements IPvp2BasicConfiguration { + + @Autowired private IConfiguration basicConfig; + + @Override + public String getIdpEntityId(String authUrl) throws EaafException { + return authUrl + "/idp"; + } + + @Override + public String getIdpSsoPostService(String authUrl) throws EaafException { + return authUrl + "/sso/post"; + } + + @Override + public String getIdpSsoRedirectService(String authUrl) throws EaafException { + return authUrl + "/sso/redirect"; + } + + @Override + public String getIdpSsoSoapService(String authUrl) throws EaafException { + return authUrl + "/sso/soap"; + } + + @Override + public List<ContactPerson> getIdpContacts() throws EaafException { + return null; + } + + @Override + public Organization getIdpOrganisation() throws EaafException { + return null; + } + + @Override + public IConfiguration getBasicConfiguration() { + return basicConfig; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java new file mode 100644 index 00000000..3f24480b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataBuilderTest; + +public class DummyPvpMetadataConfigFactory implements IPvpMetadataConfigurationFactory { + + @Override + public IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, + IPvp2CredentialProvider pvpIdpCredentials) { + return MetadataBuilderTest.idpMetadataConfig(pvpIdpCredentials, false, true); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java new file mode 100644 index 00000000..3eaa4c09 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java @@ -0,0 +1,18 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; + +public class DummySubjectNameGenerator implements ISubjectNameIdGenerator { + + @Override + public Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig) + throws Pvp2Exception { + return Pair.newInstance(authData.getBpk(), authData.getBpkType()); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props new file mode 100644 index 00000000..164b8807 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=meta +key.metadata.pass=password +key.sig.alias=sig +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props new file mode 100644 index 00000000..60cecebb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=shibboleth-sign +key.metadata.pass=password +key.sig.alias=shibboleth-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml new file mode 100644 index 00000000..7c45b5fa --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml new file mode 100644 index 00000000..ef35ea92 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks Binary files differnew file mode 100644 index 00000000..b5262cb8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml new file mode 100644 index 00000000..7fdbef90 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2045-02-05T06:41:42.966Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml new file mode 100644 index 00000000..99552053 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="dummyAuthConfig" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" /> + + <bean id="dummyVelocityGuiBuilder" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" /> + + <bean id="dummyGuiBuilderConfigFactory" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" /> + + <bean id="httpClientFactory" + class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" /> + + <bean id="dummyRevisionLogger" + class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> + + <bean id="eaafKeyStoreFactory" + class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml new file mode 100644 index 00000000..2bddd629 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <import resource="test_eaaf_core.beans.xml"/> + <import resource="classpath:/eaaf_pvp.beans.xml"/> + <import resource="classpath:/eaaf_pvp_idp.beans.xml"/> + + <bean id="dummyCredentialProvider" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + + <bean id="dummyChainingMetadataResolver" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider" /> + + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine" /> + + <bean id="dummyLoALevelMapper" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyLoALevelMapper" /> + + <bean id="dummySubjectNameIdGenerator" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummySubjectNameGenerator" /> + + <bean id="dummyPvpBasicConfig" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpConfiguration" /> + + <bean id="dummyMetadataConfigFactor" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpMetadataConfigFactory" /> + + <bean id="PVPAuthenticationRequestAction" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction"> + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> + + <bean id="pvpMetadataService" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction" > + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> + +</beans>
\ No newline at end of file |