diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_sp')
17 files changed, 1139 insertions, 968 deletions
| diff --git a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml index d2157a45..69eb26ab 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml @@ -5,7 +5,7 @@    <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_sp</artifactId>    <name>eaaf_module_pvp2_sp</name> @@ -32,11 +32,23 @@  		<scope>provided</scope>  	</dependency> +    <!-- Only for testing -->      <dependency>        <groupId>junit</groupId>        <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>    </dependencies>    <build> @@ -54,21 +66,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_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java new file mode 100644 index 00000000..7535e013 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.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.sp; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class Pvp2SProfileSpSpringResourceProvider implements SpringResourceProvider { + +  @Override +  public String getName() { +    return "EAAF PVP2 S-Profile Service-Provider SpringResourceProvider"; +  } + +  @Override +  public String[] getPackagesToScan() { +    // TODO Auto-generated method stub +    return null; +  } + +  @Override +  public Resource[] getResourcesToLoad() { +    final ClassPathResource sl20AuthConfig = +        new ClassPathResource("/eaaf_pvp_sp.beans.xml", Pvp2SProfileSpSpringResourceProvider.class); + +    return new Resource[] { sl20AuthConfig }; +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java deleted file mode 100644 index b8a8e796..00000000 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java +++ /dev/null @@ -1,195 +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.sp.api; - -import java.util.List; - -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.xml.security.credential.Credential; -import org.w3c.dom.Element; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -/** - * @author tlenz - * - */ -public interface IPVPAuthnRequestBuilderConfiguruation { - -	/** -	 * Defines a unique name for this PVP Service-provider, which is used for logging -	 *  -	 * @return -	 */ -	public String getSPNameForLogging(); -	 -	/** -	 * If true, the SAML2 isPassive flag is set in the AuthnRequest -	 *  -	 * @return -	 */ -	public Boolean isPassivRequest(); - -	/** -	 * Define the ID of the AssertionConsumerService,  -	 * which defines the required attributes in service-provider metadata. -	 *  -	 * @return -	 */ -	public Integer getAssertionConsumerServiceId(); - -	/** -	 * Define the SAML2 EntityID of the service provider. -	 *  -	 * @return -	 */ -	public String getSPEntityID(); - -	/** -	 * Define the SAML2 NameIDPolicy -	 *  -	 * @return Service-Provider EntityID, but never null -	 */ -	public String getNameIDPolicyFormat(); - -	/** -	 * Define the AuthnContextClassRefernece of this request -	 *  -	 * Example:  -	 * 			http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3  -	 * 			http://www.stork.gov.eu/1.0/citizenQAALevel/4 -	 *           -	 *  -	 * @return -	 */ -	public String getAuthnContextClassRef(); - -	/** -	 * Define the AuthnContextComparison model, which should be used -	 *  -	 * @return -	 */ -	public AuthnContextComparisonTypeEnumeration getAuthnContextComparison(); -	 -	 -	/** -	 * Define the credential, which should be used to sign the AuthnRequest -	 *  -	 * @return -	 */ -	public Credential getAuthnRequestSigningCredential(); -	 -	 -	/** -	 * Define the SAML2 EntityDescriptor of the IDP, which should receive the AuthnRequest -	 *  -	 * @return Credential, but never null. -	 */ -	public EntityDescriptor getIDPEntityDescriptor(); - -	/** -	 * Set the SAML2 NameIDPolicy allow-creation flag -	 *  -	 * @return EntityDescriptor, but never null. -	 */ -	public boolean getNameIDPolicyAllowCreation(); - -	 -	/** -	 * Set the requested SubjectNameID -	 *  -	 * @return SubjectNameID, or null if no SubjectNameID should be used -	 */ -	public String getSubjectNameID(); - -	/** -	 * Define the qualifier of the <code>SubjectNameID</code> -	 * <br><br> -	 * Like: 'urn:publicid:gv.at:cdid+BF' -	 *  -	 * @return qualifier, or null if no qualifier should be set -	 */ -	public String getSubjectNameIDQualifier(); -	 -	/** -	 * Define the format of the subjectNameID, which is included in authn-request -	 *  -	 *  -	 * @return nameIDFormat, of SAML2 'transient' if nothing is defined -	 */ -	public String getSubjectNameIDFormat(); - -	/** -	 * Define a SP specific SAML2 requestID -	 *  -	 * @return requestID, or null if the requestID should be generated automatically -	 */ -	public String getRequestID(); - -	/** -	 * Defines the 'method' attribute in 'SubjectConformation' element  -	 *  -	 * @return method, or null if no method should set -	 */ -	public String getSubjectConformationMethode(); - -	/** -	 * Define the information, which should be added as 'subjectConformationDate'  -	 * in 'SubjectConformation' element  -	 *  -	 * @return subjectConformation information or null if no subjectConformation should be set -	 */ -	public Element getSubjectConformationDate(); - -	 -	/** -	 * Get the EntityId of the SP in case of a SAML2 proxy use-case  -	 *  -	 * @return -	 */ -	public String getScopeRequesterId(); -	 -	 -	/** -	 * Get a FriendlyName for the SP that sends the request -	 *  -	 * @return -	 */ -	public String getProviderName(); -	 -	 -	/** -	 * Get a Set of SAML2 attributes that are requested by using SAML2 requested attributes -	 * <br> -	 * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for requested attributes -	 *  -	 * @return -	 */ -	public List<EAAFRequestedAttribute> getRequestedAttributes(); -	 -} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java new file mode 100644 index 00000000..597507f3 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java @@ -0,0 +1,188 @@ +/* + * 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.sp.api; + +import java.util.List; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; + +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.w3c.dom.Element; + +/** + * Configuration of a PVP2 S-Profile authentication-request builder. + * + * @author tlenz + * + */ +public interface IPvpAuthnRequestBuilderConfiguruation { + +  /** +   * Defines a unique name for this PVP Service-provider, which is used for +   * logging. +   * +   * @return +   */ +  String getSpNameForLogging(); + +  /** +   * If true, the SAML2 isPassive flag is set in the AuthnRequest. +   * +   * @return +   */ +  Boolean isPassivRequest(); + +  /** +   * Define the ID of the AssertionConsumerService, which defines the required +   * attributes in service-provider metadata. +   * +   * @return +   */ +  Integer getAssertionConsumerServiceId(); + +  /** +   * Define the SAML2 EntityID of the service provider. +   * +   * @return +   */ +  String getSpEntityID(); + +  /** +   * Define the SAML2 NameIDPolicy. +   * +   * @return Service-Provider EntityID, but never null +   */ +  String getNameIdPolicyFormat(); + +  /** +   * Define the AuthnContextClassRefernece of this request. +   * +   * <p> +   * Example: http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3 +   * http://www.stork.gov.eu/1.0/citizenQAALevel/4 +   * </p> +   * +   * @return +   */ +  String getAuthnContextClassRef(); + +  /** +   * Define the AuthnContextComparison model, which should be used. +   * +   * @return +   */ +  AuthnContextComparisonTypeEnumeration getAuthnContextComparison(); + +  /** +   * Define the credential, which should be used to sign the AuthnRequest. +   * +   * @return +   */ +  EaafX509Credential getAuthnRequestSigningCredential(); + +  /** +   * Define the SAML2 EntityDescriptor of the IDP, which should receive the +   * AuthnRequest. +   * +   * @return Credential, but never null. +   */ +  EntityDescriptor getIdpEntityDescriptor(); + +  /** +   * Set the SAML2 NameIDPolicy allow-creation flag. +   * +   * @return EntityDescriptor, but never null. +   */ +  boolean getNameIdPolicyAllowCreation(); + +  /** +   * Set the requested SubjectNameID. +   * +   * @return SubjectNameID, or null if no SubjectNameID should be used +   */ +  String getSubjectNameID(); + +  /** +   * Define the qualifier of the <code>SubjectNameID</code> <br> +   * <br> +   * Like: 'urn:publicid:gv.at:cdid+BF' +   * +   * @return qualifier, or null if no qualifier should be set +   */ +  String getSubjectNameIdQualifier(); + +  /** +   * Define the format of the subjectNameID, which is included in authn-request. +   * +   * +   * @return nameIDFormat, of SAML2 'transient' if nothing is defined +   */ +  String getSubjectNameIdFormat(); + +  /** +   * Define a SP specific SAML2 requestID. +   * +   * @return requestID, or null if the requestID should be generated automatically +   */ +  String getRequestID(); + +  /** +   * Defines the 'method' attribute in 'SubjectConformation' element. +   * +   * @return method, or null if no method should set +   */ +  String getSubjectConformationMethode(); + +  /** +   * Define the information, which should be added as 'subjectConformationDate' in +   * 'SubjectConformation' element. +   * +   * @return subjectConformation information or null if no subjectConformation +   *         should be set +   */ +  Element getSubjectConformationDate(); + +  /** +   * Get the EntityId of the SP in case of a SAML2 proxy use-case. +   * +   * @return +   */ +  String getScopeRequesterId(); + +  /** +   * Get a FriendlyName for the SP that sends the request. +   * +   * @return +   */ +  String getProviderName(); + +  /** +   * Get a Set of SAML2 attributes that are requested by using SAML2 requested +   * attributes. <br> +   * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for +   * requested attributes +   * +   * @return +   */ +  List<EaafRequestedAttribute> getRequestedAttributes(); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java index 3afcc65d..4411d9c6 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java @@ -1,56 +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.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AssertionAttributeExtractorExeption extends PVP2Exception { - -	/** -	 *  -	 */ -	private static final long serialVersionUID = -6459000942830951492L; - -	public AssertionAttributeExtractorExeption(String attributeName) { -		super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName  -				+ " can not extract.", null); -	} -	 -	public AssertionAttributeExtractorExeption(String messageId, -			Object[] parameters) { -		super(messageId, parameters); -	} - -	public AssertionAttributeExtractorExeption() { -		super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null);  -	} +public class AssertionAttributeExtractorExeption extends Pvp2Exception { + +  private static final long serialVersionUID = -6459000942830951492L; + +  public AssertionAttributeExtractorExeption(final String attributeName) { +    super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName + " can not extract.", null); +  } + +  public AssertionAttributeExtractorExeption(final String messageId, final Object[] parameters) { +    super(messageId, parameters); +  } + +  public AssertionAttributeExtractorExeption() { +    super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null); +  }  } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java index 5766aab0..03fae599 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java @@ -1,53 +1,37 @@ -/******************************************************************************* - * 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.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AssertionValidationExeption extends PVP2Exception { +public class AssertionValidationExeption extends Pvp2Exception { -	private static final long serialVersionUID = -3987805399122286259L; +  private static final long serialVersionUID = -3987805399122286259L; -	public AssertionValidationExeption(String messageId, Object[] parameters) { -		super(messageId, parameters); -	} +  public AssertionValidationExeption(final String messageId, final Object[] parameters) { +    super(messageId, parameters); +  } -	/** -	 * @param string -	 * @param object -	 * @param e -	 */ -	public AssertionValidationExeption(String string, Object[] parameters, -			Throwable e) { -		super(string, parameters, e); -	} +  public AssertionValidationExeption(final String string, final Object[] parameters, +      final Throwable e) { +    super(string, parameters, e); +  }  } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java index 9fdffaf4..251ba759 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java @@ -1,53 +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.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AuthnRequestBuildException extends PVP2Exception { +public class AuthnRequestBuildException extends Pvp2Exception { -	/** -	 *  -	 */ -	private static final long serialVersionUID = -1375451065455859354L; +  private static final long serialVersionUID = -1375451065455859354L; -	/** -	 * @param messageId -	 * @param parameters -	 */ -	public AuthnRequestBuildException(String messageId, Object[] parameters) { -		super(messageId, parameters); -	} +  public AuthnRequestBuildException(final String messageId, final Object[] parameters) { +    super(messageId, parameters); +  } -	public AuthnRequestBuildException(String messageId, Object[] parameters, Throwable e) { -		super(messageId, parameters, e); -	} +  public AuthnRequestBuildException(final String messageId, final Object[] parameters, final Throwable e) { +    super(messageId, parameters, e); +  }  } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java index 9d2ec046..44fbf40f 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java @@ -1,54 +1,37 @@ -/******************************************************************************* - * 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.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AuthnResponseValidationException extends PVP2Exception { +public class AuthnResponseValidationException extends Pvp2Exception { + +  private static final long serialVersionUID = 8023812861029406575L; -	/** -	 *  -	 */ -	private static final long serialVersionUID = 8023812861029406575L; +  public AuthnResponseValidationException(final String messageId, final Object[] parameters) { +    super(messageId, parameters); +  } -	/** -	 * @param messageId -	 * @param parameters -	 */ -	public AuthnResponseValidationException(String messageId, Object[] parameters) { -		super(messageId, parameters); -	} -	 -	public AuthnResponseValidationException(String messageId, Object[] parameters, Throwable e) { -		super(messageId, parameters, e); -	} +  public AuthnResponseValidationException(final String messageId, final Object[] parameters, +      final Throwable e) { +    super(messageId, parameters, e); +  }  } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java deleted file mode 100644 index e8cdd1f7..00000000 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java +++ /dev/null @@ -1,259 +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.sp.impl; - -import java.security.NoSuchAlgorithmException; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.RequesterID; -import org.opensaml.saml2.core.Scoping; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; - -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -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.builder.reqattr.EAAFRequestExtensionBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; -import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPVPAuthnRequestBuilderConfiguruation; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; - -/** - * @author tlenz - * - */ -@Service("pvpAuthnRequestBuilder") -public class PVPAuthnRequestBuilder { -	private static final Logger log = LoggerFactory.getLogger(PVPAuthnRequestBuilder.class); -	 -	 -	@Autowired(required=true) ApplicationContext springContext; -	 -	 -	/** -	 * Build a PVP2.x specific authentication request -	 *  -	 * @param pendingReq Currently processed pendingRequest  -	 * @param config AuthnRequest builder configuration, never null -	 * @param idpEntity SAML2 EntityDescriptor of the IDP, which receive this AuthnRequest, never null -	 * @param httpResp -	 * @throws NoSuchAlgorithmException  -	 * @throws SecurityException  -	 * @throws PVP2Exception  -	 * @throws MessageEncodingException  -	 */  -	public void buildAuthnRequest(IRequest pendingReq, IPVPAuthnRequestBuilderConfiguruation config,  -			HttpServletResponse httpResp) throws NoSuchAlgorithmException, MessageEncodingException, PVP2Exception, SecurityException { -		//get IDP Entity element from config -		EntityDescriptor idpEntity = config.getIDPEntityDescriptor(); -		 -		AuthnRequest authReq = SAML2Utils -				.createSAMLObject(AuthnRequest.class); -		 -		//select SingleSignOn Service endpoint from IDP metadata -		SingleSignOnService endpoint = null;   -		for (SingleSignOnService sss :  -				idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { -			 -			// use POST binding as default if it exists  -			if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {  -				endpoint = sss;  -				 -			} else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)  -					&& endpoint == null ) -				endpoint = sss; -			 -		} -		 -		if (endpoint == null) { -			log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID()  -					+ " does not support POST or Redirect Binding."); -			throw new AuthnRequestBuildException("sp.pvp2.00", new Object[]{config.getSPNameForLogging(), idpEntity.getEntityID()}); -			 -		} else -			authReq.setDestination(endpoint.getLocation()); -		 -		 -		//set basic AuthnRequest information -		String reqID = config.getRequestID(); -		if (StringUtils.isNotEmpty(reqID)) -			authReq.setID(reqID); -		 -		else { -			SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); -			authReq.setID(gen.generateIdentifier()); -			 -		} -		 -		authReq.setIssueInstant(new DateTime()); -		 -		//set isPassive flag -		if (config.isPassivRequest() == null) -			authReq.setIsPassive(false); -		else -			authReq.setIsPassive(config.isPassivRequest()); - -		//set EntityID of the service provider -		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); -		issuer.setFormat(NameIDType.ENTITY); -		issuer.setValue(config.getSPEntityID()); -		authReq.setIssuer(issuer); - -		//set AssertionConsumerService ID -		if (config.getAssertionConsumerServiceId() != null) -			authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); -		 -		//set NameIDPolicy -		if (config.getNameIDPolicyFormat() != null) { -			NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); -			policy.setAllowCreate(config.getNameIDPolicyAllowCreation()); -			policy.setFormat(config.getNameIDPolicyFormat()); -			authReq.setNameIDPolicy(policy); -		} -		 -		//set requested QAA level -		if (config.getAuthnContextClassRef() != null) { -			RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class);		 -			AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); -		 -			authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); -			 -			if (config.getAuthnContextComparison() == null) -				reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); -			else -				reqAuthContext.setComparison(config.getAuthnContextComparison()); -			 -			reqAuthContext.getAuthnContextClassRefs().add(authnClassRef);					 -			authReq.setRequestedAuthnContext(reqAuthContext); -		} -						 -		//set request Subject element -		if (StringUtils.isNotEmpty(config.getSubjectNameID())) { -			Subject reqSubject = SAML2Utils.createSAMLObject(Subject.class); -			NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); -			 -			subjectNameID.setValue(config.getSubjectNameID()); -			if (StringUtils.isNotEmpty(config.getSubjectNameIDQualifier())) -				subjectNameID.setNameQualifier(config.getSubjectNameIDQualifier()); -			 -			if (StringUtils.isNotEmpty(config.getSubjectNameIDFormat())) -				subjectNameID.setFormat(config.getSubjectNameIDFormat()); -			else -				subjectNameID.setFormat(NameID.TRANSIENT); -			 -			reqSubject.setNameID(subjectNameID); -						 -			if (config.getSubjectConformationDate() != null) { -				SubjectConfirmation subjectConformation = SAML2Utils.createSAMLObject(SubjectConfirmation.class); -				SubjectConfirmationData subjectConformDate = SAML2Utils.createSAMLObject(SubjectConfirmationData.class);			 -				subjectConformation.setSubjectConfirmationData(subjectConformDate); -				reqSubject.getSubjectConfirmations().add(subjectConformation ); -							 -				if (config.getSubjectConformationMethode() != null) -					subjectConformation.setMethod(config.getSubjectConformationMethode()); -								 -				subjectConformDate.setDOM(config.getSubjectConformationDate()); -								 -			} -						 -			authReq.setSubject(reqSubject ); -						 -		} -		 -		 -		//set ProviderName -		if (StringUtils.isNotEmpty(config.getProviderName())) -				authReq.setProviderName(config.getProviderName()); -		 -		//set RequesterId in case of proxy mode -		if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { -			Scoping scope = SAML2Utils.createSAMLObject(Scoping.class); -			RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class); -			requesterId.setRequesterID(config.getScopeRequesterId()); -			scope.getRequesterIDs().add(requesterId ); -			authReq.setScoping(scope ); -			 -		} -		 -		//add optional requested attributes -		if (config.getRequestedAttributes() != null) { -			List<EAAFRequestedAttribute> reqAttr = config.getRequestedAttributes();			 -			Extensions extenstions = new EAAFRequestExtensionBuilder().buildObject();			 -			EAAFRequestedAttributes reqAttributs = SAML2Utils.createSAMLObject(EAAFRequestedAttributes.class); -			reqAttributs.getAttributes().addAll(reqAttr);			 -			extenstions.getUnknownXMLObjects().add(reqAttributs);			 -			authReq.setExtensions(extenstions ); -							 -		} -		 -		//select message encoder -		IEncoder binding = null; -		if (endpoint.getBinding().equals( -				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { -			binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); -														  -		} else if (endpoint.getBinding().equals( -				SAMLConstants.SAML2_POST_BINDING_URI)) { -			binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); -			 -		} -		 -		//encode message -		binding.encodeRequest(null, httpResp, authReq,  -				endpoint.getLocation(), pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); -	} -     -} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java new file mode 100644 index 00000000..752386a0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java @@ -0,0 +1,265 @@ +/* + * 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.sp.impl; + +import java.security.NoSuchAlgorithmException; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +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.builder.reqattr.EaafRequestExtensionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPvpAuthnRequestBuilderConfiguruation; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Extensions; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameID; +import org.opensaml.saml.saml2.core.NameIDPolicy; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.RequesterID; +import org.opensaml.saml.saml2.core.Scoping; +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.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.SingleSignOnService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + +import net.shibboleth.utilities.java.support.security.SecureRandomIdentifierGenerationStrategy; + +/** + * PVP2 S-Profil Authentication-Request builder-implementation. + * + * @author tlenz + * + */ +public class PvpAuthnRequestBuilder { +  private static final Logger log = LoggerFactory.getLogger(PvpAuthnRequestBuilder.class); + +  @Autowired(required = true) +  ApplicationContext springContext; + +  /** +   * Build a PVP2.x specific authentication request +   * +   * @param pendingReq Currently processed pendingRequest +   * @param config     AuthnRequest builder configuration, never null +   * @param httpResp   http response object +   * @throws NoSuchAlgorithmException In case of error +   * @throws SecurityException        In case of error +   * @throws Pvp2Exception            In case of error +   * @throws MessageEncodingException In case of error +   */ +  public void buildAuthnRequest(final IRequest pendingReq, +      final IPvpAuthnRequestBuilderConfiguruation config, final HttpServletResponse httpResp) +      throws NoSuchAlgorithmException, MessageEncodingException, Pvp2Exception, SecurityException { +    // get IDP Entity element from config +    final EntityDescriptor idpEntity = config.getIdpEntityDescriptor(); + +    final AuthnRequest authReq = Saml2Utils.createSamlObject(AuthnRequest.class); + +    // select SingleSignOn Service endpoint from IDP metadata +    SingleSignOnService endpoint = null; +    for (final SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) +        .getSingleSignOnServices()) { + +      // use POST binding as default if it exists +      if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { +        endpoint = sss; + +      } else if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) +          && endpoint == null) { +        endpoint = sss; +      } + +    } + +    if (endpoint == null) { +      log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() +          + " does not support POST or Redirect Binding."); +      throw new AuthnRequestBuildException("sp.pvp2.00", +          new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() }); + +    } else { +      authReq.setDestination(endpoint.getLocation()); +    } + +    // set basic AuthnRequest information +    final String reqID = config.getRequestID(); +    if (StringUtils.isNotEmpty(reqID)) { +      authReq.setID(reqID); +    } else { +      final SecureRandomIdentifierGenerationStrategy gen = new SecureRandomIdentifierGenerationStrategy(); +      authReq.setID(gen.generateIdentifier()); + +    } + +    authReq.setIssueInstant(new DateTime()); + +    // set isPassive flag +    if (config.isPassivRequest() == null) { +      authReq.setIsPassive(false); +    } else { +      authReq.setIsPassive(config.isPassivRequest()); +    } + +    // set EntityID of the service provider +    final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); +    issuer.setFormat(NameIDType.ENTITY); +    issuer.setValue(config.getSpEntityID()); +    authReq.setIssuer(issuer); + +    // set AssertionConsumerService ID +    if (config.getAssertionConsumerServiceId() != null) { +      authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); +    } + +    // set NameIDPolicy +    if (config.getNameIdPolicyFormat() != null) { +      final NameIDPolicy policy = Saml2Utils.createSamlObject(NameIDPolicy.class); +      policy.setAllowCreate(config.getNameIdPolicyAllowCreation()); +      policy.setFormat(config.getNameIdPolicyFormat()); +      authReq.setNameIDPolicy(policy); +    } + +    // set requested QAA level +    if (config.getAuthnContextClassRef() != null) { +      final RequestedAuthnContext reqAuthContext = +          Saml2Utils.createSamlObject(RequestedAuthnContext.class); +      final AuthnContextClassRef authnClassRef = +          Saml2Utils.createSamlObject(AuthnContextClassRef.class); + +      authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); + +      if (config.getAuthnContextComparison() == null) { +        reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); +      } else { +        reqAuthContext.setComparison(config.getAuthnContextComparison()); +      } + +      reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); +      authReq.setRequestedAuthnContext(reqAuthContext); +    } + +    // set request Subject element +    if (StringUtils.isNotEmpty(config.getSubjectNameID())) { +      final Subject reqSubject = Saml2Utils.createSamlObject(Subject.class); +      final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + +      subjectNameID.setValue(config.getSubjectNameID()); +      if (StringUtils.isNotEmpty(config.getSubjectNameIdQualifier())) { +        subjectNameID.setNameQualifier(config.getSubjectNameIdQualifier()); +      } + +      if (StringUtils.isNotEmpty(config.getSubjectNameIdFormat())) { +        subjectNameID.setFormat(config.getSubjectNameIdFormat()); +      } else { +        subjectNameID.setFormat(NameIDType.TRANSIENT); +      } + +      reqSubject.setNameID(subjectNameID); + +      if (config.getSubjectConformationDate() != null) { +        final SubjectConfirmation subjectConformation = +            Saml2Utils.createSamlObject(SubjectConfirmation.class); +        final SubjectConfirmationData subjectConformDate = +            Saml2Utils.createSamlObject(SubjectConfirmationData.class); +        subjectConformation.setSubjectConfirmationData(subjectConformDate); +        reqSubject.getSubjectConfirmations().add(subjectConformation); + +        if (config.getSubjectConformationMethode() != null) { +          subjectConformation.setMethod(config.getSubjectConformationMethode()); +        } + +        subjectConformDate.setDOM(config.getSubjectConformationDate()); + +      } + +      authReq.setSubject(reqSubject); + +    } + +    // set ProviderName +    if (StringUtils.isNotEmpty(config.getProviderName())) { +      authReq.setProviderName(config.getProviderName()); +    } + +    // set RequesterId in case of proxy mode +    if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { +      final Scoping scope = Saml2Utils.createSamlObject(Scoping.class); +      final RequesterID requesterId = Saml2Utils.createSamlObject(RequesterID.class); +      requesterId.setRequesterID(config.getScopeRequesterId()); +      scope.getRequesterIDs().add(requesterId); +      authReq.setScoping(scope); + +    } + +    // add optional requested attributes +    if (config.getRequestedAttributes() != null) { +      final List<EaafRequestedAttribute> reqAttr = config.getRequestedAttributes(); +      final Extensions extenstions = new EaafRequestExtensionBuilder().buildObject(); +      final EaafRequestedAttributes reqAttributs = +          Saml2Utils.createSamlObject(EaafRequestedAttributes.class); +      reqAttributs.getAttributes().addAll(reqAttr); +      extenstions.getUnknownXMLObjects().add(reqAttributs); +      authReq.setExtensions(extenstions); + +    } + +    // select message encoder +    IEncoder binding = null; +    if (endpoint.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { +      binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); + +    } else if (endpoint.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { +      binding = springContext.getBean("PvpPostBinding", PostBinding.class); + +    } else { +      log.warn("Binding: {} is not supported", endpoint.getBinding()); +      throw new AuthnRequestBuildException("sp.pvp2.00", +          new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() }); + +    } + +    // encode message +    binding.encodeRequest(null, httpResp, authReq, endpoint.getLocation(), +        pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java new file mode 100644 index 00000000..7fbd2daf --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging; + +import java.util.Arrays; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +public class PvpSpModuleMessageSource implements IMessageSourceLocation { + +  @Override +  public List<String> getMessageSourceLocation() { +    return Arrays.asList("classpath:messages/pvp_sp_messages"); + +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java index 22f1cb06..b12a5913 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.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.sp.impl.utils;  import java.util.ArrayList; @@ -35,308 +28,346 @@ import java.util.List;  import java.util.Map;  import java.util.Set; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; +  import org.apache.commons.lang3.StringUtils; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeStatement; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.core.Subject; -import org.opensaml.xml.XMLObject; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnStatement; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.core.Subject;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; -  public class AssertionAttributeExtractor { -	 -	private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); -	 -	private Assertion assertion = null; -	private Map<String, List<String>> attributs = new HashMap<String, List<String>>(); -	//private PersonalAttributeList storkAttributes = new PersonalAttributeList(); -		 -	private final List<String> minimalMDSAttributeNamesList = Arrays.asList( -			PVPConstants.PRINCIPAL_NAME_NAME,  -			PVPConstants.GIVEN_NAME_NAME, -			PVPConstants.BIRTHDATE_NAME, -			PVPConstants.BPK_NAME); - -	private final List<String> minimalIDLAttributeNamesList = Arrays.asList( -			PVPConstants.EID_IDENTITY_LINK_NAME,			 -			PVPConstants.EID_SOURCE_PIN_NAME, -			PVPConstants.EID_SOURCE_PIN_TYPE_NAME); -	 -	/** -	 * Parse the SAML2 Response element and extracts included information -	 * <br><br> -	 * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response is used! -	 *  -	 * @param samlResponse SAML2 Response -	 * @throws AssertionAttributeExtractorExeption -	 */ -	public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption { -		if (samlResponse != null && samlResponse instanceof Response) { -			List<Assertion> assertions = ((Response) samlResponse).getAssertions();			 -			if (assertions.size() == 0)  -				throw new AssertionAttributeExtractorExeption("Assertion"); -				 -			else if (assertions.size() > 1) -				log.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); -			 -			assertion = assertions.get(0); -			internalInitialize(); -			 -		} else  -			throw new AssertionAttributeExtractorExeption(); -	} -	 -	/** -	 * Parse the SAML2 Assertion element and extracts included information -	 * <br><br> -	 *  -	 * @param assertion SAML2 Assertion -	 * @throws AssertionAttributeExtractorExeption -	 */ -	public AssertionAttributeExtractor(Assertion assertion) throws AssertionAttributeExtractorExeption {			 -			this.assertion = assertion; -			internalInitialize(); -			 -	} - -	/** -	 * Get all SAML2 attributes from first SAML2 AttributeStatement element -	 *  -	 * @return List of SAML2 Attributes -	 */ -	public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() { -		return assertion.getAttributeStatements().get(0).getAttributes(); -		 -	} -	 -	/** -	 * Get all SAML2 attributes of specific SAML2 AttributeStatement element -	 *  -	 * @param attrStatementID List ID of the AttributeStatement element -	 * @return List of SAML2 Attributes -	 */ -	public List<Attribute> getAllResponseAttributes(int attrStatementID) { -		return assertion.getAttributeStatements().get(attrStatementID).getAttributes(); -		 -	} -	 -	/** -	 * check attributes from assertion with minimal required attribute list -	 * @return -	 */ -	public boolean containsAllRequiredAttributes() { -		return containsAllRequiredAttributes(minimalMDSAttributeNamesList)  -				|| containsAllRequiredAttributes(minimalIDLAttributeNamesList); -		 -	} -	 -	/** -	 * check attributes from assertion with attributeNameList -	 * bPK or enc_bPK are always needed -	 *  -	 * @param List of attributes which are required -	 *  -	 * @return -	 */ -	public boolean containsAllRequiredAttributes(Collection<String> attributeNameList) {		 -		 -		//first check if a bPK or an encrypted bPK is available -		boolean flag = true; -		for (String attr : attributeNameList) { -			if (!attributs.containsKey(attr)) { -				flag = false;					 -				log.debug("Assertion contains no Attribute " + attr); -									 -			} -					 -		} -		 -		if (flag) -			return flag; -		 -		else {			 -			log.debug("Assertion contains no all minimum attributes from: " + attributeNameList.toString()); -			return false; -			 -		}		 -	} -	 -	public boolean containsAttribute(String attributeName) { -		return attributs.containsKey(attributeName); -		 -	} -	 -	public String getSingleAttributeValue(String attributeName) { -		if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) -			return attributs.get(attributeName).get(0); -		else -			return null; -		 -	} -	 -	public List<String> getAttributeValues(String attributeName) { -		return attributs.get(attributeName); -		 -	} -	 -	/** -	 * Return all include PVP attribute names -	 *  -	 * @return -	 */ -	public Set<String> getAllIncludeAttributeNames() { -		return attributs.keySet(); -		 -	} -	 -//	public PersonalAttributeList getSTORKAttributes() { -//		return storkAttributes; -//	} -	 -	 -	public String getNameID() throws AssertionAttributeExtractorExeption {		 -		if (assertion.getSubject() != null) { -			Subject subject = assertion.getSubject(); -			 -			if (subject.getNameID() != null) { -				if (StringUtils.isNotEmpty(subject.getNameID().getValue()))					 -					return subject.getNameID().getValue();			 -				 -				else -					log.error("SAML2 NameID Element is empty."); -			} -		} -			 -		throw new AssertionAttributeExtractorExeption("nameID"); -	} -	 -	/** -	 * Get the Id attribute from SAML2 assertion -	 *  -	 * @return -	 */ -	public String getAssertionID() { -		return assertion.getID(); -		 -	} -	 -	public String getSessionIndex() throws AssertionAttributeExtractorExeption {		 -		AuthnStatement authn = getAuthnStatement(); -		 -		if (StringUtils.isNotEmpty(authn.getSessionIndex())) -			return authn.getSessionIndex(); -		 -		else -			throw new AssertionAttributeExtractorExeption("SessionIndex");		 -	} - -	/** -	 * @return -	 * @throws AssertionAttributeExtractorExeption  -	 */ -	public String getQAALevel() throws AssertionAttributeExtractorExeption { -		AuthnStatement authn = getAuthnStatement(); -		if (authn.getAuthnContext() != null && authn.getAuthnContext().getAuthnContextClassRef() != null) { -			AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef(); -			 -			if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) -				return qaaClass.getAuthnContextClassRef(); -			 -			else -				throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)");			 -		} -		 -		throw new AssertionAttributeExtractorExeption("AuthnContextClassRef");		 -	} -	 -	public Assertion getFullAssertion() { -		return assertion; -	} -	 -	 -	/** -	 * Get the Assertion validTo period -	 *  -	 * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' element is used. -	 * If this is empty, this method returns value of  SAML 'Conditions' element.  -	 *  -	 * @return Date, until this SAML2 assertion is valid -	 */ -	public Date getAssertionNotOnOrAfter() { -		if (getFullAssertion().getAuthnStatements() != null  -				&& getFullAssertion().getAuthnStatements().size() > 0) { -			for (AuthnStatement el : getFullAssertion().getAuthnStatements()) { -				if (el.getSessionNotOnOrAfter() != null) -					return (el.getSessionNotOnOrAfter().toDate()); -			} -			 -		}  -		 -		return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); -					 -	} -	 -	/** -	 * Get the Assertion validFrom period -	 *  -     * This method returns value of  SAML 'Conditions' element.  -	 *  -	 * @return Date, after this SAML2 assertion is valid, otherwise null -	 */ -	public Date getAssertionNotBefore() { -		try { -			return getFullAssertion().getConditions().getNotBefore().toDate(); -			 -		} catch (NullPointerException e) { -			return null; -			 -		} -					 -	} -	 -	private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { -		List<AuthnStatement> authnList = assertion.getAuthnStatements(); -		if (authnList.size() == 0) -			throw new AssertionAttributeExtractorExeption("AuthnStatement"); -		 -		else if (authnList.size() > 1) -			log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used."); -		 -		return authnList.get(0); -	} -	 -	private void internalInitialize() { -		if (assertion.getAttributeStatements() != null && -				assertion.getAttributeStatements().size() > 0) { -			AttributeStatement attrStat = assertion.getAttributeStatements().get(0); -			for (Attribute attr : attrStat.getAttributes()) { -				if (attr.getName().startsWith(PVPConstants.STORK_ATTRIBUTE_PREFIX)) {							 -					List<String> storkAttrValues = new ArrayList<String>(); -					for (XMLObject el : attr.getAttributeValues()) -						storkAttrValues.add(el.getDOM().getTextContent()); -					 -//					PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(),  -//							false, storkAttrValues , "Available"); -//					storkAttributes.put(attr.getName(), storkAttr ); -					 -				} else { -					List<String> attrList = new ArrayList<String>(); -					for (XMLObject el : attr.getAttributeValues()) -						attrList.add(el.getDOM().getTextContent()); - -					attributs.put(attr.getName(), attrList); -											 -				} -			}	 -		}	 -	} + +  private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); + +  private Assertion assertion = null; +  private final Map<String, List<String>> attributs = new HashMap<>(); +  // private PersonalAttributeList storkAttributes = new PersonalAttributeList(); + +  @Deprecated +  private final List<String> minimalMdsAttributeNamesList = +      Arrays.asList(PvpConstants.PRINCIPAL_NAME_NAME, PvpConstants.GIVEN_NAME_NAME, +          PvpConstants.BIRTHDATE_NAME, PvpConstants.BPK_NAME); + +  @Deprecated +  private final List<String> minimalIdlAttributeNamesList = +      Arrays.asList(PvpConstants.EID_IDENTITY_LINK_NAME, PvpConstants.EID_SOURCE_PIN_NAME, +          PvpConstants.EID_SOURCE_PIN_TYPE_NAME); + +  private final List<String> minimalEidAttributeNamesList = +      Arrays.asList(ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME); + +  /** +   * Parse the SAML2 Response element and extracts included information. <br> +   * <br> +   * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response +   * is used! +   * +   * @param samlResponse SAML2 Response +   * @throws AssertionAttributeExtractorExeption In case of an error +   */ +  public AssertionAttributeExtractor(final StatusResponseType samlResponse) +      throws AssertionAttributeExtractorExeption { +    if (samlResponse != null && samlResponse instanceof Response) { +      final List<Assertion> assertions = ((Response) samlResponse).getAssertions(); +      if (assertions.size() == 0) { +        throw new AssertionAttributeExtractorExeption("Assertion"); +      } else if (assertions.size() > 1) { +        log.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); +      } + +      assertion = assertions.get(0); +      internalInitialize(); + +    } else { +      throw new AssertionAttributeExtractorExeption(); +    } +  } + +  /** +   * Parse the SAML2 Assertion element and extracts included information. <br> +   * <br> +   * +   * @param assertion SAML2 Assertion +   * @throws AssertionAttributeExtractorExeption In case of an error +   */ +  public AssertionAttributeExtractor(final Assertion assertion) +      throws AssertionAttributeExtractorExeption { +    this.assertion = assertion; +    internalInitialize(); + +  } + +  /** +   * Get all SAML2 attributes from first SAML2 AttributeStatement element. +   * +   * @return List of SAML2 Attributes +   */ +  public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() { +    return assertion.getAttributeStatements().get(0).getAttributes(); + +  } + +  /** +   * Get all SAML2 attributes of specific SAML2 AttributeStatement element. +   * +   * @param attrStatementID List ID of the AttributeStatement element +   * @return List of SAML2 Attributes +   */ +  public List<Attribute> getAllResponseAttributes(final int attrStatementID) { +    return assertion.getAttributeStatements().get(attrStatementID).getAttributes(); + +  } + +  /** +   * check attributes from assertion with minimal required attribute list. +   * +   * @return +   */ +  public boolean containsAllRequiredAttributes() { +    return containsAllRequiredAttributes(minimalEidAttributeNamesList) +        || containsAllRequiredAttributes(minimalIdlAttributeNamesList) +        || containsAllRequiredAttributes(minimalMdsAttributeNamesList); + +  } + +  /** +   * check attributes from assertion with attributeNameList bPK or enc_bPK are +   * always needed. +   * +   * @param attributeNameList List of attributes which are required +   * +   * @return +   */ +  public boolean containsAllRequiredAttributes(final Collection<String> attributeNameList) { + +    // first check if a bPK or an encrypted bPK is available +    boolean flag = true; +    for (final String attr : attributeNameList) { +      if (!attributs.containsKey(attr)) { +        flag = false; +        log.debug("Assertion contains no Attribute " + attr); + +      } + +    } + +    if (flag) { +      return flag; +    } else { +      log.debug( +          "Assertion contains no all minimum attributes from: " + attributeNameList.toString()); +      return false; + +    } +  } + +  public boolean containsAttribute(final String attributeName) { +    return attributs.containsKey(attributeName); + +  } + +  /** +   * Get single attribute with name. +   * +   * @param attributeName attribute Name +   * @return Attribute value +   */ +  public String getSingleAttributeValue(final String attributeName) { +    if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) { +      return attributs.get(attributeName).get(0); +    } else { +      return null; +    } + +  } + +  public List<String> getAttributeValues(final String attributeName) { +    return attributs.get(attributeName); + +  } + +  /** +   * Return all include PVP attribute names. +   * +   * @return +   */ +  public Set<String> getAllIncludeAttributeNames() { +    return attributs.keySet(); + +  } + +  /** +   * Get User's nameId. +   * +   * @return nameId +   * @throws AssertionAttributeExtractorExeption In case of an error +   */ +  public String getNameID() throws AssertionAttributeExtractorExeption { +    if (assertion.getSubject() != null) { +      final Subject subject = assertion.getSubject(); + +      if (subject.getNameID() != null) { +        if (StringUtils.isNotEmpty(subject.getNameID().getValue())) { +          return subject.getNameID().getValue(); +        } else { +          log.error("SAML2 NameID Element is empty."); +        } +      } +    } + +    throw new AssertionAttributeExtractorExeption("nameID"); +  } + +  /** +   * Get the Id attribute from SAML2 assertion. +   * +   * @return +   */ +  public String getAssertionID() { +    return assertion.getID(); + +  } + +  /** +   * Get SessionIndex from assertion. +   * +   * @return sessionIndex +   * @throws AssertionAttributeExtractorExeption In case of an error +   */ +  public String getSessionIndex() throws AssertionAttributeExtractorExeption { +    final AuthnStatement authn = getAuthnStatement(); + +    if (StringUtils.isNotEmpty(authn.getSessionIndex())) { +      return authn.getSessionIndex(); +    } else { +      throw new AssertionAttributeExtractorExeption("SessionIndex"); +    } +  } + +  /** +   * Get LoA from Assertion. +   * +   * @return LoA +   * @throws AssertionAttributeExtractorExeption In case of an error +   */ +  public String getQaaLevel() throws AssertionAttributeExtractorExeption { +    final AuthnStatement authn = getAuthnStatement(); +    if (authn.getAuthnContext() != null +        && authn.getAuthnContext().getAuthnContextClassRef() != null) { +      final AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef(); + +      if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) { +        return qaaClass.getAuthnContextClassRef(); +      } else { +        throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)"); +      } +    } + +    throw new AssertionAttributeExtractorExeption("AuthnContextClassRef"); +  } + +  public Assertion getFullAssertion() { +    return assertion; +  } + +  /** +   * Get the Assertion validTo period. +   * +   * <p> +   * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' +   * element is used. If this is empty, this method returns value of SAML +   * 'Conditions' element. +   * </p> +   * +   * @return Date, until this SAML2 assertion is valid +   */ +  public Date getAssertionNotOnOrAfter() { +    if (getFullAssertion().getAuthnStatements() != null +        && getFullAssertion().getAuthnStatements().size() > 0) { +      for (final AuthnStatement el : getFullAssertion().getAuthnStatements()) { +        if (el.getSessionNotOnOrAfter() != null) { +          return el.getSessionNotOnOrAfter().toDate(); +        } +      } + +    } + +    return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); + +  } + +  /** +   * Get the Assertion issuing date. +   * +   * <p> +   * This method returns value of SAML 'Conditions' element. +   * </p> +   * +   * @return Date, when the SAML2 assertion was issued, otherwise null +   */ +  public Date getAssertionIssuingDate() { +    try { +      return getFullAssertion().getIssueInstant().toDate(); + +    } catch (final NullPointerException e) { +      return null; + +    } +  } + +  /** +   * Get the Assertion validFrom period. +   * +   * <p> +   * This method returns value of SAML 'Conditions' element. +   * </p> +   * +   * @return Date, after this SAML2 assertion is valid, otherwise null +   */ +  public Date getAssertionNotBefore() { +    try { +      return getFullAssertion().getConditions().getNotBefore().toDate(); + +    } catch (final NullPointerException e) { +      return null; + +    } +  } + +  private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { +    final List<AuthnStatement> authnList = assertion.getAuthnStatements(); +    if (authnList.size() == 0) { +      throw new AssertionAttributeExtractorExeption("AuthnStatement"); +    } else if (authnList.size() > 1) { +      log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used."); +    } + +    return authnList.get(0); +  } + +  private void internalInitialize() { +    if (assertion.getAttributeStatements() != null +        && assertion.getAttributeStatements().size() > 0) { +      final AttributeStatement attrStat = assertion.getAttributeStatements().get(0); +      for (final Attribute attr : attrStat.getAttributes()) { +        final List<String> attrList = new ArrayList<>(); +        for (final XMLObject el : attr.getAttributeValues()) { +          attrList.add(el.getDOM().getTextContent()); +          attributs.put(attr.getName(), attrList); + +        } +      } +    } +  }  } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 00000000..9a6cb2d2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml new file mode 100644 index 00000000..439ad005 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml @@ -0,0 +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="pvpSpLogMessageSource" +        class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging.PvpSpModuleMessageSource" /> + +  <bean id="pvpAuthnRequestBuilder" +        class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.PvpAuthnRequestBuilder" /> +         +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties new file mode 100644 index 00000000..682c3f18 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties @@ -0,0 +1,17 @@ +sp.pvp2.00=Can not build PVP AuthnRequest for {0} {1}. No valid SingleSignOnService endpoint found. +sp.pvp2.01=Can not build PVP AuthnRequest for {0}. IDP is not allowed for federated authentication. +sp.pvp2.02=Can not build PVP AuthnRequest for {0}. IDP has no (valid) metadata. +sp.pvp2.03=Receive PVP Response from {0} with unsupported Binding.   +sp.pvp2.04=Receive invalid PVP Response from {0}. No PVP metadata found.   +sp.pvp2.05=Receive invalid PVP Response from {0} {1}. StatusCode:{2} Msg:{3}. +sp.pvp2.06=Receive invalid PVP Response from {0}. Assertion does not contain all required attributes. +sp.pvp2.07=Receive invalid PVP Response from {0}. Attribute {1} is not valid. +sp.pvp2.08=Receive invalid PVP Response from {0}. Response issuer {1} is not valid or allowed. +sp.pvp2.09=Receive invalid PVP Response from {0} {1}. StatusCodes:{2} {3} Msg:{4} +sp.pvp2.10=Receive invalid PVP Response from {0}. No valid assertion included. +sp.pvp2.11=Receive invalid PVP Response from {0}. Assertion decryption FAILED. +sp.pvp2.12=Receive invalid PVP Response from {0}. Msg:{1} +sp.pvp2.13=Can not build PVP AuthnRequest for {0}. Internal processing error. + + + diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java new file mode 100644 index 00000000..4a132c3f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java @@ -0,0 +1,57 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.test; + +import java.io.IOException; +import java.io.InputStream; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider; +import at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider; + +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; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileSpSpringResourceProviderTest { + +  @Test +  public void testSpringConfig() { +    final Pvp2SProfileCoreSpringResourceProvider test = +        new Pvp2SProfileCoreSpringResourceProvider(); +    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", +          Pvp2SProfileSpSpringResourceProvider.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_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java new file mode 100644 index 00000000..90bb084a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java @@ -0,0 +1,39 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.test; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/eaaf_pvp_sp.beans.xml"}) +public class PvpSpMessageSourceTest { + +  @Autowired +  private ResourceLoader loader; +  @Autowired(required = false) +  private List<IMessageSourceLocation> messageSources; + +  @Test +  public void checkMessageSources() { +    Assert.assertNotNull("No messageSource", messageSources); + +    for (final IMessageSourceLocation messageSource : messageSources) { +      Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation()); + +      for (final String el : messageSource.getMessageSourceLocation()) { +        final Resource messages = loader.getResource(el + ".properties"); +        Assert.assertTrue("Source not exist", messages.exists()); + +      } +    } +  } +} | 
