diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20')
27 files changed, 3017 insertions, 2724 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/pom.xml b/eaaf_modules/eaaf_module_auth_sl20/pom.xml index 2153dfaa..f293f37e 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/pom.xml +++ b/eaaf_modules/eaaf_module_auth_sl20/pom.xml @@ -1,14 +1,17 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" +  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>      <groupId>at.gv.egiz.eaaf</groupId>      <artifactId>eaaf_modules</artifactId> -    <version>1.0.14-SNAPSHOT</version> +    <version>1.1.0-SNAPSHOT</version>    </parent>    <artifactId>eaaf_module_auth_sl20</artifactId>    <name>Generic SL2.0 authentication</name> -   -   <licenses> + +  <licenses>      <license>        <name>European Union Public License, version 1.2 (EUPL-1.2)</name>        <url>https://opensource.org/licenses/EUPL-1.2</url> @@ -24,37 +27,37 @@        <organizationUrl>https://www.egiz.gv.at</organizationUrl>      </developer>    </developers> -   +    <dependencies> -  	<dependency> -		<groupId>at.gv.egiz.eaaf</groupId> -	  	<artifactId>eaaf-core</artifactId> -	  	<version>${egiz.eaaf.version}</version> -	</dependency> -  	<dependency> -    	<groupId>org.bitbucket.b_c</groupId> -    	<artifactId>jose4j</artifactId> -  	</dependency> -  	<dependency> -    	<groupId>com.fasterxml.jackson.core</groupId> -    	<artifactId>jackson-databind</artifactId> -	</dependency> -  	 -	<dependency> -    	<groupId>javax.servlet</groupId> -    	<artifactId>javax.servlet-api</artifactId> -    	<scope>provided</scope> -	</dependency>  	  	 +    <dependency> +      <groupId>at.gv.egiz.eaaf</groupId> +      <artifactId>eaaf-core</artifactId> +      <version>${egiz.eaaf.version}</version> +    </dependency> +    <dependency> +      <groupId>org.bitbucket.b_c</groupId> +      <artifactId>jose4j</artifactId> +    </dependency> +    <dependency> +      <groupId>com.fasterxml.jackson.core</groupId> +      <artifactId>jackson-databind</artifactId> +    </dependency> + +    <dependency> +      <groupId>javax.servlet</groupId> +      <artifactId>javax.servlet-api</artifactId> +      <scope>provided</scope> +    </dependency>    </dependencies> -   +    <build> -   	<resources> -  		<resource> -  			<directory>src/main/resources</directory> -  		</resource> -  	</resources> -   -     <plugins> +    <resources> +      <resource> +        <directory>src/main/resources</directory> +      </resource> +    </resources> + +    <plugins>        <plugin>          <groupId>org.apache.maven.plugins</groupId>          <artifactId>maven-compiler-plugin</artifactId> @@ -70,13 +73,13 @@          <artifactId>maven-jar-plugin</artifactId>          <version>3.1.1</version>          <configuration> -        	<archive> -            	<manifest> -              		<addClasspath>true</addClasspath> -              		<addDefaultImplementationEntries>true</addDefaultImplementationEntries> -              		<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> -            	</manifest> -          	</archive>             +          <archive> +            <manifest> +              <addClasspath>true</addClasspath> +              <addDefaultImplementationEntries>true</addDefaultImplementationEntries> +              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> +            </manifest> +          </archive>          </configuration>        </plugin> @@ -92,23 +95,23 @@            </filesets>          </configuration>        </plugin> -       +        <!-- enable co-existence of testng and junit --> -	  <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> +      <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> -   +  </project>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java index 7e306f25..4009796f 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java @@ -2,129 +2,145 @@ package at.gv.egiz.eaaf.modules.auth.sl20;  import java.util.Arrays;  import java.util.List; -  import javax.annotation.PostConstruct; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IspConfiguration;  import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired;  /** + * AuthModule to select a Securtiy-Layer 2.0 based authentication process. + *   * @author tlenz   *   */ -public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule {	 -	private static final Logger log = LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class); -	 -	private int priority = 3; -	public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4"); -		 -	@Autowired(required=true) protected IConfiguration authConfig; -	@Autowired(required=true) private AbstractAuthenticationManager authManager; -	 -	@Override -	public int getPriority() {  -		return priority;  -	} - -	/** -	 * Sets the priority of this module. Default value is {@code 0}. -	 * @param priority The priority. -	 */ -	public void setPriority(int priority) { -		this.priority = priority; -	} - -	@PostConstruct -	protected void initalSL20Authentication() { -		//parameter to whiteList -		authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); -		authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); -		 -	} -	 -	 -	/* (non-Javadoc) -	 * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) -	 */ -	@Override -	public String selectProcess(ExecutionContext context, IRequest pendingReq) { -		final ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); -		 -		if (spConfig == null) { -			log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); -			throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); -			 -		} -		 -		final String sl20ClientTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase()); -		final String sl20VDATypeHeader = (String)  context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); -		 -		if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(), getGeneralConfigPropertyNameEnableModuleDefault())) { -			if (spConfig != null &&  -					StringUtils.isNotEmpty(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule())) && -						Boolean.valueOf(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule()))) { -				log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier()); -				log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE +  ": " + sl20ClientTypeHeader);			 -				log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE +  ": " + sl20VDATypeHeader); -				return getProcessName(); -			 -			} else { -				log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier()); -				return null; -			 -			} -			 -		} else { -			log.trace("SL2.0 is NOT enabled with property: {}", getGeneralConfigPropertyNameEnableModule()); -			return null; -		 -		} -						 -	} - -	/** -	 * Get the general configuration-key that holds the enabled key for this authentication module  -	 *  -	 * @return -	 */ -	public abstract String getGeneralConfigPropertyNameEnableModule(); - -	/** -	 * Get the default value of the general configuration-key that holds the enabled key for this authentication module  -	 *  -	 * @return -	 */ -	public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault(); -	 -	/** -	 * Get the SP specific configuration-key that holds the enabled key for this authentication module  -	 *  -	 * @return configuration key for SP configuration -	 */ -	public abstract String getSPConfigPropertyNameEnableModule(); -	 -	/** -	 * Get the name of this specific SL2.0 process -	 *  -	 * @return -	 */ -	public abstract String getProcessName(); -	 -	/* (non-Javadoc) -	 * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() -	 */ -	@Override -	public abstract String[] getProcessDefinitions(); +public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule { +  private static final Logger log = +      LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class); + +  private int priority = 3; +  public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4"); + +  @Autowired(required = true) +  protected IConfiguration authConfig; +  @Autowired(required = true) +  private AbstractAuthenticationManager authManager; + +  @Override +  public int getPriority() { +    return priority; +  } + +  /** +   * Sets the priority of this module. Default value is {@code 0}. +   * +   * @param priority The priority. +   */ +  public void setPriority(final int priority) { +    this.priority = priority; +  } + +  @PostConstruct +  protected void initalSL20Authentication() { +    // parameter to whiteList +    authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); +    authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); + +  } + + +  /* +   * (non-Javadoc) +   * +   * @see +   * at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process +   * .api.ExecutionContext) +   */ +  @Override +  public String selectProcess(final ExecutionContext context, final IRequest pendingReq) { +    final IspConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); + +    if (spConfig == null) { +      log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); +      throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); + +    } + +    final String sl20ClientTypeHeader = +        (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase()); +    final String sl20VdaTypeHeader = +        (String) context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); + +    if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(), +        getGeneralConfigPropertyNameEnableModuleDefault())) { +      if (spConfig != null +          && StringUtils +              .isNotEmpty(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule())) +          && Boolean +              .valueOf(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule()))) { +        log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier()); +        log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + ": " + sl20ClientTypeHeader); +        log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE + ": " + sl20VdaTypeHeader); +        return getProcessName(); + +      } else { +        log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier()); +        return null; + +      } + +    } else { +      log.trace("SL2.0 is NOT enabled with property: {}", +          getGeneralConfigPropertyNameEnableModule()); +      return null; + +    } + +  } + +  /** +   * Get the general configuration-key that holds the enabled key for this authentication module. +   * +   * @return +   */ +  public abstract String getGeneralConfigPropertyNameEnableModule(); + +  /** +   * Get the default value of the general configuration-key that holds the enabled key for this +   * authentication module. +   * +   * @return +   */ +  public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault(); + +  /** +   * Get the SP specific configuration-key that holds the enabled key for this authentication module. +   * +   * @return configuration key for SP configuration +   */ +  public abstract String getSpConfigPropertyNameEnableModule(); + +  /** +   * Get the name of this specific SL2.0 process. +   * +   * @return +   */ +  public abstract String getProcessName(); + +  /* +   * (non-Javadoc) +   * +   * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() +   */ +  @Override +  public abstract String[] getProcessDefinitions();  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java index a1490d2b..a8460911 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java @@ -1,58 +1,75 @@  package at.gv.egiz.eaaf.modules.auth.sl20;  public class Constants { -	 -	public static final String CONFIG_PROP_PREFIX = "modules.sl20"; -	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = CONFIG_PROP_PREFIX + ".vda.urls.qualeID."; -	 -	public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX + ".vda.authblock.transformation.id";	 -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path"; -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX + ".security.keystore.password"; -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias"; -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX + ".security.sign.password"; -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX + ".security.encryption.alias";; -	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX + ".security.encryption.password"; -	 -	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; -	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; -	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list"; -	public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; -	 -	public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + ".security.eID.validation.disable"; -	public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled"; -	public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.required"; -	public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX + ".security.eID.signed.result.required"; -	 -	public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url"; -	public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code"; -	public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303"; -	 -	public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled"; -	public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints"; -	 -	public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_"; -	 -	/** -	 * Only dummy data for development!!!!!! 	   -	 */ -	public static final String DUMMY_SIGNING_CERT =  -			"MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n" +  -			"BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n" +  -			"HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n" +  -			"MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n" +  -			"cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n" +  -			"Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n" +  -			"WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n" +  -			"WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n" +  -			"Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n" +  -			"V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n" +  -			"LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n" +  -			"8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n" +  -			"60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n" +  -			"3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n" +  -			"8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n" +  -			"TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg=="; -	 -	public static final String DUMMY_SIGNING_CERT_FINGERPRINT = "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW"; + +  public static final String CONFIG_PROP_PREFIX = "modules.sl20"; +  public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = +      CONFIG_PROP_PREFIX + ".vda.urls.qualeID."; + +  public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = +      CONFIG_PROP_PREFIX + ".vda.authblock.transformation.id"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = +      CONFIG_PROP_PREFIX + ".security.keystore.path"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = +      CONFIG_PROP_PREFIX + ".security.keystore.password"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = +      CONFIG_PROP_PREFIX + ".security.sign.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = +      CONFIG_PROP_PREFIX + ".security.sign.password"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = +      CONFIG_PROP_PREFIX + ".security.encryption.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = +      CONFIG_PROP_PREFIX + ".security.encryption.password"; + +  public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; +  public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = +      CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; +  public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = +      CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list"; +  public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; + +  public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = +      CONFIG_PROP_PREFIX + ".security.eID.validation.disable"; +  public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = +      CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled"; +  public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = +      CONFIG_PROP_PREFIX + ".security.eID.encryption.required"; +  public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = +      CONFIG_PROP_PREFIX + ".security.eID.signed.result.required"; + +  public static final String CONFIG_PROP_IPC_RETURN_URL = +      CONFIG_PROP_PREFIX + ".testing.ipc.return.url"; +  public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = +      CONFIG_PROP_PREFIX + ".testing.redirect.http.code"; +  public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303"; + +  public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled"; +  public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints"; + +  public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_"; + +  /** +   * Only dummy data for development!!!!!!. +   */ +  public static final String DUMMY_SIGNING_CERT = +      "MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n" +          + "BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n" +          + "HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n" +          + "MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n" +          + "cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n" +          + "Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n" +          + "WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n" +          + "WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n" +          + "Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n" +          + "V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n" +          + "LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n" +          + "8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n" +          + "60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n" +          + "3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n" +          + "8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n" +          + "TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg=="; + +  public static final String DUMMY_SIGNING_CERT_FINGERPRINT = +      "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW";  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java index e19ef5fc..af155206 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java @@ -1,16 +1,16 @@  package at.gv.egiz.eaaf.modules.auth.sl20;  /** - * Set of event codes uses in Auth-Handler implementation - *  + * Set of event codes uses in Auth-Handler implementation. + *   * @author tlenz   *   */  public class EventCodes { -	public static final int AUTHPROCESS_SL20_SELECTED = 4111; -	public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112; -	public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; -	 -	public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113; +  public static final int AUTHPROCESS_SL20_SELECTED = 4111; +  public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112; +  public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; + +  public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113;  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java index 0c625a9b..7ca4ea87 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java @@ -7,33 +7,34 @@ import com.fasterxml.jackson.databind.JsonNode;  public class VerificationResult { -	private Boolean validSigned = null; -	private List<X509Certificate> certs = null; -	private JsonNode payload = null; -	 -	public VerificationResult(JsonNode payload) { -		this.payload = payload; -		 -	} -	 -	public VerificationResult(JsonNode string, List<X509Certificate> certs, boolean wasValidSigned) { -		this.payload = string; -		this.certs = certs; -		this.validSigned = wasValidSigned; -		 -	} -	 -	public Boolean isValidSigned() { -		return validSigned; -	} -	public List<X509Certificate> getCertChain() { -		return certs; -	} -	public JsonNode getPayload() { -		return payload; -	} -	 -	 -	 -	 +  private Boolean validSigned = null; +  private List<X509Certificate> certs = null; +  private JsonNode payload = null; + +  public VerificationResult(final JsonNode payload) { +    this.payload = payload; + +  } + +  public VerificationResult(final JsonNode string, final List<X509Certificate> certs, final boolean wasValidSigned) { +    this.payload = string; +    this.certs = certs; +    this.validSigned = wasValidSigned; + +  } + +  public Boolean isValidSigned() { +    return validSigned; +  } + +  public List<X509Certificate> getCertChain() { +    return certs; +  } + +  public JsonNode getPayload() { +    return payload; +  } + + +  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java new file mode 100644 index 00000000..a14fbe9e --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SL20EidDataValidationException extends SL20Exception { +  private static final long serialVersionUID = 1L; + +  public SL20EidDataValidationException(final Object[] parameters) { +    super("sl20.07", parameters); + +  } + +  public SL20EidDataValidationException(final Object[] parameters, final Throwable e) { +    super("sl20.07", parameters, e); + +  } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java index b23b5ca3..12921ad6 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java @@ -1,19 +1,19 @@  package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; -public class SL20Exception extends EAAFAuthenticationException { +public class SL20Exception extends EaafAuthenticationException { -	private static final long serialVersionUID = 1L; +  private static final long serialVersionUID = 1L; -	public SL20Exception(String messageId, Object[] parameters) { -		super(messageId, parameters); +  public SL20Exception(final String messageId, final Object[] parameters) { +    super(messageId, parameters); -	} -	 -	public SL20Exception(String messageId, Object[] parameters, Throwable wrapped) { -		super(messageId, parameters, wrapped); +  } -	} +  public SL20Exception(final String messageId, final Object[] parameters, final Throwable wrapped) { +    super(messageId, parameters, wrapped); + +  }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java index eaf55ba3..c751f2c2 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java @@ -2,19 +2,19 @@ package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;  public class SL20SecurityException extends SL20Exception { -	private static final long serialVersionUID = 3281385988027147449L; +  private static final long serialVersionUID = 3281385988027147449L; -	public SL20SecurityException(Object[] parameters) { -		super("sl20.05", parameters); -	} -	 -	public SL20SecurityException(String parameter) { -		super("sl20.05", new Object[] {parameter}); -	} -	 -	public SL20SecurityException(Object[] parameters, Throwable wrapped) { -		super("sl20.05", parameters, wrapped); +  public SL20SecurityException(final Object[] parameters) { +    super("sl20.05", parameters); +  } -	} +  public SL20SecurityException(final String parameter) { +    super("sl20.05", new Object[] {parameter}); +  } + +  public SL20SecurityException(final Object[] parameters, final Throwable wrapped) { +    super("sl20.05", parameters, wrapped); + +  }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java deleted file mode 100644 index 24df735a..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java +++ /dev/null @@ -1,16 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SL20eIDDataValidationException extends SL20Exception { -	private static final long serialVersionUID = 1L; - -	public SL20eIDDataValidationException(Object[] parameters) { -		super("sl20.07", parameters); -		 -	} -	 -	public SL20eIDDataValidationException(Object[] parameters, Throwable e) { -		super("sl20.07", parameters, e); -		 -	} - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java deleted file mode 100644 index 1f521ebc..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SLCommandoBuildException extends SL20Exception { - -	private static final long serialVersionUID = 1L; - -	 -	public SLCommandoBuildException(String msg) { -		super("sl20.01", new Object[]{msg}); -		 -	} -	 -	public SLCommandoBuildException(String msg, Throwable e) { -		super("sl20.01", new Object[]{msg}, e); -		 -	} -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java deleted file mode 100644 index 60993e69..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SLCommandoParserException extends SL20Exception { - -	private static final long serialVersionUID = 1L; - -	 -	public SLCommandoParserException(String msg) { -		super("sl20.02", new Object[]{msg}); -		 -	} -	 -	public SLCommandoParserException(String msg, Throwable e) { -		super("sl20.02", new Object[]{msg}, e); -		 -	} -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java new file mode 100644 index 00000000..bed1cdb0 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java @@ -0,0 +1,17 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SlCommandoBuildException extends SL20Exception { + +  private static final long serialVersionUID = 1L; + + +  public SlCommandoBuildException(final String msg) { +    super("sl20.01", new Object[] {msg}); + +  } + +  public SlCommandoBuildException(final String msg, final Throwable e) { +    super("sl20.01", new Object[] {msg}, e); + +  } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java new file mode 100644 index 00000000..dab42631 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java @@ -0,0 +1,17 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SlCommandoParserException extends SL20Exception { + +  private static final long serialVersionUID = 1L; + + +  public SlCommandoParserException(final String msg) { +    super("sl20.02", new Object[] {msg}); + +  } + +  public SlCommandoParserException(final String msg, final Throwable e) { +    super("sl20.02", new Object[] {msg}, e); + +  } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java new file mode 100644 index 00000000..251b516f --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java @@ -0,0 +1,250 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.tasks; + +import java.security.cert.CertificateEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.api.idp.IspConfiguration; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServletTask { +  private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualEidRequestTask.class); + +  @Autowired(required = true) +  private IHttpClientFactory httpClientFactory; +  @Autowired(required = true) +  protected IConfigurationWithSP authConfigWithSp; + +  @Override +  public void execute(final ExecutionContext executionContext, final HttpServletRequest request, +      final HttpServletResponse response) throws TaskExecutionException { + +    log.debug("Starting SL2.0 authentication process .... "); + +    revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth"); + +    try { +      // get service-provider configuration +      final IspConfiguration oaConfig = pendingReq.getServiceProviderConfiguration(); + +      if (oaConfig == null) { +        log.warn("No SP configuration in pendingReq!"); +        throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!"); + +      } + +      // get basic configuration parameters +      final String vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext); +      if (StringUtils.isEmpty(vdaQualEidDUrl)) { +        log.error("NO VDA URL for qualified eID (" +            + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")"); +        throw new SL20Exception("sl20.03", new Object[] {"NO VDA URL for qualified eID"}); + +      } + +      log.debug("Use {} as VDA end-point", vdaQualEidDUrl); +      pendingReq.setRawDataToTransaction( +          Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, +          vdaQualEidDUrl); +      revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualEidDUrl); + +      // create SL2.0 command for qualified eID +      final String signedQualEidCommand = buildSignedQualifiedEidCommand(); + +      // build request container +      final String qualEidReqId = Random.nextProcessReferenceValue(); +      final ObjectNode sl20Req = +          SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, null, null, signedQualEidCommand); + +      // build http POST request +      final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualEidDUrl).build()); +      final List<NameValuePair> parameters = new ArrayList<>(); +      parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, +          Base64Url.encode(sl20Req.toString().getBytes()))); +      httpReq.setEntity(new UrlEncodedFormEntity(parameters)); + +      // build http GET request +      // URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); +      // sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, +      // Base64Url.encode(sl20Req.toString().getBytes())); +      // HttpGet httpReq = new HttpGet(sl20ReqUri.build()); + +      // set native client header +      httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, +          SL20Constants.HTTP_HEADER_VALUE_NATIVE); + +      log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes())); + +      // request VDA +      final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); + +      // parse response +      log.info("Receive response from VDA ... "); +      final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp); +      final VerificationResult respPayloadContainer = +          SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); + +      if (respPayloadContainer.isValidSigned() == null) { +        log.debug("Receive unsigned payLoad from VDA"); + +      } + +      final JsonNode respPayload = respPayloadContainer.getPayload(); +      if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() +          .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) { +        log.debug("Find 'redirect' command in VDA response ... "); +        final JsonNode params = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, +            SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true); +        final String redirectUrl = SL20JsonExtractorUtils.getStringValue(params, +            SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true); +        final JsonNode command = SL20JsonExtractorUtils.getJsonObjectValue(params, +            SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false); +        final String signedCommand = SL20JsonExtractorUtils.getStringValue(params, +            SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false); + +        // create forward SL2.0 command +        final ObjectNode sl20Forward = sl20Resp.deepCopy(); +        SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, +            SL20Constants.SL20_SIGNEDPAYLOAD, command.deepCopy(), signedCommand); + +        // store pending request +        pendingReq.setRawDataToTransaction( +            Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, qualEidReqId); +        requestStoreage.storePendingRequest(pendingReq); + +        // forward SL2.0 command +        // TODO: maybe add SL2ClientType Header from execution context +        SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectUrl, +            Integer +                .parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, +                    Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); + +      } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() +          .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { +        JsonNode result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, +            SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false); +        if (result == null) { +          result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, +              SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false); +        } + +        final String errorCode = SL20JsonExtractorUtils.getStringValue(result, +            SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); +        final String errorMsg = SL20JsonExtractorUtils.getStringValue(result, +            SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); + +        log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); +        throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg}); + +      } else { +        // TODO: update to add error handling +        log.warn("Received an unrecognized command: " +            + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()); +        throw new SlCommandoParserException( +            "Received an unrecognized command: " +                 + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).toString()); +      } + + +    } catch (final EaafAuthenticationException e) { +      throw new TaskExecutionException(pendingReq, +          "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); + +    } catch (final Exception e) { +      log.warn("SL2.0 Authentication FAILED with a generic error.", e); +      throw new TaskExecutionException(pendingReq, e.getMessage(), e); + +    } finally { +      TransactionIdUtils.removeTransactionId(); +      TransactionIdUtils.removeSessionId(); + +    } + +  } + +  /** +   * Create a implementation specific qualified eID SL2.0 command +   * +   * @param oaConfig +   * +   * @return signed JWT token as serialized {@link String} +   * @throws CertificateEncodingException In case of certificate parsing error +   * @throws SL20Exception In case of a SL2.0 error +   */ +  protected abstract String buildSignedQualifiedEidCommand() +      throws CertificateEncodingException, SL20Exception; + + +  private String extractVdaUrlForSpecificOa(final IspConfiguration oaConfig, +      final ExecutionContext executionContext) { + +    // load SP specific config for development and testing purposes +    final String spSpecificVdaEndpoints = +        oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST); + +    // load general configuration +    final Map<String, String> endPointMap = authConfigWithSp +        .getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST); +    endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT)); +    if (StringUtils.isNotEmpty(spSpecificVdaEndpoints)) { +      endPointMap.putAll(KeyValueUtils.convertListToMap(KeyValueUtils +          .getListOfCsvValues(KeyValueUtils.normalizeCsvValueString(spSpecificVdaEndpoints)))); +      log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... "); + +    } + +    log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... "); + +    // selection based on request Header +    final String sl20VdaTypeHeader = +        (String) executionContext.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); +    if (StringUtils.isNotEmpty(sl20VdaTypeHeader)) { +      final String vdaUrl = endPointMap.get(sl20VdaTypeHeader); +      if (StringUtils.isNotEmpty(vdaUrl)) { +        return vdaUrl.trim(); +      } else { +        log.info("Can NOT find VDA with Id: " + sl20VdaTypeHeader + ". Use default VDA"); +      } + +    } + + +    log.info("NO specific VDA endpoint requested or found. Use default VDA"); +    return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT); + +  } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java deleted file mode 100644 index 85302d83..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java +++ /dev/null @@ -1,227 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.tasks; - -import java.security.cert.CertificateEncodingException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; -import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils; - -public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServletTask { -	private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualeIDRequestTask.class); -	 -	@Autowired(required=true) private IHttpClientFactory httpClientFactory; -	@Autowired(required=true) protected IConfigurationWithSP authConfigWithSp; -	 -	@Override  -	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) -			throws TaskExecutionException { -			 -			log.debug("Starting SL2.0 authentication process .... "); -  -			revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth"); -			 -			try { -				//get service-provider configuration -				final ISPConfiguration oaConfig = pendingReq.getServiceProviderConfiguration(); -				 -				if (oaConfig == null) { -					log.warn("No SP configuration in pendingReq!"); -					throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!"); -					 -				} -				 -				//get basic configuration parameters -				final String vdaQualeIDUrl = extractVDAURLForSpecificOA(oaConfig, executionContext);				 -				if (StringUtils.isEmpty(vdaQualeIDUrl)) { -					log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")"); -					throw new SL20Exception("sl20.03", new Object[]{"NO VDA URL for qualified eID"}); -					 -				} -				 -				log.debug("Use {} as VDA end-point", vdaQualeIDUrl) ; -				pendingReq.setRawDataToTransaction( -						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,  -						vdaQualeIDUrl); -				revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualeIDUrl); -						 -				//create SL2.0 command for qualified eID -				final String signedQualeIDCommand = buildSignedQualifiedEIDCommand(); -						 -				//build request container -				final String qualeIDReqId = Random.nextProcessReferenceValue(); -				final ObjectNode sl20Req = SL20JSONBuilderUtils.createGenericRequest(qualeIDReqId, null, null, signedQualeIDCommand); -				 -				//build http POST request -				final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualeIDUrl).build());								 -				final List<NameValuePair> parameters = new ArrayList<NameValuePair>();; -				parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes()))); -				httpReq.setEntity(new UrlEncodedFormEntity(parameters ));				 -				 -				//build http GET request -//				URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); -//				sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes())); -//				HttpGet httpReq = new HttpGet(sl20ReqUri.build()); -				 -				//set native client header -				httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE); - -				log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes())); -				 -				//request VDA -				final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); -								 -				//parse response -				log.info("Receive response from VDA ... "); -				final JsonNode sl20Resp = SL20JSONExtractorUtils.getSL20ContainerFromResponse(httpResp); -				final VerificationResult respPayloadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); -				 -				if (respPayloadContainer.isValidSigned() == null) { -					log.debug("Receive unsigned payLoad from VDA"); -					 -				} -				 -				final JsonNode respPayload = respPayloadContainer.getPayload(); -				if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() -						.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) { -					log.debug("Find 'redirect' command in VDA response ... ");									 -					final JsonNode params = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true);					 -					final String redirectURL = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true);									 -					final JsonNode command = SL20JSONExtractorUtils.getJSONObjectValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false); -					final String signedCommand = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false);					 - -					//create forward SL2.0 command -					final ObjectNode sl20Forward = sl20Resp.deepCopy();					 -					SL20JSONBuilderUtils.addOnlyOnceOfTwo(sl20Forward,  -							SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,  -							command.deepCopy(), signedCommand); -										 -					//store pending request -					pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,  -							qualeIDReqId); -					requestStoreage.storePendingRequest(pendingReq); - -					//forward SL2.0 command -					//TODO: maybe add SL2ClientType Header from execution context -					SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL, -							Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); -													 -				} else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() -						.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {  -					JsonNode result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false); -					if (result  == null) -						result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false); -					 -					final String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); -					final String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); -					 -					log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); -					throw new SL20Exception("sl20.08", new Object[]{errorCode, errorMsg}); -					 -				} else { -					//TODO: update to add error handling -					log.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()); -					throw new SLCommandoParserException("Received an unrecognized command: \" + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()"); -				} -				 -				 -			} catch (final EAAFAuthenticationException  e) { -				throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); -				 -			} catch (final Exception e) { -				log.warn("SL2.0 Authentication FAILED with a generic error.", e); -				throw new TaskExecutionException(pendingReq, e.getMessage(), e); -				 -			} finally {				 -				TransactionIDUtils.removeTransactionId(); -				TransactionIDUtils.removeSessionId(); -				 -			} -			 -	} -			 -	/** -	 * Create a implementation specific qualified eID SL2.0 command -	 * @param oaConfig  -	 *  -	 * @return signed JWT token as serialized {@link String}  -	 * @throws CertificateEncodingException  -	 * @throws SLCommandoBuildException  -	 * @throws SL20Exception  -	 */ -	protected abstract String buildSignedQualifiedEIDCommand() throws CertificateEncodingException, SL20Exception; - -	 -	private String extractVDAURLForSpecificOA(ISPConfiguration oaConfig, ExecutionContext executionContext) {		 -		 -		//load SP specific config for development and testing purposes -		final String spSpecificVDAEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST);		 -		 -		//load general configuration -		final Map<String, String> endPointMap = authConfigWithSp.getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST); -		endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT)); -		if (StringUtils.isNotEmpty(spSpecificVDAEndpoints)) { -			endPointMap.putAll(KeyValueUtils.convertListToMap( -							KeyValueUtils.getListOfCSVValues( -								KeyValueUtils.normalizeCSVValueString(spSpecificVDAEndpoints)))); -			log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... "); -		 -		}  -				 -		log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... "); -		 -		//selection based on request Header -		final String sl20VDATypeHeader = (String)  executionContext.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); -		if (StringUtils.isNotEmpty(sl20VDATypeHeader)) { -			final String vdaURL = endPointMap.get(sl20VDATypeHeader); -			if (StringUtils.isNotEmpty(vdaURL)) -				return vdaURL.trim();			 -			else  -				log.info("Can NOT find VDA with Id: " + sl20VDATypeHeader + ". Use default VDA"); -						 -		} - -				 -		log.info("NO specific VDA endpoint requested or found. Use default VDA"); -		return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT); -				 -	} - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java new file mode 100644 index 00000000..39cfce05 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java @@ -0,0 +1,344 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.tasks; + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder; +import at.gv.egiz.eaaf.core.impl.utils.StreamUtils; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJoseTools; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + + +public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask { +  private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class); + +  private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; + +  @Autowired(required = true) +  private IJoseTools joseTools; + +  @Override +  public void execute(final ExecutionContext executionContext, final HttpServletRequest request, +      final HttpServletResponse response) throws TaskExecutionException { +    String sl20Result = null; + +    try { +      log.debug("Receiving SL2.0 response process .... "); +      JsonNode sl20ReqObj = null; + +      // A-Trust does not SET http-header 'SL2ClientType' with value 'native' +      // If A-trust sends an error, its maybe FrontChannel on DataURL +      // boolean aTrustErrorWorkAround = false; + +      try { +        // get SL2.0 command or result from HTTP request +        final Map<String, String> reqParams = getParameters(request); +        sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); + +        if (StringUtils.isEmpty(sl20Result)) { +          // Workaround for SIC Handy-Signature, because it sends result in InputStream +          final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8"); +          if (StringUtils.isNotEmpty(isReqInput)) { +            log.info("Use SIC Handy-Signature work-around!"); +            sl20Result = isReqInput.substring("slcommand=".length()); + +          } else { +            log.info("NO SL2.0 commando or result FOUND."); +            throw new SL20Exception("sl20.04", null); +          } + +        } + +        log.trace("Received SL2.0 result: " + sl20Result); +        revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, +            request.getRemoteAddr()); + +        // parse SL2.0 command/result into JSON +        try { +          sl20ReqObj = +              new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result)); + +        } catch (final JsonParseException e) { +          log.warn("SL2.0 command or result is NOT valid JSON.", e); +          log.debug("SL2.0 msg: " + sl20Result); +          throw new SL20Exception("sl20.02", +              new Object[] {"SL2.0 command or result is NOT valid JSON."}, e); + +        } + +        // check on errorMessage +        final VerificationResult payLoadContainerErrorCheck = +            SL20JsonExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, false); +        if (SL20JsonExtractorUtils +            .getStringValue(payLoadContainerErrorCheck.getPayload(), +                SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) +            .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { +          log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... "); +          final JsonNode errorResult = SL20JsonExtractorUtils +              .extractSL20Result(payLoadContainerErrorCheck.getPayload(), joseTools, false); +          final String errorCode = SL20JsonExtractorUtils.getStringValue(errorResult, +              SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); +          final String errorMsg = SL20JsonExtractorUtils.getStringValue(errorResult, +              SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false); + +          log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", +              errorCode, errorMsg); +          // aTrustErrorWorkAround = true; +          throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg}); + +        } else { +          // Receive no error - To request validation + +          // validate reqId with inResponseTo +          final String sl20ReqId = pendingReq.getRawData( +              Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); +          final String inRespTo = +              SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); +          if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { +            log.info( +                "SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +            throw new SL20SecurityException( +                "SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +          } + + +          // validate signature +          final VerificationResult payLoadContainer = SL20JsonExtractorUtils +              .extractSL20PayLoad(sl20ReqObj, joseTools, authConfig.getBasicConfigurationBoolean( +                  Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); + +          if ((payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) { +            if (authConfig.getBasicConfigurationBoolean( +                Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { +              log.info("SL20 result from VDA was not valid signed"); +              throw new SL20SecurityException(new Object[] {"Signature on SL20 result NOT valid."}); + +            } else { +              log.warn( +                  "SL20 result from VDA is NOT valid signed, but signatures-verification " +                  + "is DISABLED by configuration!"); + +            } +          } + +          payLoadContainer.getCertChain(); + + +          // extract payloaf +          final JsonNode payLoad = payLoadContainer.getPayload(); + + +          // handle SL2.0 response payLoad +          handleResponsePayLoad(payLoad); + +        } + +      } catch (final EaafAuthenticationException e) { +        log.warn("SL2.0 processing error:", e); +        if (sl20Result != null) { +          log.debug("Received SL2.0 result: " + sl20Result); +        } +        pendingReq.setRawDataToTransaction( +            Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, +            new TaskExecutionException(pendingReq, +                "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); + +      } catch (final Exception e) { +        log.warn("ERROR:", e); +        log.warn("SL2.0 Authentication FAILED with a generic error.", e); +        if (sl20Result != null) { +          log.debug("Received SL2.0 result: " + sl20Result); +        } +        pendingReq.setRawDataToTransaction( +            Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, +            new TaskExecutionException(pendingReq, e.getMessage(), e)); + +      } finally { +        // store pending request +        requestStoreage.storePendingRequest(pendingReq); + +        // write SL2.0 response +        if (sl20ReqObj != null) { +          // buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround); +          buildResponse(request, response, sl20ReqObj); +        } else { +          buildErrorResponse(request, response, "2000", "General transport Binding error"); +        } + +      } + +    } catch (final Exception e) { +      // write internal server errror 500 according to SL2.0 specification, chapter https transport +      // binding +      log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e); +      if (sl20Result != null) { +        log.debug("Received SL2.0 result: " + sl20Result); +      } +      try { +        response.sendError(500, "Internal Server Error."); + +      } catch (final IOException e1) { +        log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); + +      } + +    } finally { +      TransactionIdUtils.removeTransactionId(); +      TransactionIdUtils.removeSessionId(); + +    } +  } + +  protected abstract void handleResponsePayLoad(JsonNode payLoad) +      throws SlCommandoParserException, SL20Exception, EaafStorageException; + +  protected abstract String getResumeEndPoint(); + +  private void buildErrorResponse(final HttpServletRequest request, +      final HttpServletResponse response, final String errorCode, final String errorMsg) +      throws Exception { +    final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg); +    final ObjectNode errorCommand = SL20JsonBuilderUtils +        .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); + + +    final ObjectNode respContainer = SL20JsonBuilderUtils +        .createGenericResponse(UUID.randomUUID().toString(), null, null, errorCommand, null); + +    log.trace("SL20 response to VDA: " + respContainer); +    final StringWriter writer = new StringWriter(); +    writer.write(respContainer.toString()); +    final byte[] content = writer.toString().getBytes("UTF-8"); +    response.setStatus(HttpServletResponse.SC_OK); +    response.setContentLength(content.length); +    response.setContentType(ContentType.APPLICATION_JSON.toString()); +    response.getOutputStream().write(content); + +  } + +  private void buildResponse(final HttpServletRequest request, final HttpServletResponse response, +      final JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException { +    // create response +    final Map<String, String> reqParameters = new HashMap<>(); +    reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, +        pendingReq.getPendingRequestId()); +    final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters( +        new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), null), +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters); +    final ObjectNode callCommand = SL20JsonBuilderUtils +        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); + +    // build first redirect command for app +    final ObjectNode redirectOneParams = SL20JsonBuilderUtils.createRedirectCommandParameters( +        generateIpcRedirectUrlForDebugging(), callCommand, null, true); +    final ObjectNode redirectOneCommand = SL20JsonBuilderUtils +        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); + +    // build second redirect command for IDP +    final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters( +        new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), +            pendingReq.getPendingRequestId()), +        redirectOneCommand, null, false); +    final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils +        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); + +    // build generic SL2.0 response container +    final String transactionId = +        SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); +    final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest( +        UUID.randomUUID().toString(), transactionId, redirectTwoCommand, null); + +    if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null +        && request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) +            .equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { +      log.debug("Client request containts 'native client' header ... "); +      log.trace("SL20 response to VDA: " + respContainer); +      final StringWriter writer = new StringWriter(); +      writer.write(respContainer.toString()); +      final byte[] content = writer.toString().getBytes("UTF-8"); +      response.setStatus(HttpServletResponse.SC_OK); +      response.setContentLength(content.length); +      response.setContentType(ContentType.APPLICATION_JSON.toString()); +      response.getOutputStream().write(content); + + +    } else { +      log.info("SL2.0 DataURL communication needs http header: '" +          + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); + +      log.debug("Client request containts is no native client ... "); +      final URIBuilder clientRedirectUri = +          new URIBuilder(new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), +              getResumeEndPoint(), pendingReq.getPendingRequestId())); +      response.setStatus(Integer +          .parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, +              Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); +      response.setHeader("Location", clientRedirectUri.build().toString()); + + +      // throw new SL20Exception("sl20.06", +      // new Object[] {"SL2.0 DataURL communication needs http header: '" + +      // SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); + +    } +  } + +  /** +   * Generates a IPC redirect URL that is configured on IDP side. +   * +   * @return IPC ReturnURL, or null if no URL is configured +   */ +  private String generateIpcRedirectUrlForDebugging() { + + +    String ipcRedirectUrlConfig = +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL); +    if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) { +      if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) { +        log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); +        ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#", +            EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" +                + pendingReq.getPendingRequestId()); + +      } + +      return ipcRedirectUrlConfig; +    } + +    return null; + +  } + + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java deleted file mode 100644 index b4039cf9..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java +++ /dev/null @@ -1,321 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.tasks; - -import java.io.IOException; -import java.io.StringWriter; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.ContentType; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder; -import at.gv.egiz.eaaf.core.impl.utils.StreamUtils; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJOSETools; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils; - - -public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask { -	private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualeIDTask.class); -	 -	@Autowired(required=true) private IJOSETools joseTools; -	 -	@Override -	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) -			throws TaskExecutionException {		 -		String sl20Result = null; -		  -		try { -			log.debug("Receiving SL2.0 response process .... "); -			JsonNode sl20ReqObj = null; -			 -			//A-Trust does not SET http-header 'SL2ClientType' with value 'native' -			//If A-trust sends an error, its maybe FrontChannel on DataURL -			//boolean aTrustErrorWorkAround = false; -			 -			try { -				//get SL2.0 command or result from HTTP request -				final Map<String, String> reqParams = getParameters(request); -				sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); -				 -				if (StringUtils.isEmpty(sl20Result)) { -					//Workaround for SIC Handy-Signature, because it sends result in InputStream -					final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8");					 -					if (StringUtils.isNotEmpty(isReqInput)) { -						log.info("Use SIC Handy-Signature work-around!"); -						sl20Result = isReqInput.substring("slcommand=".length()); -						 -					} else {					 -						log.info("NO SL2.0 commando or result FOUND."); -						throw new SL20Exception("sl20.04", null); -					} -				 -				} - -				log.trace("Received SL2.0 result: " + sl20Result);				 -				revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, request.getRemoteAddr()); -			 -				//parse SL2.0 command/result into JSON			 -				try { -					sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result)); -				 -				} catch (final JsonParseException  e) { -					log.warn("SL2.0 command or result is NOT valid JSON.", e); -					log.debug("SL2.0 msg: " + sl20Result); -					throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e); -				 -				} -			 -				//check on errorMessage -				final VerificationResult payLoadContainerErrorCheck = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, false); -				if (SL20JSONExtractorUtils.getStringValue( -						payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) -							.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { -					log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... "); -					final JsonNode errorResult = SL20JSONExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(), joseTools, false); -					final String errorCode = SL20JSONExtractorUtils.getStringValue(errorResult,  -							SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); -					final String errorMsg = SL20JSONExtractorUtils.getStringValue(errorResult,  -							SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false); -					 -					log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", errorCode, errorMsg); -					//aTrustErrorWorkAround = true; -					throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg}); -									 -				} else { -					//Receive no error - To request validation -					 -					//validate reqId with inResponseTo  -					final String sl20ReqId = pendingReq.getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); -					final String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); -					if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { -						log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -						throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -					} -				 -				 -					//validate signature -					final VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad( -							sl20ReqObj, joseTools,  -							authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); -					 -					if ( (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) { -						if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { -							log.info("SL20 result from VDA was not valid signed"); -							throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); -					 -						} else { -							log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification is DISABLED by configuration!"); -							 -						} -					} -					 -					payLoadContainer.getCertChain(); -				 -				 -					//extract payloaf -					final JsonNode payLoad = payLoadContainer.getPayload(); -				 -					 -					//handle SL2.0 response payLoad -					handleResponsePayLoad(payLoad); -					 -				}		 -				 -			} catch (final EAAFAuthenticationException  e) { -				log.warn("SL2.0 processing error:", e); -				if (sl20Result != null) -					log.debug("Received SL2.0 result: " + sl20Result); -				pendingReq.setRawDataToTransaction( -						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,  -						new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); -				 -			} catch (final Exception e) { -				log.warn("ERROR:", e); -				log.warn("SL2.0 Authentication FAILED with a generic error.", e); -				if (sl20Result != null) -					log.debug("Received SL2.0 result: " + sl20Result); -				pendingReq.setRawDataToTransaction( -						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,  -						new TaskExecutionException(pendingReq, e.getMessage(), e)); -				 -			} finally { -				//store pending request -				requestStoreage.storePendingRequest(pendingReq); -								 -					//write SL2.0 response -					if (sl20ReqObj != null)				 -						//buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround); -						buildResponse(request, response, sl20ReqObj); -					else  -						buildErrorResponse(request, response, "2000", "General transport Binding error");					 -					 -			} -		 -		} catch (final Exception e) { -			//write internal server errror 500 according to SL2.0 specification, chapter https transport binding			 -			log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e); -			if (sl20Result != null) -				log.debug("Received SL2.0 result: " + sl20Result); -			try { -				response.sendError(500, "Internal Server Error."); -				 -			} catch (final IOException e1) { -				log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); -				 -			}	 -			 -		} finally { -			TransactionIDUtils.removeTransactionId(); -			TransactionIDUtils.removeSessionId(); -			 -		} -	} - -	protected abstract void handleResponsePayLoad(JsonNode payLoad) throws SLCommandoParserException, SL20Exception, EAAFStorageException; - -	protected abstract String getResumeEndPoint(); -	 -	private void buildErrorResponse(HttpServletRequest request, HttpServletResponse response, String errorCode, String errorMsg) throws Exception {				 -		final ObjectNode error = SL20JSONBuilderUtils.createErrorCommandResult(errorCode, errorMsg); -		final ObjectNode errorCommand = SL20JSONBuilderUtils.createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); -		 -		 -		final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericResponse( -				UUID.randomUUID().toString(), -				null, -				null,  -				errorCommand ,  -				null); -				 -		log.trace("SL20 response to VDA: " + respContainer); -		final StringWriter writer = new StringWriter(); -		writer.write(respContainer.toString());						 -		final byte[] content = writer.toString().getBytes("UTF-8"); -		response.setStatus(HttpServletResponse.SC_OK); -		response.setContentLength(content.length); -		response.setContentType(ContentType.APPLICATION_JSON.toString());						 -		response.getOutputStream().write(content); -				 -	} - -	private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException {		 -		//create response  -		final Map<String, String> reqParameters = new HashMap<String, String>(); -		reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); -		final ObjectNode callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( -				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), null),  -				SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,  -				false,  -				reqParameters); -		final ObjectNode callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); -				 -		//build first redirect command for app -		final ObjectNode redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters( -		generateICPRedirectURLForDebugging(),  -		callCommand, null, true); -		final ObjectNode redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); -						 -		//build second redirect command for IDP -		final ObjectNode redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( -				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()),  -				redirectOneCommand, null, false); -		final ObjectNode redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); -		 -		//build generic SL2.0 response container								 -		final String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); -		final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericRequest( -				UUID.randomUUID().toString(),  -				transactionId,  -				redirectTwoCommand,  -				null);  -				 -		if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  -				request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {					 -			log.debug("Client request containts 'native client' header ... "); -			log.trace("SL20 response to VDA: " + respContainer); -			final StringWriter writer = new StringWriter(); -			writer.write(respContainer.toString());						 -			final byte[] content = writer.toString().getBytes("UTF-8"); -			response.setStatus(HttpServletResponse.SC_OK); -			response.setContentLength(content.length); -			response.setContentType(ContentType.APPLICATION_JSON.toString());						 -			response.getOutputStream().write(content); -			 -			 -		} else {						 -			log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); -			 -			log.debug("Client request containts is no native client ... "); -			final URIBuilder clientRedirectURI = new URIBuilder( -					new DataURLBuilder().buildDataURL( -							pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId())); -			response.setStatus(Integer.parseInt( -					authConfig.getBasicConfiguration( -							Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,  -							Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); -			response.setHeader("Location", clientRedirectURI.build().toString()); -			 -			 -//			throw new SL20Exception("sl20.06",  -//					new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); -			 -		} -	} - -	/** -	 * Generates a IPC redirect URL that is configured on IDP side -	 *  -	 * @return IPC ReturnURL, or null if no URL is configured -	 */ -	private String generateICPRedirectURLForDebugging() { -		final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; -			 -		String ipcRedirectURLConfig = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL);				 -		if (StringUtils.isNotEmpty(ipcRedirectURLConfig)) {			 -			if (ipcRedirectURLConfig.contains(PATTERN_PENDING_REQ_ID)) { -				log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); -				ipcRedirectURLConfig = ipcRedirectURLConfig.replaceAll( -						"#PENDINGREQID#",  -						EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId()); -			 -			} -			 -			return ipcRedirectURLConfig; -		} -	 -		return null; -		 -	} -	 -	 -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java deleted file mode 100644 index b124ada7..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java +++ /dev/null @@ -1,87 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.X509Certificate; -import java.util.List; - -import javax.annotation.Nonnull; - -import org.jose4j.jwa.AlgorithmConstraints; -import org.jose4j.lang.JoseException; - -import com.fasterxml.jackson.databind.JsonNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; - -public interface IJOSETools { - -	/** -	 * Create a JWS signature -	 *  -	 * @param payLoad Payload to sign -	 * @throws SLCommandoBuildException  -	 */ -	public String createSignature(String payLoad) throws SLCommandoBuildException; - -	/** -	 * Validates a signed SL2.0 message -	 *  -	 * @param serializedContent -	 * @return -	 * @throws SLCommandoParserException -	 * @throws SL20Exception  -	 */ -	@Nonnull -	public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception; -	 -	/** -	 * Validate a JWS signature  -	 *  -	 * @param serializedContent JWS in serialized form -	 * @param trustedCerts trusted X509 certificates -	 * @param constraints signature verification constraints -	 * @return Signature-verification result -	 * @throws JoseException -	 * @throws IOException -	 */ -	@Nonnull -	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, -			@Nonnull AlgorithmConstraints constraints) throws JoseException, IOException; -	 -	/** -	 * Validate a JWS signature  -	 *  -	 * @param serializedContent JWS in serialized form -	 * @param trustStore with trusted X509 certificates -	 * @param algconstraints signature verification constraints -	 * @return Signature-verification result -	 * @throws JoseException -	 * @throws IOException -	 * @throws KeyStoreException  -	 */ -	@Nonnull -	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore, -			@Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException; -	 -	/** -	 * Get the encryption certificate for SL2.0 End-to-End encryption -	 *  -	 * @return -	 */ -	public X509Certificate getEncryptionCertificate(); - -	/** -	 * Decrypt a serialized JWE token -	 *  -	 * @param compactSerialization Serialized JWE token -	 * @return decrypted payload -	 * @throws SL20Exception  -	 */ -	public JsonNode decryptPayload(String compactSerialization) throws SL20Exception; - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java new file mode 100644 index 00000000..caa2e8d8 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java @@ -0,0 +1,84 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.X509Certificate; +import java.util.List; +import javax.annotation.Nonnull; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.lang.JoseException; +import com.fasterxml.jackson.databind.JsonNode; + +public interface IJoseTools { + +  /** +   * Create a JWS signature. +   * +   * @param payLoad Payload to sign +   * @throws SlCommandoBuildException In case of a signature creation error +   */ +  public String createSignature(String payLoad) throws SlCommandoBuildException; + +  /** +   * Validates a signed SL2.0 message. +   * +   * @param serializedContent Serialized JWS signature +   * @return Verification-result DAO +   * @throws SL20Exception In case of a signature validation error +   */ +  @Nonnull +  public VerificationResult validateSignature(@Nonnull String serializedContent) +      throws SL20Exception; + +  /** +   * Validate a JWS signature. +   * +   * @param serializedContent JWS in serialized form +   * @param trustedCerts trusted X509 certificates +   * @param constraints signature verification constraints +   * @return Signature-verification result +   * @throws JoseException In case of a signature verification error +   * @throws IOException In case of a general IO error +   */ +  @Nonnull +  public VerificationResult validateSignature(@Nonnull String serializedContent, +      @Nonnull List<X509Certificate> trustedCerts, @Nonnull AlgorithmConstraints constraints) +      throws JoseException, IOException; + +  /** +   * Validate a JWS signature. +   * +   * @param serializedContent JWS in serialized form +   * @param trustStore with trusted X509 certificates +   * @param algconstraints signature verification constraints +   * @return Signature-verification result +   * @throws JoseException In case of a signature verification error +   * @throws IOException In case of a general IO error +   * @throws KeyStoreException In case of TrustStore error +   */ +  @Nonnull +  public VerificationResult validateSignature(@Nonnull String serializedContent, +      @Nonnull KeyStore trustStore, @Nonnull AlgorithmConstraints algconstraints) +      throws JoseException, IOException, KeyStoreException; + +  /** +   * Get the encryption certificate for SL2.0 End-to-End encryption. +   * +   * @return +   */ +  public X509Certificate getEncryptionCertificate(); + +  /** +   * Decrypt a serialized JWE token. +   * +   * @param compactSerialization Serialized JWE token +   * @return decrypted payload +   * @throws SL20Exception In case of a decryption error +   */ +  public JsonNode decryptPayload(String compactSerialization) throws SL20Exception; + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java index b33649e1..f38203d2 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java @@ -18,114 +18,125 @@ import com.fasterxml.jackson.databind.SerializationFeature;  import com.fasterxml.jackson.databind.type.TypeFactory;  import at.gv.egiz.eaaf.core.api.utils.IJsonMapper; -import at.gv.egiz.eaaf.core.exceptions.EAAFJsonMapperException; +import at.gv.egiz.eaaf.core.exceptions.EaafJsonMapperException;  public class JsonMapper implements IJsonMapper { -	private static final Logger log = LoggerFactory.getLogger(JsonMapper.class); -	 -	private final ObjectMapper mapper = new ObjectMapper(); -	 -	/** -	 * The default constructor where the default pretty printer is disabled. -	 */ -	public JsonMapper() { -		this(false); -		 -	} -	 -	/** -	 * The constructor. -	 * @param prettyPrint enables or disables the default pretty printer -	 */ -	public JsonMapper(@NonNull boolean prettyPrint) { -		log.trace("Initializing JSON object-mapper ... "); -		mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true); -		mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true); -		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES , true); -		mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); -		mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY); -		mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY); -		if (prettyPrint) { -			mapper.enable(SerializationFeature.INDENT_OUTPUT); -		} -				 -		log.debug("JSON object-mapper initialized"); -		 -	} - -	 -	/* (non-Javadoc) -	 * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper() -	 */ -	public ObjectMapper getMapper() { -		return mapper; -		 -	} -	 -	 -	/* (non-Javadoc) -	 * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object) -	 */ -	@Override -	public String serialize(Object value) throws EAAFJsonMapperException { -		try { -			return mapper.writeValueAsString(value); -			 -		} catch (final JsonProcessingException e) { -			log.warn("JSON mapping FAILED with error: {}", e.getMessage()); -			throw new EAAFJsonMapperException(e.getMessage(), e); -			 -		} -		 -	} - -	/* (non-Javadoc) -	 * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, java.lang.Class) -	 */ -	@Override -	public <T> Object deserialize(String value, Class<T> clazz) throws EAAFJsonMapperException { -		try {					 -			if (clazz != null) { -				if (clazz.isAssignableFrom(TypeReference.class)) -					return mapper.readValue(value, clazz);					 -				else {				 -					final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); -					return mapper.readValue(value, javaType); -					 -				} -			 -			} else -				return mapper.readValue(value, Object.class); -			 -		} catch (final IOException e) { -			log.warn("JSON mapping FAILED with error: {}", e.getMessage()); -			throw new EAAFJsonMapperException(e.getMessage(), e); -			 -		} -		 -	} -	 -	@Override -	public <T> Object deserialize(InputStream is, Class<T> clazz) throws EAAFJsonMapperException { -		try {					 -			if (clazz != null) { -				if (clazz.isAssignableFrom(TypeReference.class)) -					return mapper.readValue(is, clazz);					 -				else {				 -					final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); -					return mapper.readValue(is, javaType); -					 -				} -			 -			} else -				return mapper.readValue(is, Object.class); -			 -		} catch (final IOException e) { -			log.warn("JSON mapping FAILED with error: {}", e.getMessage()); -			throw new EAAFJsonMapperException(e.getMessage(), e); -			 -		} -		 -	} -							 +  private static final Logger log = LoggerFactory.getLogger(JsonMapper.class); + +  private final ObjectMapper mapper = new ObjectMapper(); + +  /** +   * The default constructor where the default pretty printer is disabled. +   */ +  public JsonMapper() { +    this(false); + +  } + +  /** +   * The constructor. +   *  +   * @param prettyPrint enables or disables the default pretty printer +   */ +  public JsonMapper(@NonNull final boolean prettyPrint) { +    log.trace("Initializing JSON object-mapper ... "); +    mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true); +    mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true); +    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); +    mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); +    mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY); +    mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY); +    if (prettyPrint) { +      mapper.enable(SerializationFeature.INDENT_OUTPUT); +    } + +    log.debug("JSON object-mapper initialized"); + +  } + + +  /* +   * (non-Javadoc) +   *  +   * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper() +   */ +  public ObjectMapper getMapper() { +    return mapper; + +  } + + +  /* +   * (non-Javadoc) +   *  +   * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object) +   */ +  @Override +  public String serialize(final Object value) throws EaafJsonMapperException { +    try { +      return mapper.writeValueAsString(value); + +    } catch (final JsonProcessingException e) { +      log.warn("JSON mapping FAILED with error: {}", e.getMessage()); +      throw new EaafJsonMapperException(e.getMessage(), e); + +    } + +  } + +  /* +   * (non-Javadoc) +   *  +   * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, java.lang.Class) +   */ +  @Override +  public <T> Object deserialize(final String value, final Class<T> clazz) +      throws EaafJsonMapperException { +    try { +      if (clazz != null) { +        if (clazz.isAssignableFrom(TypeReference.class)) { +          return mapper.readValue(value, clazz); +        } else { +          final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); +          return mapper.readValue(value, javaType); + +        } + +      } else { +        return mapper.readValue(value, Object.class); +      } + +    } catch (final IOException e) { +      log.warn("JSON mapping FAILED with error: {}", e.getMessage()); +      throw new EaafJsonMapperException(e.getMessage(), e); + +    } + +  } + +  @Override +  public <T> Object deserialize(final InputStream is, final Class<T> clazz) +      throws EaafJsonMapperException { +    try { +      if (clazz != null) { +        if (clazz.isAssignableFrom(TypeReference.class)) { +          return mapper.readValue(is, clazz); +        } else { +          final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); +          return mapper.readValue(is, javaType); + +        } + +      } else { +        return mapper.readValue(is, Object.class); +      } + +    } catch (final IOException e) { +      log.warn("JSON mapping FAILED with error: {}", e.getMessage()); +      throw new EaafJsonMapperException(e.getMessage(), e); + +    } + +  } +  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index c07c6081..28106377 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -38,7 +38,7 @@ import com.fasterxml.jackson.core.JsonParseException;  import com.fasterxml.jackson.databind.JsonNode;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;  import at.gv.egiz.eaaf.core.impl.utils.FileUtils;  import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;  import at.gv.egiz.eaaf.core.impl.utils.X509Utils; @@ -46,375 +46,408 @@ import at.gv.egiz.eaaf.modules.auth.sl20.Constants;  import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;  import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;  import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;  @Service -public class JsonSecurityUtils implements IJOSETools{ -	private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); -	 -	@Autowired(required=true) IConfiguration authConfig; -	private Key signPrivKey = null; -	private X509Certificate[] signCertChain = null; -	 -	private Key encPrivKey = null; -	private X509Certificate[] encCertChain = null; -	 -	private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>(); -	 -	private static JsonMapper mapper = new JsonMapper(); -	 -	@PostConstruct -	protected void initalize() { -		log.info("Initialize SL2.0 authentication security constrains ... "); -		try { -			if (getKeyStoreFilePath() != null) { 			 -				final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),  -						getKeyStorePassword()); -				 -				//load signing key -				signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray()); -				final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias()); -				signCertChain = new X509Certificate[certChainSigning.length]; -				for (int i=0; i<certChainSigning.length; i++) { -					if (certChainSigning[i] instanceof X509Certificate) { -						signCertChain[i] = (X509Certificate)certChainSigning[i]; -					} else -						log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); -					 -				} -				 -				//load encryption key -				try { -					encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); -					if (encPrivKey != null) { -						final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias()); -						encCertChain = new X509Certificate[certChainEncryption.length]; -						for (int i=0; i<certChainEncryption.length; i++) { -							if (certChainEncryption[i] instanceof X509Certificate) { -								encCertChain[i] = (X509Certificate)certChainEncryption[i]; -							} else -								log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType()); -						}									 -					} else -						log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); -					 -				} catch (final Exception e) { -					log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), e); -			 -				} - -				//load trusted certificates -				trustedCerts = readCertsFromKeyStore(keyStore); -				 -				//some short validation -				if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) { -					log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); -					throw new SL20Exception("sl20.03", new Object[]{"Can NOT open private key for signing"}); -					 -				} -				 -				if (signCertChain == null || signCertChain.length == 0) { -					log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); -					throw new SL20Exception("sl20.03", new Object[]{"NO certificate for SL2.0 signing"}); -					 -				} -				 -				log.info("SL2.0 authentication security constrains initialized."); -				 -			} else -				log.info("NO SL2.0 authentication security configuration. Initialization was skipped"); -							 -		} catch ( final Exception e) { -			log.error("SL2.0 security constrains initialization FAILED.", e); -			 -		} -		 -	} -	 -	@Override -	public String createSignature(String payLoad) throws SLCommandoBuildException { -		try { -			final JsonWebSignature jws = new JsonWebSignature(); -			 -			//set payload -			jws.setPayload(payLoad); -		 -			//set basic header		 -			jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND); -		 -			//set signing information -			jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); -			jws.setKey(signPrivKey); -			 -			//TODO: -			jws.setCertificateChainHeaderValue(signCertChain); -			jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]); -		 -			return jws.getCompactSerialization(); -			 -		} catch (final JoseException e) { -			log.warn("Can NOT sign SL2.0 command.", e); -			throw new SLCommandoBuildException("Can NOT sign SL2.0 command.", e); -			 -		} -		 -	} -	 -	@Override -	public VerificationResult validateSignature(String serializedContent, KeyStore trustStore, -			AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException { -		final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore); -		return validateSignature(serializedContent, trustedCertificates , algconstraints); -		 -	} -	 -	@Override -	@NonNull -	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException { -		final JsonWebSignature jws = new JsonWebSignature(); -		//set payload -		jws.setCompactSerialization(serializedContent); -			 -		//set security constrains -		jws.setAlgorithmConstraints(constraints); -		 -		//load signinc certs -		Key selectedKey = null; -		final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); -		final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); -		if (x5cCerts != null) { -			log.debug("Found x509 certificate in JOSE header ... "); -			log.trace("Sorting received X509 certificates ... "); -			final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); -						 -			if (trustedCerts.contains(sortedX5cCerts.get(0))) { -				selectedKey = sortedX5cCerts.get(0).getPublicKey(); -				 -			} else { -				log.info("Can NOT find JOSE certificate in truststore."); -				try { -					log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); -					 -				} catch (final CertificateEncodingException e) { -					e.printStackTrace(); -					 -				} -				 -			} -			 -		} else if (StringUtils.isNotEmpty(x5t256)) { -			log.debug("Found x5t256 fingerprint in JOSE header .... "); -			final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); -			selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); -			 -		} else { -			throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); -			 -		} -				 -		if (selectedKey == null) { -			throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); -			 -		} -				 -		//set verification key -		jws.setKey(selectedKey); -				 -		//load payLoad		 -		return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature()) ; -		 -		 -	} - -	@Override -	@Nonnull -	public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception { -		try { -			final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST,    -					SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); -			 -			final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints); -			 -			if (!result.isValidSigned()) { -				log.info("JWS signature invalide. Stopping authentication process ..."); -				log.debug("Received JWS msg: " + serializedContent); -				throw new SL20SecurityException("JWS signature invalide."); -				 -			} -			 -			log.debug("SL2.0 commando signature validation sucessfull"); -			return result; -						 -		} catch (JoseException | JsonParseException e) { -			log.warn("SL2.0 commando signature validation FAILED", e); -			throw new SL20SecurityException(new Object[]{e.getMessage()}, e); -			 -		} catch (final IOException e) { -			log.warn("Decrypted SL2.0 result can not be parsed.", e); -			throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e); -			 -		} -					 -	} -	 - -	@Override -	public JsonNode decryptPayload(String compactSerialization) throws SL20Exception { -		try {			 -			final JsonWebEncryption receiverJwe = new JsonWebEncryption(); -		 -			//set security constrains -			receiverJwe.setAlgorithmConstraints( -					new AlgorithmConstraints(ConstraintType.WHITELIST, -							SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()]))); -			receiverJwe.setContentEncryptionAlgorithmConstraints( -					new AlgorithmConstraints(ConstraintType.WHITELIST, -							SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()]))); -		 -			//set payload -			receiverJwe.setCompactSerialization(compactSerialization); - -					 -			//validate key from header against key from config -			final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); -			final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); -			if (x5cCerts != null) { -				log.debug("Found x509 certificate in JOSE header ... "); -				log.trace("Sorting received X509 certificates ... "); -				final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); -		 -				if (!sortedX5cCerts.get(0).equals(encCertChain[0])) { -					log.info("Certificate from JOSE header does NOT match encryption certificate"); -					log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString()); -					 -					try { -						log.debug("Cert: " + Base64Utils.encode(sortedX5cCerts.get(0).getEncoded())); -					} catch (final CertificateEncodingException e) { -						e.printStackTrace(); -					} -					throw new SL20Exception("sl20.05", new Object[]{"Certificate from JOSE header does NOT match encryption certificate"}); -				} -				 -			} else if (StringUtils.isNotEmpty(x5t256)) { -				log.debug("Found x5t256 fingerprint in JOSE header .... "); -				final String certFingerPrint = X509Util.x5tS256(encCertChain[0]); -				if (!certFingerPrint.equals(x5t256)) { -					log.info("X5t256 from JOSE header does NOT match encryption certificate"); -					log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); -					throw new SL20Exception("sl20.05", new Object[]{"X5t256 from JOSE header does NOT match encryption certificate"}); -					 -				} -				 -			} else { -				log.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); -				throw new SLCommandoParserException("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); -				 -			} -						 -			//set key -			receiverJwe.setKey(encPrivKey); -			 -						 -			//decrypt payload			 -			return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); -			 -		} catch (final JoseException e) { -			log.warn("SL2.0 result decryption FAILED", e); -			throw new SL20SecurityException(new Object[]{e.getMessage()}, e); -			 -		} catch ( final JsonParseException e) { -			log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e); -			throw new SLCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e); -			 -		} catch (final IOException e) { -			log.warn("Decrypted SL2.0 result can not be parsed.", e); -			throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e); -		} -		 -	} -	 -	 -	 -	@Override -	public X509Certificate getEncryptionCertificate() { -		//TODO: maybe update after SL2.0 update on encryption certificate parts -		if (encCertChain !=null && encCertChain.length > 0) -			return encCertChain[0]; -		else -			return null; -	} -	 -	private String getKeyStoreFilePath() throws EAAFConfigurationException, MalformedURLException { -		return FileUtils.makeAbsoluteURL( -					authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH),  -					authConfig.getConfigurationRootDirectory()); -	} -	 -	private String getKeyStorePassword() { -		String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD); -		if (value != null) -			value = value.trim(); -		 -		return value; - -	} -	 -	private String getSigningKeyAlias() { -		String value = authConfig.getBasicConfiguration( -				Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim(); -		if (value != null) -			value = value.trim(); -		 -		return value; -	} -	 -	private String getSigningKeyPassword() { -		String value = authConfig.getBasicConfiguration( -				Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim(); -		if (value != null) -			value = value.trim(); -		 -		return value; -	} - -	private String getEncryptionKeyAlias() { -		String value = authConfig.getBasicConfiguration( -				Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS).trim(); -		if (value != null) -			value = value.trim(); -		 -		return value; -	} -	 -	private String getEncryptionKeyPassword() { -		String value = authConfig.getBasicConfiguration( -				Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD).trim(); -		if (value != null) -			value = value.trim(); -		 -		return value; -	} -	 -	@Nonnull -	private List<X509Certificate> readCertsFromKeyStore(@Nonnull KeyStore keyStore) throws KeyStoreException { -		final List<X509Certificate> result = new ArrayList<>(); -		 -		final Enumeration<String> aliases = keyStore.aliases(); -		while(aliases.hasMoreElements()) { -			final String el = aliases.nextElement(); -			log.trace("Process TrustStoreEntry: " + el); -			if (keyStore.isCertificateEntry(el)) { -				final Certificate cert = keyStore.getCertificate(el);  -				if (cert != null && cert instanceof X509Certificate) -					result.add((X509Certificate) cert); -				else -					log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); -				 -			} -		} -		 -		return Collections.unmodifiableList(result); -	} -	 +public class JsonSecurityUtils implements IJoseTools { +  private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); + +  @Autowired(required = true) +  IConfiguration authConfig; +  private Key signPrivKey = null; +  private X509Certificate[] signCertChain = null; + +  private Key encPrivKey = null; +  private X509Certificate[] encCertChain = null; + +  private List<X509Certificate> trustedCerts = new ArrayList<>(); + +  private static JsonMapper mapper = new JsonMapper(); + +  @PostConstruct +  protected void initalize() { +    log.info("Initialize SL2.0 authentication security constrains ... "); +    try { +      if (getKeyStoreFilePath() != null) { +        final KeyStore keyStore = +            KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), getKeyStorePassword()); + +        // load signing key +        signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray()); +        final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias()); +        signCertChain = new X509Certificate[certChainSigning.length]; +        for (int i = 0; i < certChainSigning.length; i++) { +          if (certChainSigning[i] instanceof X509Certificate) { +            signCertChain[i] = (X509Certificate) certChainSigning[i]; +          } else { +            log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); +          } + +        } + +        // load encryption key +        try { +          encPrivKey = +              keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); +          if (encPrivKey != null) { +            final Certificate[] certChainEncryption = +                keyStore.getCertificateChain(getEncryptionKeyAlias()); +            encCertChain = new X509Certificate[certChainEncryption.length]; +            for (int i = 0; i < certChainEncryption.length; i++) { +              if (certChainEncryption[i] instanceof X509Certificate) { +                encCertChain[i] = (X509Certificate) certChainEncryption[i]; +              } else { +                log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType()); +              } +            } +          } else { +            log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); +          } + +        } catch (final Exception e) { +          log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " +              + e.getMessage(), e); + +        } + +        // load trusted certificates +        trustedCerts = readCertsFromKeyStore(keyStore); + +        // some short validation +        if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) { +          log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); +          throw new SL20Exception("sl20.03", new Object[] {"Can NOT open private key for signing"}); + +        } + +        if (signCertChain == null || signCertChain.length == 0) { +          log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); +          throw new SL20Exception("sl20.03", new Object[] {"NO certificate for SL2.0 signing"}); + +        } + +        log.info("SL2.0 authentication security constrains initialized."); + +      } else { +        log.info("NO SL2.0 authentication security configuration. Initialization was skipped"); +      } + +    } catch (final Exception e) { +      log.error("SL2.0 security constrains initialization FAILED.", e); + +    } + +  } + +  @Override +  public String createSignature(final String payLoad) throws SlCommandoBuildException { +    try { +      final JsonWebSignature jws = new JsonWebSignature(); + +      // set payload +      jws.setPayload(payLoad); + +      // set basic header +      jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND); + +      // set signing information +      jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); +      jws.setKey(signPrivKey); + +      // TODO: +      jws.setCertificateChainHeaderValue(signCertChain); +      jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]); + +      return jws.getCompactSerialization(); + +    } catch (final JoseException e) { +      log.warn("Can NOT sign SL2.0 command.", e); +      throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e); + +    } + +  } + +  @Override +  public VerificationResult validateSignature(final String serializedContent, +      final KeyStore trustStore, final AlgorithmConstraints algconstraints) +      throws JoseException, IOException, KeyStoreException { +    final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore); +    return validateSignature(serializedContent, trustedCertificates, algconstraints); + +  } + +  @Override +  @NonNull +  public VerificationResult validateSignature(@Nonnull final String serializedContent, +      @Nonnull final List<X509Certificate> trustedCerts, +      @Nonnull final AlgorithmConstraints constraints) throws JoseException, IOException { +    final JsonWebSignature jws = new JsonWebSignature(); +    // set payload +    jws.setCompactSerialization(serializedContent); + +    // set security constrains +    jws.setAlgorithmConstraints(constraints); + +    // load signinc certs +    Key selectedKey = null; +    final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); +    final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +    if (x5cCerts != null) { +      log.debug("Found x509 certificate in JOSE header ... "); +      log.trace("Sorting received X509 certificates ... "); +      final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + +      if (trustedCerts.contains(sortedX5cCerts.get(0))) { +        selectedKey = sortedX5cCerts.get(0).getPublicKey(); + +      } else { +        log.info("Can NOT find JOSE certificate in truststore."); +        try { +          log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); + +        } catch (final CertificateEncodingException e) { +          e.printStackTrace(); + +        } + +      } + +    } else if (StringUtils.isNotEmpty(x5t256)) { +      log.debug("Found x5t256 fingerprint in JOSE header .... "); +      final X509VerificationKeyResolver x509VerificationKeyResolver = +          new X509VerificationKeyResolver(trustedCerts); +      selectedKey = +          x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); + +    } else { +      throw new JoseException( +          "JWS contains NO signature certificate or NO certificate fingerprint"); + +    } + +    if (selectedKey == null) { +      throw new JoseException( +          "Can NOT select verification key for JWS. Signature verification FAILED"); + +    } + +    // set verification key +    jws.setKey(selectedKey); + +    // load payLoad +    return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, +        jws.verifySignature()); + + +  } + +  @Override +  @Nonnull +  public VerificationResult validateSignature(@Nonnull final String serializedContent) +      throws SL20Exception { +    try { +      final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, +          SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING +              .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); + +      final VerificationResult result = +          validateSignature(serializedContent, trustedCerts, algConstraints); + +      if (!result.isValidSigned()) { +        log.info("JWS signature invalide. Stopping authentication process ..."); +        log.debug("Received JWS msg: " + serializedContent); +        throw new SL20SecurityException("JWS signature invalide."); + +      } + +      log.debug("SL2.0 commando signature validation sucessfull"); +      return result; + +    } catch (JoseException | JsonParseException e) { +      log.warn("SL2.0 commando signature validation FAILED", e); +      throw new SL20SecurityException(new Object[] {e.getMessage()}, e); + +    } catch (final IOException e) { +      log.warn("Decrypted SL2.0 result can not be parsed.", e); +      throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e); + +    } + +  } + + +  @Override +  public JsonNode decryptPayload(final String compactSerialization) throws SL20Exception { +    try { +      final JsonWebEncryption receiverJwe = new JsonWebEncryption(); + +      // set security constrains +      receiverJwe.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.WHITELIST, +          SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION +              .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()]))); +      receiverJwe.setContentEncryptionAlgorithmConstraints(new AlgorithmConstraints( +          ConstraintType.WHITELIST, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION +              .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()]))); + +      // set payload +      receiverJwe.setCompactSerialization(compactSerialization); + + +      // validate key from header against key from config +      final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); +      final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); +      if (x5cCerts != null) { +        log.debug("Found x509 certificate in JOSE header ... "); +        log.trace("Sorting received X509 certificates ... "); +        final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + +        if (!sortedX5cCerts.get(0).equals(encCertChain[0])) { +          log.info("Certificate from JOSE header does NOT match encryption certificate"); +          log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString()); + +          try { +            log.debug("Cert: " + Base64Utils.encode(sortedX5cCerts.get(0).getEncoded())); +          } catch (final CertificateEncodingException e) { +            e.printStackTrace(); +          } +          throw new SL20Exception("sl20.05", +              new Object[] {"Certificate from JOSE header does NOT match encryption certificate"}); +        } + +      } else if (StringUtils.isNotEmpty(x5t256)) { +        log.debug("Found x5t256 fingerprint in JOSE header .... "); +        final String certFingerPrint = X509Util.x5tS256(encCertChain[0]); +        if (!certFingerPrint.equals(x5t256)) { +          log.info("X5t256 from JOSE header does NOT match encryption certificate"); +          log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); +          throw new SL20Exception("sl20.05", +              new Object[] {"X5t256 from JOSE header does NOT match encryption certificate"}); + +        } + +      } else { +        log.info( +            "Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); +        throw new SlCommandoParserException( +            "Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); + +      } + +      // set key +      receiverJwe.setKey(encPrivKey); + + +      // decrypt payload +      return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); + +    } catch (final JoseException e) { +      log.warn("SL2.0 result decryption FAILED", e); +      throw new SL20SecurityException(new Object[] {e.getMessage()}, e); + +    } catch (final JsonParseException e) { +      log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e); +      throw new SlCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e); + +    } catch (final IOException e) { +      log.warn("Decrypted SL2.0 result can not be parsed.", e); +      throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e); +    } + +  } + + + +  @Override +  public X509Certificate getEncryptionCertificate() { +    // TODO: maybe update after SL2.0 update on encryption certificate parts +    if (encCertChain != null && encCertChain.length > 0) { +      return encCertChain[0]; +    } else { +      return null; +    } +  } + +  private String getKeyStoreFilePath() throws EaafConfigurationException, MalformedURLException { +    return FileUtils.makeAbsoluteUrl( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH), +        authConfig.getConfigurationRootDirectory()); +  } + +  private String getKeyStorePassword() { +    String value = +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD); +    if (value != null) { +      value = value.trim(); +    } + +    return value; + +  } + +  private String getSigningKeyAlias() { +    String value = authConfig +        .getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim(); +    if (value != null) { +      value = value.trim(); +    } + +    return value; +  } + +  private String getSigningKeyPassword() { +    String value = authConfig +        .getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim(); +    if (value != null) { +      value = value.trim(); +    } + +    return value; +  } + +  private String getEncryptionKeyAlias() { +    String value = authConfig +        .getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS).trim(); +    if (value != null) { +      value = value.trim(); +    } + +    return value; +  } + +  private String getEncryptionKeyPassword() { +    String value = authConfig +        .getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD) +        .trim(); +    if (value != null) { +      value = value.trim(); +    } + +    return value; +  } + +  @Nonnull +  private List<X509Certificate> readCertsFromKeyStore(@Nonnull final KeyStore keyStore) +      throws KeyStoreException { +    final List<X509Certificate> result = new ArrayList<>(); + +    final Enumeration<String> aliases = keyStore.aliases(); +    while (aliases.hasMoreElements()) { +      final String el = aliases.nextElement(); +      log.trace("Process TrustStoreEntry: " + el); +      if (keyStore.isCertificateEntry(el)) { +        final Certificate cert = keyStore.getCertificate(el); +        if (cert != null && cert instanceof X509Certificate) { +          result.add((X509Certificate) cert); +        } else { +          log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); +        } + +      } +    } + +    return Collections.unmodifiableList(result); +  } +  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java index 06c36cff..5a8be243 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java @@ -8,234 +8,273 @@ import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;  import org.jose4j.jws.AlgorithmIdentifiers;  public class SL20Constants { -	public static final int CURRENT_SL20_VERSION = 10; -	 -	//http binding parameters -	public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; -	public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; -	 -	public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl"; -	public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; -	 -	public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType"; -	public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA"; -	public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp"; -	 -	public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation"; -	 -	 -	//******************************************************************************************* -	//JSON signing and encryption headers -	public static final String JSON_ALGORITHM = "alg"; -	public static final String JSON_CONTENTTYPE = "cty"; -	public static final String JSON_X509_CERTIFICATE = "x5c"; -	public static final String JSON_X509_FINGERPRINT = "x5t#S256"; -	public static final String JSON_ENCRYPTION_PAYLOAD = "enc"; -	 -	public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256; -	public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512; -	public static final String JSON_ALGORITHM_SIGNING_ES256 = AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256; -	public static final String JSON_ALGORITHM_SIGNING_ES512 = AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512; -	public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256; -	public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512; - -	public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Arrays.asList( -			JSON_ALGORITHM_SIGNING_RS256, -			JSON_ALGORITHM_SIGNING_RS512, -			JSON_ALGORITHM_SIGNING_ES256, -			JSON_ALGORITHM_SIGNING_ES512, -			JSON_ALGORITHM_SIGNING_PS256, -			JSON_ALGORITHM_SIGNING_PS512 -			); -	 -	public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP; -	public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = KeyManagementAlgorithmIdentifiers.RSA_OAEP_256; -	 -	public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Arrays.asList( -			JSON_ALGORITHM_ENC_KEY_RSAOAEP, -			JSON_ALGORITHM_ENC_KEY_RSAOAEP256 -			); -	 -	public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256; -	public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512; -	public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = ContentEncryptionAlgorithmIdentifiers.AES_128_GCM; -	public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = ContentEncryptionAlgorithmIdentifiers.AES_256_GCM; -	 -	public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Arrays.asList( -			JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, -			JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512, -			JSON_ALGORITHM_ENC_PAYLOAD_A128GCM, -			JSON_ALGORITHM_ENC_PAYLOAD_A256GCM -		); -	 -	 -	//********************************************************************************************* -	//Object identifier for generic transport container -	public static final String SL20_CONTENTTYPE_SIGNED_COMMAND ="application/sl2.0;command"; -	public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT ="application/sl2.0;result"; -	 -	public static final String SL20_VERSION = "v"; -	public static final String SL20_REQID = "reqID"; -	public static final String SL20_RESPID = "respID"; -	public static final String SL20_INRESPTO = "inResponseTo"; -	public static final String SL20_TRANSACTIONID = "transactionID"; -	public static final String SL20_PAYLOAD = "payload"; -	public static final String SL20_SIGNEDPAYLOAD = "signedPayload"; -	 -	//Generic Object identifier for commands -	public static final String SL20_COMMAND_CONTAINER_NAME = "name"; -	public static final String SL20_COMMAND_CONTAINER_PARAMS = "params"; -	public static final String SL20_COMMAND_CONTAINER_RESULT = "result"; -	public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult"; -		 -	//COMMAND Object identifier -	public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect"; -	public static final String SL20_COMMAND_IDENTIFIER_CALL = "call"; -	public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error"; -	@Deprecated public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; -	public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent"; -	//public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig"; -	 -	public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate"; -	public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES"; -	 -	 -	public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey"; -	public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert"; -	 -	public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword"; -	public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth"; -	public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor"; -	 -	//*****COMMAND parameter identifier****** -	//general Identifier -	public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value"; -	public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key";	 -	public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl"; -	public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc"; -	public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc"; -	 -	//Redirect command -	public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url"; -	public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command"; -	public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand"; -	public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect";		 -	 -	//Call command -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL; -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method"; -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get"; -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post"; -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID";	 -	public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams"; - -	//error command -	public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode"; -	public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage"; -	 -	//qualified eID command -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID"; -	public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;  -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE"; -	public static final String SL20_COMMAND_PARAM_EID_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; -	public static final String SL20_COMMAND_PARAM_EID_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK"; -	public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL"; -	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; -	 -	public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID"; -	public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent"; -	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS"; -	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ"; -	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent"; -	 -	//qualified Signature comamnd -//	public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -//	public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; -	 -	 -	//getCertificate -	public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId"; -	public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; -	public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; -	public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c"; -	 -	//createCAdES Signture -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId";	 -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel";	 -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature"; -	 -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L"; -	public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A"; -	 -	 -	 -	//create binding key command -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword";	 -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; -	 -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1"; -	 -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth"; -	 -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert"; -	public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass"; -		 -	 -	//store binding certificate command -	public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c"; -	public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success"; -	public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK"; -	 -	// Username and password authentication -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg"; -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain"; -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2"; -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;	 -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID; -	public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD; -	 -	//JWS Token authentication -	public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce"; -	public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData"; -	public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl"; -	public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;	 -	public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE; -	 -	//QR-Code authentication -	public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode"; -	public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -	 +  public static final int CURRENT_SL20_VERSION = 10; + +  // http binding parameters +  public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; +  public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; + +  public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl"; +  public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; + +  public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType"; +  public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA"; +  public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp"; + +  public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation"; + + +  // ******************************************************************************************* +  // JSON signing and encryption headers +  public static final String JSON_ALGORITHM = "alg"; +  public static final String JSON_CONTENTTYPE = "cty"; +  public static final String JSON_X509_CERTIFICATE = "x5c"; +  public static final String JSON_X509_FINGERPRINT = "x5t#S256"; +  public static final String JSON_ENCRYPTION_PAYLOAD = "enc"; + +  public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256; +  public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512; +  public static final String JSON_ALGORITHM_SIGNING_ES256 = +      AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256; +  public static final String JSON_ALGORITHM_SIGNING_ES512 = +      AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512; +  public static final String JSON_ALGORITHM_SIGNING_PS256 = +      AlgorithmIdentifiers.RSA_PSS_USING_SHA256; +  public static final String JSON_ALGORITHM_SIGNING_PS512 = +      AlgorithmIdentifiers.RSA_PSS_USING_SHA512; + +  public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Arrays.asList( +      JSON_ALGORITHM_SIGNING_RS256, JSON_ALGORITHM_SIGNING_RS512, JSON_ALGORITHM_SIGNING_ES256, +      JSON_ALGORITHM_SIGNING_ES512, JSON_ALGORITHM_SIGNING_PS256, JSON_ALGORITHM_SIGNING_PS512); + +  public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = +      KeyManagementAlgorithmIdentifiers.RSA_OAEP; +  public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = +      KeyManagementAlgorithmIdentifiers.RSA_OAEP_256; + +  public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = +      Arrays.asList(JSON_ALGORITHM_ENC_KEY_RSAOAEP, JSON_ALGORITHM_ENC_KEY_RSAOAEP256); + +  public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = +      ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256; +  public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = +      ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512; +  public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = +      ContentEncryptionAlgorithmIdentifiers.AES_128_GCM; +  public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = +      ContentEncryptionAlgorithmIdentifiers.AES_256_GCM; + +  public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Arrays.asList( +      JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512, +      JSON_ALGORITHM_ENC_PAYLOAD_A128GCM, JSON_ALGORITHM_ENC_PAYLOAD_A256GCM); + + +  // ********************************************************************************************* +  // Object identifier for generic transport container +  public static final String SL20_CONTENTTYPE_SIGNED_COMMAND = "application/sl2.0;command"; +  public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT = "application/sl2.0;result"; + +  public static final String SL20_VERSION = "v"; +  public static final String SL20_REQID = "reqID"; +  public static final String SL20_RESPID = "respID"; +  public static final String SL20_INRESPTO = "inResponseTo"; +  public static final String SL20_TRANSACTIONID = "transactionID"; +  public static final String SL20_PAYLOAD = "payload"; +  public static final String SL20_SIGNEDPAYLOAD = "signedPayload"; + +  // Generic Object identifier for commands +  public static final String SL20_COMMAND_CONTAINER_NAME = "name"; +  public static final String SL20_COMMAND_CONTAINER_PARAMS = "params"; +  public static final String SL20_COMMAND_CONTAINER_RESULT = "result"; +  public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult"; + +  // COMMAND Object identifier +  public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect"; +  public static final String SL20_COMMAND_IDENTIFIER_CALL = "call"; +  public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error"; +  @Deprecated +  public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; +  public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent"; +  // public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig"; + +  public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate"; +  public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES"; + + +  public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey"; +  public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert"; + +  public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword"; +  public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth"; +  public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor"; + +  // *****COMMAND parameter identifier****** +  // general Identifier +  public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value"; +  public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key"; +  public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl"; +  public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc"; +  public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc"; + +  // Redirect command +  public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url"; +  public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command"; +  public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand"; +  public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect"; + +  // Call command +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = +      SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL; +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method"; +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get"; +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post"; +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = +      "includeTransactionID"; +  public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams"; + +  // error command +  public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode"; +  public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage"; + +  // qualified eID command +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID"; +  public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = +      "MANDATE-REFERENCE-VALUE"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE"; +  public static final String SL20_COMMAND_PARAM_EID_X5CENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; +  public static final String SL20_COMMAND_PARAM_EID_JWKCENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK"; +  public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL"; +  @Deprecated +  public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; + +  public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID"; +  public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent"; +  public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS"; +  public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ"; +  public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent"; + +  // qualified Signature comamnd +  // public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = +  // SL20_COMMAND_PARAM_GENERAL_DATAURL; +  // public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = +  // SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + + +  // getCertificate +  public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId"; +  public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; +  public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; +  public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c"; + +  // createCAdES Signture +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = +      "padesComatibility"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = +      "excludedByteRange"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature"; + +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L"; +  public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A"; + + + +  // create binding key command +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = +      "reqUserPassword"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1"; + +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = +      "useSecureElement"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = +      "needUserAuth"; + +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = +      "attCert"; +  public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass"; + + +  // store binding certificate command +  public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c"; +  public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success"; +  public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK"; + +  // Username and password authentication +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg"; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain"; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2"; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = +      SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = +      SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID; +  public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = +      SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD; + +  // JWS Token authentication +  public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce"; +  public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData"; +  public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl"; +  public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = +      SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE; + +  // QR-Code authentication +  public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode"; +  public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = +      SL20_COMMAND_PARAM_GENERAL_DATAURL; +  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java index 4d8cabb7..be306b69 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java @@ -3,61 +3,61 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils;  import java.io.IOException;  import java.io.StringWriter;  import java.net.URISyntaxException; -  import javax.annotation.Nonnull;  import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -  import org.apache.http.client.utils.URIBuilder;  import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.http.MediaType; -  import com.fasterxml.jackson.databind.JsonNode;  public class SL20HttpBindingUtils { -	private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); -	 -	/** -	 * Write SL2.0 response into http-response object  -	 *  -	 * @param httpReq Current http request -	 * @param httpResp Current http response -	 * @param sl20Forward SL2.0 command that should be written to response -	 * @param redirectURL SL2.0 redirect URL in case of SL2.0 redirect command and no native client (see SL2.0 specification) -	 * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command and no native client (see SL2.0 specification) -	 * @throws IOException -	 * @throws URISyntaxException -	 */ -	public static void writeIntoResponse(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp,  -			@Nonnull JsonNode sl20Forward, @Nullable String redirectURL, -			@Nonnull int httpCodeRedirect) throws IOException, URISyntaxException { -		//forward SL2.0 command -		httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); -		 -		if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  -				httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { -			log.debug("Client request containts 'native client' header ... ");												 -			final StringWriter writer = new StringWriter(); -			writer.write(sl20Forward.toString());						 -			final byte[] content = writer.toString().getBytes("UTF-8"); -			httpResp.setStatus(HttpServletResponse.SC_OK); -			httpResp.setContentLength(content.length); -			httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);						 -			httpResp.getOutputStream().write(content); -											 -		} else { -			log.debug("Client request containts is no native client ... "); -			final URIBuilder clientRedirectURI = new URIBuilder(redirectURL); -			clientRedirectURI.addParameter( -					SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,  -					Base64Url.encode(sl20Forward.toString().getBytes())); -			httpResp.setStatus(httpCodeRedirect); -			httpResp.setHeader("Location", clientRedirectURI.build().toString()); -			 -		} -		 -	} +  private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); + +  /** +   * Write SL2.0 response into http-response object +   * +   * @param httpReq Current http request +   * @param httpResp Current http response +   * @param sl20Forward SL2.0 command that should be written to response +   * @param redirectUrl SL2.0 redirect URL in case of SL2.0 redirect command and no native client +   *        (see SL2.0 specification) +   * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command and no native +   *        client (see SL2.0 specification) +   * @throws IOException In case of an IO error +   * @throws URISyntaxException In case of a wrong URL +   */ +  public static void writeIntoResponse(@Nonnull final HttpServletRequest httpReq, +      @Nonnull final HttpServletResponse httpResp, @Nonnull final JsonNode sl20Forward, +      @Nullable final String redirectUrl, @Nonnull final int httpCodeRedirect) +      throws IOException, URISyntaxException { +    // forward SL2.0 command +    httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); + +    if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null +        && httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) +            .equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { +      log.debug("Client request containts 'native client' header ... "); +      final StringWriter writer = new StringWriter(); +      writer.write(sl20Forward.toString()); +      final byte[] content = writer.toString().getBytes("UTF-8"); +      httpResp.setStatus(HttpServletResponse.SC_OK); +      httpResp.setContentLength(content.length); +      httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); +      httpResp.getOutputStream().write(content); + +    } else { +      log.debug("Client request containts is no native client ... "); +      final URIBuilder clientRedirectUri = new URIBuilder(redirectUrl); +      clientRedirectUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, +          Base64Url.encode(sl20Forward.toString().getBytes())); +      httpResp.setStatus(httpCodeRedirect); +      httpResp.setHeader("Location", clientRedirectUri.build().toString()); + +    } + +  }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java deleted file mode 100644 index ba069ac7..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java +++ /dev/null @@ -1,640 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; - -public class SL20JSONBuilderUtils { - -	private static JsonMapper mapper = new JsonMapper(); -	 -	/** -	 * Create command request -	 * @param name -	 * @param params -	 * @throws SLCommandoBuildException -	 * @return -	 */ -	public static ObjectNode createCommand(String name, ObjectNode params) throws SLCommandoBuildException { -		 -		final ObjectNode command = mapper.getMapper().createObjectNode(); -		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); -		addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);				 -		return command; -		 -	} -	 -	/** -	 * Create signed command request -	 *  -	 * @param name -	 * @param params -	 * @param signer -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static String createSignedCommand(String name, ObjectNode params, IJOSETools signer) throws SLCommandoBuildException { -		final ObjectNode command = mapper.getMapper().createObjectNode();	 -		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); -		addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);		 -		return signer.createSignature(command.toString()); -				 -	} - - -	/** -	 * Create encrypted command result -	 *  -	 * @param result -	 * @param encrypter -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static String createEncryptedCommandoResult(ObjectNode result, JsonSecurityUtils encrypter) throws SLCommandoBuildException { -		//TODO: add real implementation -		//create header and footer -		final String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); -		final String payLoad = result.toString(); -		final String dummyFooter = createJsonSignedFooter(encrypter); -		 -		return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." -			+ Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "." -			+ Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); -	 -	} -	 -	 -	/** -	 * Create command result -	 *  -	 * @param name -	 * @param result -	 * @param encryptedResult -	 * @throws SLCommandoBuildException -	 * @return -	 */ -	public static ObjectNode createCommandResponse(String name, ObjectNode result, String encryptedResult) throws SLCommandoBuildException { -		final ObjectNode command = mapper.getMapper().createObjectNode(); -		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);		 -		addOnlyOnceOfTwo(command,  -				SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,  -				result, encryptedResult);			 -		return command; -		 -	} -	 -	/** -	 * Create command result -	 *  -	 * @param name -	 * @param result -	 * @param encryptedResult -	 * @throws SLCommandoBuildException -	 * @return -	 */ -	public static String createSignedCommandResponse(String name, ObjectNode result, String encryptedResult, JsonSecurityUtils signer) throws SLCommandoBuildException { -		final ObjectNode command = mapper.getMapper().createObjectNode(); -		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);		 -		addOnlyOnceOfTwo(command,  -				SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,  -				result, encryptedResult);	 -		final String encodedCommand = command.toString();  -		 -		//TODO: add real implementation -		//create header and footer -		final String dummyHeader = createJsonSignedHeader(signer).toString(); -		final String dummyFooter = createJsonSignedFooter(signer); -		 -		return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." -				+ Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "." -				+ Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); -				 -	} -	 -	/** -	 * Create parameters for Redirect command -	 *   -	 * @param url -	 * @param command -	 * @param signedCommand -	 * @param ipcRedirect -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createRedirectCommandParameters(String url, ObjectNode command, ObjectNode signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{ -		final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); -		addOnlyOnceOfTwo(redirectReqParams,  -				SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND,  -				command, signedCommand);		 -		addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false); -		addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false); -		return redirectReqParams; -		 -	} -	 -	/** -	 * Create parameters for Call command -	 *  -	 * @param url -	 * @param method -	 * @param includeTransactionId -	 * @param reqParameters -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map<String, String> reqParameters) throws SLCommandoBuildException { -		final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); -		addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true); -		addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true); -		addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false); -		addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters);		 -		return callReqParams; -		 -	} -	 -	/** -	 * Create result for Error command -	 *  -	 * @param errorCode -	 * @param errorMsg -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true); -		return result; -		 -	} -	 -	/** -	 * Create parameters for qualifiedeID command -	 *  -	 * @param consentTemplateId Identifier of the template that is used for consent visualization -	 * @param consent Consent that has to be signed by user -	 * @param dataUrl -	 * @param additionalReqParameters -	 * @param x5cEnc -	 * @return -	 * @throws CertificateEncodingException -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createQualifiedeEIDConsent(String consentTemplateId, byte[] consent,  String dataUrl,  -			X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { -		final ObjectNode params = mapper.getMapper().createObjectNode(); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true); -		addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true);		 -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);		 -		return params; - -	} -	 -	 -	/** -	 * Create parameters for qualifiedeID command -	 *  -	 * @param authBlockId -	 * @param dataUrl -	 * @param additionalReqParameters -	 * @param x5cEnc -	 * @return -	 * @throws CertificateEncodingException -	 * @throws SLCommandoBuildException -	 */ -	@Deprecated -	public static ObjectNode createQualifiedeIDCommandParameters(String authBlockId,  String dataUrl,  -			Map<String, String> additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { -		final ObjectNode params = mapper.getMapper().createObjectNode(); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); -		addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);		 -		return params; - -	} -	 -	/** -	 * Create result for qualifiedeID command -	 *  -	 * @param idl -	 * @param authBlock -	 * @param ccsURL -	 * @param LoA -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true); -		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, LoA, true); -		return result; -		 -	} -	 -	 -	/** -	 * Create Binding-Key command parameters -	 *  -	 * @param kontoId -	 * @param subjectName -	 * @param keySize -	 * @param keyAlg -	 * @param policies -	 * @param dataUrl -	 * @param x5cVdaTrust -	 * @param reqUserPassword -	 * @param x5cEnc -	 * @return -	 * @throws SLCommandoBuildException -	 * @throws CertificateEncodingException -	 */ -	public static ObjectNode createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg,  -			Map<String, String> policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { -		final ObjectNode params = mapper.getMapper().createObjectNode(); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true); -		addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true);		 -		addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies);		 -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, false); -		addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, false); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false); -		return params; -		 -	} -	 -	/** -	 * Create Binding-Key command result -	 *  -	 * @param appId -	 * @param csr -	 * @param attCert -	 * @param password -	 * @return -	 * @throws SLCommandoBuildException -	 * @throws CertificateEncodingException -	 */ -	public static ObjectNode createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true); -		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true); -		addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false); -		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false);		 -		return result; -		 -	} -	 -	/** -	 * Create Store Binding-Certificate command parameters -	 *  -	 * @param cert -	 * @param dataUrl -	 * @return -	 * @throws CertificateEncodingException -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException { -		final ObjectNode params = mapper.getMapper().createObjectNode(); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true);		 -		return params; -		 -	} -	 -	/** -	 * Create Store Binding-Certificate command result -	 *  -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS,  -				SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true); -		return result; -		 -	} -	 -	 -	/** -	 * Create idAndPassword command parameters -	 *  -	 * @param keyAlg -	 * @param dataUrl -	 * @param x5cEnc -	 * @return -	 * @throws SLCommandoBuildException -	 * @throws CertificateEncodingException -	 */ -	public static ObjectNode createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { -		final ObjectNode params = mapper.getMapper().createObjectNode();		 -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true); -		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false); -		return params; -		 -	} -	 -	/** -	 * Create idAndPassword command result -	 *  -	 * @param kontoId -	 * @param password -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true); -		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true);		 -		return result; -		 -	} -	 -	/** -	 * Create JWS Token Authentication command -	 *  -	 * @param nonce -	 * @param dataUrl -	 * @param displayData -	 * @param displayUrl -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createJwsTokenAuthCommandParams(String nonce, String dataUrl, List<String> displayData, List<String> displayUrl) throws SLCommandoBuildException { -		final ObjectNode params = mapper.getMapper().createObjectNode(); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true); -		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true); -		addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData); -		addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl);		 -		return params; -		 -	} -	 -	/** -	 * Create JWS Token Authentication command result -	 *  -	 * @param nonce -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException { -		final ObjectNode result = mapper.getMapper().createObjectNode(); -		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true);		 -		return result; -		 -	} -	 -	 -	/** -	 * Create Generic Request Container -	 *  -	 * @param reqId -	 * @param transactionId -	 * @param payLoad -	 * @param signedPayload -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static ObjectNode createGenericRequest(String reqId, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { -		final ObjectNode req = mapper.getMapper().createObjectNode(); -		addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); -		addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true); -		addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);		 -		addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,  -				payLoad, signedPayload);		 -		return req; -		 -	} -	 -	/** -	 * Create Generic Response Container -	 *  -	 * @param respId -	 * @param inResponseTo -	 * @param transactionId -	 * @param payLoad -	 * @param signedPayload -	 * @return -	 * @throws SLCommandoBuildException -	 */ -	public static final ObjectNode createGenericResponse(String respId, String inResponseTo, String transactionId,  -			ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException {		 -		final ObjectNode req = mapper.getMapper().createObjectNode(); -		addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); -		addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true); -		addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false); -		addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);		 -		addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,  -				payLoad, signedPayload);		 -		return req; -		 -	} -	 -	/** -	 * Add one element of two possible elements <br> -	 * This method adds either the first element or the second element to parent JSON, but never both.   -	 *  -	 * @param parent Parent JSON element -	 * @param firstKeyId first element Id -	 * @param secondKeyId second element Id -	 * @param first first element -	 * @param second second element -	 * @throws SLCommandoBuildException -	 */ -	public static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, String second) throws SLCommandoBuildException { -		if (first == null && (second == null  || second.isEmpty())) -			throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); -		 -		else if (first != null && second != null) -			throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); -		 -		else if (first != null) -			parent.set(firstKeyId, first); -		 -		else if (second != null && !second.isEmpty()) -			parent.put(secondKeyId, second); -		 -		else -			throw new SLCommandoBuildException("Internal build error"); -	} -	 -	 -	 -	//TODO!!!! -	private static ObjectNode createJsonSignedHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { -		final ObjectNode header = mapper.getMapper().createObjectNode(); -		addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true); -		addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true);		 -		addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT)); -		 -		return header; -	} -	 -	//TODO!!!! -	private static ObjectNode createJsonEncryptionHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { -		final ObjectNode header = mapper.getMapper().createObjectNode(); -		addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true); -		addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true); -		addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true);		 -		addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true); -		 -		return header; -	} -	 -	//TODO!!!! -	private static String createJsonSignedFooter(JsonSecurityUtils signer) {		 -		return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" +  -				"  AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" +  -				"  BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" +  -				"  0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" +  -				"  hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" +  -				"  p0igcN_IoypGlUPQGe77Rw"; -	} - -	 -	 -	private static void addArrayOfStrings(ObjectNode parent, String keyId, List<String> values) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId);		 -		if (values != null) { -			final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); -			parent.set(keyId, callReqParamsArray  ); -			for(final String el : values) -				callReqParamsArray.add(el); -			 -		} -	} -	 -	 -	private static void addArrayOfStringElements(ObjectNode parent, String keyId, Map<String, String> keyValuePairs) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId);		 -		if (keyValuePairs != null) {			 -			final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); -			parent.set(keyId, callReqParamsArray); -			 -			for(final Entry<String, String> el : keyValuePairs.entrySet()) { -				final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); -				callReqParams.put(el.getKey(), el.getValue()); -				callReqParamsArray.add(callReqParams); -				 -			} -		} -	} -	 -	private static void addSingleCertificateElement(ObjectNode parent, String keyId, X509Certificate cert, boolean isRequired) throws CertificateEncodingException, SLCommandoBuildException { -		if (cert != null) -			addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired); -		 -		else if (isRequired) -			throw new SLCommandoBuildException(keyId + " is marked as REQUIRED"); -		 -	} -	 -	 -	 -	private static void addSingleByteElement(ObjectNode parent, String keyId, byte[] value, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && value == null) -			throw new SLCommandoBuildException(keyId + " has NULL value"); -		 -		else if (value != null) -			parent.put(keyId, Base64.getEncoder().encodeToString(value)); -		 -	} -	 -	private static void addSingleBooleanElement(ObjectNode parent, String keyId, Boolean value, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && value == null) -			throw new SLCommandoBuildException(keyId + " has a NULL value"); -			 -		else if (value != null) -			parent.put(keyId, value); -		 -	} -	 -	private static void addSingleNumberElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && value == null) -			throw new SLCommandoBuildException(keyId + " has a NULL value"); -		 -		else if (value != null) -			parent.put(keyId, value);; -		 -	} -	 -	private static void addSingleStringElement(ObjectNode parent, String keyId, String value, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && (value == null || value.isEmpty())) -			throw new SLCommandoBuildException(keyId + " has an empty value"); -		 -		else if (value != null && !value.isEmpty()) -			parent.put(keyId, value); -		 -	} -	 -	private static void addSingleIntegerElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && value == null) -			throw new SLCommandoBuildException(keyId + " has an empty value"); -		 -		else if (value != null) -			parent.put(keyId, value); -		 -	} -	 -	private static void addSingleJSONElement(ObjectNode parent, String keyId, ObjectNode element, boolean isRequired) throws SLCommandoBuildException { -		validateParentAndKey(parent, keyId); -		 -		if (isRequired && element == null) -			throw new SLCommandoBuildException("No commando name included"); -		 -		else if (element != null) -			parent.set(keyId, element); -				 -	} -		 -	private static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, ObjectNode second) throws SLCommandoBuildException { -		if (first == null && second == null) -			throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); -		 -		else if (first != null && second != null) -			throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); -		 -		else if (first != null) -			parent.set(firstKeyId, first); -		 -		else if (second != null) -			parent.set(secondKeyId, second); -		 -		else -			throw new SLCommandoBuildException("Internal build error"); -	} -	 -	private static void validateParentAndKey(ObjectNode parent, String keyId) throws SLCommandoBuildException { -		if (parent == null) -			throw new SLCommandoBuildException("NO parent JSON element"); -		 -		if (keyId == null || keyId.isEmpty()) -			throw new SLCommandoBuildException("NO JSON element identifier"); -	} -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java deleted file mode 100644 index 314dde17..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java +++ /dev/null @@ -1,368 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.util.EntityUtils; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; - -public class SL20JSONExtractorUtils { -	private static final Logger log = LoggerFactory.getLogger(SL20JSONExtractorUtils.class); -	private static JsonMapper mapper = new JsonMapper(); -	 -	 -	/** -	 * Extract String value from JSON  -	 *  -	 * @param input -	 * @param keyID -	 * @param isRequired -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static String getStringValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { -		try { -			final JsonNode internal = getAndCheck(input, keyID, isRequired); -		 -			if (internal != null) -				return internal.asText(); -			else -				return null; -			 -		} catch (final SLCommandoParserException e) { -			throw e; -			 -		} catch (final Exception e) { -			throw new SLCommandoParserException("Can not extract String value with keyId: " + keyID, e); -			 -		}		 -	} -	 -	/** -	 * Extract Boolean value from JSON  -	 *  -	 * @param input -	 * @param keyID -	 * @param isRequired -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static boolean getBooleanValue(ObjectNode input, String keyID, boolean isRequired, boolean defaultValue) throws SLCommandoParserException { -		try { -			final JsonNode internal = getAndCheck(input, keyID, isRequired); -				 -			if (internal != null) -				return internal.asBoolean(); -			else -				return defaultValue; -			 -		} catch (final SLCommandoParserException e) { -			throw e; -			 -		} catch (final Exception e) { -			throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); -			 -		}		 -	} -	 -	/** -	 * Extract JSONObject value from JSON  -	 *  -	 * @param input -	 * @param keyID -	 * @param isRequired -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static JsonNode getJSONObjectValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { -		try { -			final JsonNode internal = getAndCheck(input, keyID, isRequired); -				 -			if (internal != null) -				return internal; -			else -				return null; -			 -		} catch (final SLCommandoParserException e) { -			throw e; -			 -		} catch (final Exception e) { -			throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); -			 -		}		 -	} -	 -	/** -	 * Extract a List of String elements from a JSON element -	 *  -	 * @param input -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static List<String> getListOfStringElements(JsonNode input) throws SLCommandoParserException { -		final List<String> result = new ArrayList<String>(); -		if (input != null) { -			if (input.isArray()) {			 -				final Iterator<JsonNode> arrayIterator = input.iterator(); -				while(arrayIterator.hasNext()) { -					final JsonNode next = arrayIterator.next(); -					if (next.isTextual()) -						result.add(next.asText());											 -				} -				 -			} else if (input.isTextual()) { -				result.add(input.asText()); -				 -			} else { -				log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); -				throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); -				 -			} -		} -		 -		return result; -	} -	 -	/** -	 * Extract Map of Key/Value pairs from a JSON Element -	 *  -	 * @param input parent JSON object -	 * @param keyID KeyId of the child that should be parsed -	 * @param isRequired -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static Map<String, String> getMapOfStringElements(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { -		final JsonNode internal = getAndCheck(input, keyID, isRequired); -		return getMapOfStringElements(internal); -		 -	} -	 -	/** -	 * Extract Map of Key/Value pairs from a JSON Element  -	 *  -	 * @param input -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static Map<String, String> getMapOfStringElements(JsonNode input) throws SLCommandoParserException {		 -		final Map<String, String> result = new HashMap<String, String>(); - -		if (input != null) { -			if (input.isArray()) {						 -				final Iterator<JsonNode> arrayIterator = input.iterator(); -				while(arrayIterator.hasNext()) { -					final JsonNode next = arrayIterator.next(); -					final Iterator<Entry<String, JsonNode>> entry = next.fields(); -					entitySetToMap(result, entry); -										 -				} -				 -			} else if (input.isObject()) { -				final Iterator<Entry<String, JsonNode>> objectKeys = input.fields(); -				entitySetToMap(result, objectKeys); -				 -			} else -				throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); -			 -		} -		 -		return result; -	} -	 -	private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonNode>> entry) { -		while (entry.hasNext()) { -			final Entry<String, JsonNode> el = entry.next(); -			if (result.containsKey(el.getKey())) -				log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... "); -			 -			result.put(el.getKey(), el.getValue().asText()); -		 -		} -		 -	} -	 -	 -	public static JsonNode extractSL20Result(JsonNode command, IJOSETools decrypter, boolean mustBeEncrypted) throws SL20Exception { -		final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); -		final JsonNode encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); -		 -		if (result == null && encryptedResult == null) -			throw new SLCommandoParserException("NO result OR encryptedResult FOUND.");		 -				 -		else if (encryptedResult == null && mustBeEncrypted) -			throw new SLCommandoParserException("result MUST be encrypted."); -				 -		else if (encryptedResult != null && encryptedResult.isTextual()) { -			try { -				return decrypter.decryptPayload(encryptedResult.asText()); -				 -			} catch (final Exception e) { -				log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); -				if (!mustBeEncrypted) { -					log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible"); - -					//dummy code -					try { -						final String[] signedPayload = encryptedResult.toString().split("\\."); -						final JsonNode payLoad = mapper.getMapper().readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); -						return payLoad; -						 -					} catch (final Exception e1) { -						log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); -						throw new SL20Exception(e.getMessage(), null, e); -						 -					} -					 -				} else -					throw e;	 -				 -			} - -		} else if (result != null) { -				return result; - -		} else -			throw new SLCommandoParserException("Internal build error"); -		 -		 -	} -		 -	/** -	 * Extract payLoad from generic transport container -	 *  -	 * @param container -	 * @param joseTools -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static VerificationResult extractSL20PayLoad(JsonNode container, IJOSETools joseTools, boolean mustBeSigned) throws SL20Exception { -		 -		final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); -		final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); -		 -		if (mustBeSigned && joseTools == null) -			throw new SLCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); -					 -		if (sl20Payload == null && sl20SignedPayload == null) -			throw new SLCommandoParserException("NO payLoad OR signedPayload FOUND.");		 -		 -		else if (sl20SignedPayload == null && mustBeSigned) -			throw new SLCommandoParserException("payLoad MUST be signed."); - -		else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) {	 -			return joseTools.validateSignature(sl20SignedPayload.asText()); -		 -		} else if (sl20Payload != null) -			return new VerificationResult(sl20Payload); -		 -		 else -			throw new SLCommandoParserException("Internal build error"); -			 -		 -	} -	 -	 -	/** -	 * Extract generic transport container from httpResponse -	 *  -	 * @param httpResp -	 * @return -	 * @throws SLCommandoParserException -	 */ -	public static JsonNode getSL20ContainerFromResponse(HttpResponse httpResp) throws SLCommandoParserException { -		try { -			JsonNode sl20Resp = null; -			if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { -				final Header[] locationHeader = httpResp.getHeaders("Location"); -				if (locationHeader == null) -					throw new SLCommandoParserException("Find Redirect statuscode but not Location header"); -			 -				final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); -				sl20Resp =  mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); -			 -			} else if (httpResp.getStatusLine().getStatusCode() == 200) { -				if (httpResp.getEntity().getContentType() == null) -					throw new SLCommandoParserException("SL20 response contains NO ContentType");					 -				 -				if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) -					throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());					 -				sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); -		 -			} else if ( (httpResp.getStatusLine().getStatusCode() == 500) ||  -					(httpResp.getStatusLine().getStatusCode() == 401) ||  -					(httpResp.getStatusLine().getStatusCode() == 400) ) { -				log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()  -						+ ". Search for error message"); -				 -				try { -					sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); -					 -				} catch (final Exception e) { -					log.warn("SL20 response contains no valid JSON", e); -					throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()  -							+ " AND NO valid JSON errormsg", e); -					 -				} -							 -				 -				 -			} else -				throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); - -			log.info("Find JSON object in http response"); -			return sl20Resp; -			 -		} catch (final Exception e) { -			throw new SLCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); -			 -		}		 -	} -	 -	private static JsonNode parseSL20ResultFromResponse(HttpEntity resp) throws Exception { -		if (resp != null && resp.getContent() != null) { -			final String rawSL20Resp = EntityUtils.toString(resp);			 -			final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); -			 -			//TODO: check sl20Resp type like && sl20Resp.isJsonObject()			 -			if (sl20Resp != null) { -				return sl20Resp; -				 -			} else -				throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object"); -			 -			 -		} else -			throw new SLCommandoParserException("Can NOT find content in http response"); - 					 -	} -	 -	 -	private static JsonNode getAndCheck(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { -		final JsonNode internal = input.get(keyID); -		 -		if (internal == null && isRequired)  -			throw new SLCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist"); -		 -		return internal; -		 -	} -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java new file mode 100644 index 00000000..f505f28d --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java @@ -0,0 +1,731 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class SL20JsonBuilderUtils { + +  private static JsonMapper mapper = new JsonMapper(); + +  /** +   * Create command request. +   * +   * @param name Commando name +   * @param params Commando parameters +   * @return JSON Object +   * @throws SlCommandoBuildException In case of a build error +   */ +  public static ObjectNode createCommand(final String name, final ObjectNode params) +      throws SlCommandoBuildException { + +    final ObjectNode command = mapper.getMapper().createObjectNode(); +    addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); +    addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); +    return command; + +  } + +  /** +   * Create signed command request. +   * +   * @param name Commando name +   * @param params commando parameter +   * @param signer JWS signer implementation +   * @return Serialized JWS +   * @throws SlCommandoBuildException In case of a build error +   */ +  public static String createSignedCommand(final String name, final ObjectNode params, +      final IJoseTools signer) throws SlCommandoBuildException { +    final ObjectNode command = mapper.getMapper().createObjectNode(); +    addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); +    addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); +    return signer.createSignature(command.toString()); + +  } + + +  /** +   * Create encrypted command result. +   * +   * @param result JSON to encrypt +   * @param encrypter JWE encrypter implementation +   * @return Serialized JWE +   * @throws SlCommandoBuildException In case of a processing error +   */ +  public static String createEncryptedCommandoResult(final ObjectNode result, +      final JsonSecurityUtils encrypter) throws SlCommandoBuildException { +    // TODO: add real implementation +    // create header and footer +    final String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); +    final String payLoad = result.toString(); +    final String dummyFooter = createJsonSignedFooter(encrypter); + +    return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." +        + Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "." +        + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); + +  } + + +  /** +   * Create command result. +   * +   * @param name Commando name +   * @param result commande result +   * @param encryptedResult encrypted commando result +   * @return Result json +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createCommandResponse(final String name, final ObjectNode result, +      final String encryptedResult) throws SlCommandoBuildException { +    final ObjectNode command = mapper.getMapper().createObjectNode(); +    addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); +    addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, +        SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); +    return command; + +  } + +  /** +   * Create signed command result. +   * +   * @param name commando name +   * @param result commando result +   * @param encryptedResult encrypted commando result +   * @return JWS in serialized form +   * @throws SlCommandoBuildException in case of an error + +   */ +  public static String createSignedCommandResponse(final String name, final ObjectNode result, +      final String encryptedResult, final JsonSecurityUtils signer) +      throws SlCommandoBuildException { +    final ObjectNode command = mapper.getMapper().createObjectNode(); +    addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); +    addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, +        SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); +    final String encodedCommand = command.toString(); + +    // TODO: add real implementation +    // create header and footer +    final String dummyHeader = createJsonSignedHeader(signer).toString(); +    final String dummyFooter = createJsonSignedFooter(signer); + +    return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." +        + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "." +        + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); + +  } + +  /** +   * Create parameters for Redirect command. +   * +   * @param url redirect URL +   * @param command embedded command +   * @param signedCommand Signed embedded command +   * @param ipcRedirect IPC redirect flag +   * @return result JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createRedirectCommandParameters(final String url, +      final ObjectNode command, final ObjectNode signedCommand, final Boolean ipcRedirect) +      throws SlCommandoBuildException { +    final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); +    addOnlyOnceOfTwo(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, command, signedCommand); +    addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, +        url, false); +    addSingleBooleanElement(redirectReqParams, +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false); +    return redirectReqParams; + +  } + +  /** +   * Create parameters for Call command. +   * +   * @param url http URL for Call command +   * @param method http method used by call commando result +   * @param includeTransactionId TransactionId +   * @param reqParameters Request parameters on CALL command +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createCallCommandParameters(final String url, final String method, +      final Boolean includeTransactionId, final Map<String, String> reqParameters) +      throws SlCommandoBuildException { +    final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); +    addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, +        true); +    addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, +        method, true); +    addSingleBooleanElement(callReqParams, +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, +        false); +    addArrayOfStringElements(callReqParams, +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters); +    return callReqParams; + +  } + +  /** +   * Create result for Error command. +   * +   * @param errorCode Error-Code +   * @param errorMsg Error-message +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createErrorCommandResult(final String errorCode, final String errorMsg) +      throws SlCommandoBuildException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, +        errorCode, true); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, +        errorMsg, true); +    return result; + +  } + +  /** +   * Create parameters for qualifiedeID command. +   * +   * @param consentTemplateId Identifier of the template that is used for consent visualization +   * @param consent Consent that has to be signed by user +   * @param dataUrl DataURL for result +   * @param x5cEnc Response encryption certificate +   * @return JSON +   * @throws CertificateEncodingException In case of a encryption certificate encoding problem +   * @throws SlCommandoBuildException In case of a generel error +   */ +  public static ObjectNode createQualifiedeEidConsent(final String consentTemplateId, +      final byte[] consent, final String dataUrl, final X509Certificate x5cEnc) +      throws CertificateEncodingException, SlCommandoBuildException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, +        consentTemplateId, true); +    addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); +    return params; + +  } + + +  /** +   * Create parameters for qualifiedeID command. +   * +   * @param authBlockId AuthBlock transformation Id +   * @param dataUrl DataURL for result +   * @param additionalReqParameters  additional parameters +   * @param x5cEnc Response encryption certificate +   * @return JSON +   * @throws CertificateEncodingException In case of a encryption certificate encoding problem +   * @throws SlCommandoBuildException In case of a generel error +   */ +  @Deprecated +  public static ObjectNode createQualifiedEidCommandParameters(final String authBlockId, +      final String dataUrl, final Map<String, String> additionalReqParameters, +      final X509Certificate x5cEnc) throws CertificateEncodingException, SlCommandoBuildException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, +        true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); +    addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, +        additionalReqParameters); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); +    return params; + +  } + +  /** +   * Create result for qualifiedeID command. +   * +   * @param idl IdentityLink +   * @param authBlock AuthBlock +   * @param ccsUrl VDA URL +   * @param loa LoA +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createQualifiedEidCommandResult(final byte[] idl, final byte[] authBlock, +      final String ccsUrl, final String loa) throws SlCommandoBuildException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true); +    addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, +        true); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsUrl, +        true); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, loa, true); +    return result; + +  } + + +  /** +   * Create Binding-Key command parameters. +   * +   * @param kontoId KontoId +   * @param subjectName SubjectName +   * @param keySize KeySize +   * @param keyAlg Key-algorithm +   * @param policies Key policy +   * @param dataUrl DataURL +   * @param x5cVdaTrust trusted certificate from VDA +   * @param reqUserPassword User passwort initialize request +   * @param x5cEnc Result encryption certificate +   * @return JSON +   * @throws SlCommandoBuildException in case of an errr +   * @throws CertificateEncodingException In case of a certificate error +   */ +  public static ObjectNode createBindingKeyCommandParams(final String kontoId, +      final String subjectName, final int keySize, final String keyAlg, +      final Map<String, String> policies, final String dataUrl, final X509Certificate x5cVdaTrust, +      final Boolean reqUserPassword, final X509Certificate x5cEnc) +      throws SlCommandoBuildException, CertificateEncodingException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, +        true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, +        true); +    addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, +        keySize, true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, +        true); +    addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, +        policies); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, +        true); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, +        x5cVdaTrust, false); +    addSingleBooleanElement(params, +        SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, +        false); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, +        x5cEnc, false); +    return params; + +  } + +  /** +   * Create Binding-Key command result. +   * +   * @param appId AppId +   * @param csr CSR +   * @param attCert Key-Attestation certificate +   * @param password user's password +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   * @throws CertificateEncodingException In case of a certificate processing error +   */ +  public static ObjectNode createBindingKeyCommandResult(final String appId, final byte[] csr, +      final X509Certificate attCert, final byte[] password) +      throws SlCommandoBuildException, CertificateEncodingException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, +        appId, true); +    addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, +        true); +    addSingleCertificateElement(result, +        SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, +        false); +    addSingleByteElement(result, +        SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false); +    return result; + +  } + +  /** +   * Create Store Binding-Certificate command parameters. +   * +   * @param cert Certificate +   * @param dataUrl DATA URL +   * @return JSON +   * @throws CertificateEncodingException In case of a certificate processing error +   * @throws SlCommandoBuildException In case of a error +   */ +  public static ObjectNode createStoreBindingCertCommandParams(final X509Certificate cert, +      final String dataUrl) throws CertificateEncodingException, SlCommandoBuildException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, +        cert, true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, +        true); +    return params; + +  } + +  /** +   * Create Store Binding-Certificate command result. +   * +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createStoreBindingCertCommandSuccessResult() +      throws SlCommandoBuildException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS, +        SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true); +    return result; + +  } + + +  /** +   * Create idAndPassword command parameters. +   * +   * @param keyAlg key algorithm +   * @param dataUrl DATA Url +   * @param x5cEnc result encryption certificate +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   * @throws CertificateEncodingException In case of a certificate processing error +   */ +  public static ObjectNode createIdAndPasswordCommandParameters(final String keyAlg, +      final String dataUrl, final X509Certificate x5cEnc) +      throws SlCommandoBuildException, CertificateEncodingException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, +        keyAlg, true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, +        dataUrl, true); +    addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, +        x5cEnc, false); +    return params; + +  } + +  /** +   * Create idAndPassword command result. +   * +   * @param kontoId User's Id +   * @param password User's password +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createIdAndPasswordCommandResult(final String kontoId, +      final byte[] password) throws SlCommandoBuildException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleStringElement(result, +        SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true); +    addSingleByteElement(result, +        SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true); +    return result; + +  } + +  /** +   * Create JWS Token Authentication command. +   * +   * @param nonce nonce that should be signed +   * @param dataUrl Data URL +   * @param displayData Data that should be displayed +   * @param displayUrl  URL to data that should be displayed +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createJwsTokenAuthCommandParams(final String nonce, final String dataUrl, +      final List<String> displayData, final List<String> displayUrl) +      throws SlCommandoBuildException { +    final ObjectNode params = mapper.getMapper().createObjectNode(); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, +        true); +    addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, +        true); +    addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, +        displayData); +    addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, +        displayUrl); +    return params; + +  } + +  /** +   * Create JWS Token Authentication command result. +   * +   * @param nonce Serialzed JWS that contains the signed nonce +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createJwsTokenAuthCommandResult(final String nonce) +      throws SlCommandoBuildException { +    final ObjectNode result = mapper.getMapper().createObjectNode(); +    addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, +        nonce, true); +    return result; + +  } + + +  /** +   * Create Generic Request Container. +   * +   * @param reqId RequestId +   * @param transactionId TransactionId +   * @param payLoad unsigned payload +   * @param signedPayload Signed payload +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static ObjectNode createGenericRequest(final String reqId, final String transactionId, +      final ObjectNode payLoad, final String signedPayload) throws SlCommandoBuildException { +    final ObjectNode req = mapper.getMapper().createObjectNode(); +    addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, +        true); +    addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true); +    addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); +    addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, +        signedPayload); +    return req; + +  } + +  /** +   * Create Generic Response Container. +   * +   * @param respId Response Id +   * @param inResponseTo RequestId to this response +   * @param transactionId transactionId +   * @param payLoad Unsigned payload +   * @param signedPayload Signed payload +   * @return JSON +   * @throws SlCommandoBuildException In case of an error +   */ +  public static final ObjectNode createGenericResponse(final String respId, +      final String inResponseTo, final String transactionId, final ObjectNode payLoad, +      final String signedPayload) throws SlCommandoBuildException { +    final ObjectNode req = mapper.getMapper().createObjectNode(); +    addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, +        true); +    addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true); +    addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false); +    addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); +    addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, +        signedPayload); +    return req; + +  } + +  private static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, +      final String secondKeyId, final ObjectNode first, final ObjectNode second) +      throws SlCommandoBuildException { +    if (first == null && second == null) { +      throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); +    } else if (first != null && second != null) { +      throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); +    } else if (first != null) { +      parent.set(firstKeyId, first); +    } else if (second != null) { +      parent.set(secondKeyId, second); +    } else { +      throw new SlCommandoBuildException("Internal build error"); +    } +  } + +  /** +   * Add one element of two possible elements <br> +   * This method adds either the first element or the second element to parent JSON, but never both. +   * +   * @param parent Parent JSON element +   * @param firstKeyId first element Id +   * @param secondKeyId second element Id +   * @param first first element +   * @param second second element +   * @throws SlCommandoBuildException In case of an error. +   */ +  public static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, +      final String secondKeyId, final ObjectNode first, final String second) +      throws SlCommandoBuildException { +    if (first == null && (second == null || second.isEmpty())) { +      throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); +    } else if (first != null && second != null) { +      throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); +    } else if (first != null) { +      parent.set(firstKeyId, first); +    } else if (second != null && !second.isEmpty()) { +      parent.put(secondKeyId, second); +    } else { +      throw new SlCommandoBuildException("Internal build error"); +    } +  } + + + +  // TODO!!!! +  private static ObjectNode createJsonSignedHeader(final JsonSecurityUtils signer) +      throws SlCommandoBuildException { +    final ObjectNode header = mapper.getMapper().createObjectNode(); +    addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, +        SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true); +    addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, +        SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true); +    addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, +        Arrays.asList(Constants.DUMMY_SIGNING_CERT)); + +    return header; +  } + +  // TODO!!!! +  private static ObjectNode createJsonEncryptionHeader(final JsonSecurityUtils signer) +      throws SlCommandoBuildException { +    final ObjectNode header = mapper.getMapper().createObjectNode(); +    addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, +        SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true); +    addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, +        SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true); +    addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, +        SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true); +    addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, +        Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true); + +    return header; +  } + +  // TODO!!!! +  private static String createJsonSignedFooter(final JsonSecurityUtils signer) { +    return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" +        + "  AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" +        + "  BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" +        + "  0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" +        + "  hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" +        + "  p0igcN_IoypGlUPQGe77Rw"; +  } + + + +  private static void addArrayOfStrings(final ObjectNode parent, final String keyId, +      final List<String> values) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); +    if (values != null) { +      final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); +      parent.set(keyId, callReqParamsArray); +      for (final String el : values) { +        callReqParamsArray.add(el); +      } + +    } +  } + + +  private static void addArrayOfStringElements(final ObjectNode parent, final String keyId, +      final Map<String, String> keyValuePairs) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); +    if (keyValuePairs != null) { +      final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); +      parent.set(keyId, callReqParamsArray); + +      for (final Entry<String, String> el : keyValuePairs.entrySet()) { +        final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); +        callReqParams.put(el.getKey(), el.getValue()); +        callReqParamsArray.add(callReqParams); + +      } +    } +  } + +  private static void addSingleCertificateElement(final ObjectNode parent, final String keyId, +      final X509Certificate cert, final boolean isRequired) +      throws CertificateEncodingException, SlCommandoBuildException { +    if (cert != null) { +      addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired); +    } else if (isRequired) { +      throw new SlCommandoBuildException(keyId + " is marked as REQUIRED"); +    } + +  } + + + +  private static void addSingleByteElement(final ObjectNode parent, final String keyId, +      final byte[] value, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && value == null) { +      throw new SlCommandoBuildException(keyId + " has NULL value"); +    } else if (value != null) { +      parent.put(keyId, Base64.getEncoder().encodeToString(value)); +    } + +  } + +  private static void addSingleBooleanElement(final ObjectNode parent, final String keyId, +      final Boolean value, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && value == null) { +      throw new SlCommandoBuildException(keyId + " has a NULL value"); +    } else if (value != null) { +      parent.put(keyId, value); +    } + +  } + +  private static void addSingleNumberElement(final ObjectNode parent, final String keyId, +      final Integer value, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && value == null) { +      throw new SlCommandoBuildException(keyId + " has a NULL value"); +    } else if (value != null) { +      parent.put(keyId, value); +    } + +  } + +  private static void addSingleStringElement(final ObjectNode parent, final String keyId, +      final String value, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && (value == null || value.isEmpty())) { +      throw new SlCommandoBuildException(keyId + " has an empty value"); +    } else if (value != null && !value.isEmpty()) { +      parent.put(keyId, value); +    } + +  } + +  private static void addSingleIntegerElement(final ObjectNode parent, final String keyId, +      final Integer value, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && value == null) { +      throw new SlCommandoBuildException(keyId + " has an empty value"); +    } else if (value != null) { +      parent.put(keyId, value); +    } + +  } + +  private static void addSingleJsonElement(final ObjectNode parent, final String keyId, +      final ObjectNode element, final boolean isRequired) throws SlCommandoBuildException { +    validateParentAndKey(parent, keyId); + +    if (isRequired && element == null) { +      throw new SlCommandoBuildException("No commando name included"); +    } else if (element != null) { +      parent.set(keyId, element); +    } + +  } + + + +  private static void validateParentAndKey(final ObjectNode parent, final String keyId) +      throws SlCommandoBuildException { +    if (parent == null) { +      throw new SlCommandoBuildException("NO parent JSON element"); +    } + +    if (keyId == null || keyId.isEmpty()) { +      throw new SlCommandoBuildException("NO JSON element identifier"); +    } +  } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java new file mode 100644 index 00000000..f4b5a724 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java @@ -0,0 +1,407 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.util.EntityUtils; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class SL20JsonExtractorUtils { +  private static final Logger log = LoggerFactory.getLogger(SL20JsonExtractorUtils.class); +  private static JsonMapper mapper = new JsonMapper(); + + +  /** +   * Extract String value from JSON. +   * +   * @param input JSON +   * @param keyID Element identifier +   * @param isRequired true, if the element must not null +   * @return Value of this element +   * @throws SlCommandoParserException In case an error +   */ +  public static String getStringValue(final JsonNode input, final String keyID, +      final boolean isRequired) throws SlCommandoParserException { +    try { +      final JsonNode internal = getAndCheck(input, keyID, isRequired); + +      if (internal != null) { +        return internal.asText(); +      } else { +        return null; +      } + +    } catch (final SlCommandoParserException e) { +      throw e; + +    } catch (final Exception e) { +      throw new SlCommandoParserException("Can not extract String value with keyId: " + keyID, e); + +    } +  } + +  /** +   * Extract Boolean value from JSON. +   * +   * @param input JSON +   * @param keyID Element identifier +   * @param isRequired true, if the element must not null +   * @return Boolean +   * @throws SlCommandoParserException In case of an error +   */ +  public static boolean getBooleanValue(final ObjectNode input, final String keyID, +      final boolean isRequired, final boolean defaultValue) throws SlCommandoParserException { +    try { +      final JsonNode internal = getAndCheck(input, keyID, isRequired); + +      if (internal != null) { +        return internal.asBoolean(); +      } else { +        return defaultValue; +      } + +    } catch (final SlCommandoParserException e) { +      throw e; + +    } catch (final Exception e) { +      throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + +    } +  } + +  /** +   * Extract JSONObject value from JSON. +   * +   * @param input JSON +   * @param keyID Element identifier +   * @param isRequired true, if the element must not null +   * @return JSON node +   * @throws SlCommandoParserException In case of an error +   */ +  public static JsonNode getJsonObjectValue(final JsonNode input, final String keyID, +      final boolean isRequired) throws SlCommandoParserException { +    try { +      final JsonNode internal = getAndCheck(input, keyID, isRequired); + +      if (internal != null) { +        return internal; +      } else { +        return null; +      } + +    } catch (final SlCommandoParserException e) { +      throw e; + +    } catch (final Exception e) { +      throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + +    } +  } + +  /** +   * Extract a List of String elements from a JSON element. +   * +   * @param input JSON +   * @return List of Elements in this node +   * @throws SlCommandoParserException In case of an error +   */ +  public static List<String> getListOfStringElements(final JsonNode input) +      throws SlCommandoParserException { +    final List<String> result = new ArrayList<>(); +    if (input != null) { +      if (input.isArray()) { +        final Iterator<JsonNode> arrayIterator = input.iterator(); +        while (arrayIterator.hasNext()) { +          final JsonNode next = arrayIterator.next(); +          if (next.isTextual()) { +            result.add(next.asText()); +          } +        } + +      } else if (input.isTextual()) { +        result.add(input.asText()); + +      } else { +        log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); +        throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); + +      } +    } + +    return result; +  } + +  /** +   * Extract Map of Key/Value pairs from a JSON Element. +   * +   * @param input parent JSON object +   * @param keyID KeyId of the child that should be parsed +   * @param isRequired true, if the element must not null +   * @return Map of element pairs +   * @throws SlCommandoParserException In case of an error +   */ +  public static Map<String, String> getMapOfStringElements(final JsonNode input, final String keyID, +      final boolean isRequired) throws SlCommandoParserException { +    final JsonNode internal = getAndCheck(input, keyID, isRequired); +    return getMapOfStringElements(internal); + +  } + +  /** +   * Extract Map of Key/Value pairs from a JSON Element. +   * +   * @param input JSON +   * @return Map of element pairs +   * @throws SlCommandoParserException in case of an error +   */ +  public static Map<String, String> getMapOfStringElements(final JsonNode input) +      throws SlCommandoParserException { +    final Map<String, String> result = new HashMap<>(); + +    if (input != null) { +      if (input.isArray()) { +        final Iterator<JsonNode> arrayIterator = input.iterator(); +        while (arrayIterator.hasNext()) { +          final JsonNode next = arrayIterator.next(); +          final Iterator<Entry<String, JsonNode>> entry = next.fields(); +          entitySetToMap(result, entry); + +        } + +      } else if (input.isObject()) { +        final Iterator<Entry<String, JsonNode>> objectKeys = input.fields(); +        entitySetToMap(result, objectKeys); + +      } else { +        throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); +      } + +    } + +    return result; +  } + +  private static void entitySetToMap(final Map<String, String> result, +      final Iterator<Entry<String, JsonNode>> entry) { +    while (entry.hasNext()) { +      final Entry<String, JsonNode> el = entry.next(); +      if (result.containsKey(el.getKey())) { +        log.info("Attr. Map already contains Element with Key: " + el.getKey() +            + ". Overwrite element ... "); +      } + +      result.put(el.getKey(), el.getValue().asText()); + +    } + +  } + + +  /** +   * Extract Security-Layer 2.0 result from response object. +   * +   * @param command SL2.0 command +   * @param decrypter JWS decrypter implementation +   * @param mustBeEncrypted if <code>true</code>, the result must be encrypted +   * @return decrypted JSON +   * @throws SL20Exception In case of an error +   */ +  public static JsonNode extractSL20Result(final JsonNode command, final IJoseTools decrypter, +      final boolean mustBeEncrypted) throws SL20Exception { +    final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); +    final JsonNode encryptedResult = +        command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); + +    if (result == null && encryptedResult == null) { +      throw new SlCommandoParserException("NO result OR encryptedResult FOUND."); +    } else if (encryptedResult == null && mustBeEncrypted) { +      throw new SlCommandoParserException("result MUST be encrypted."); +    } else if (encryptedResult != null && encryptedResult.isTextual()) { +      try { +        return decrypter.decryptPayload(encryptedResult.asText()); + +      } catch (final Exception e) { +        log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); +        if (!mustBeEncrypted) { +          log.warn( +              "Decrypted results are disabled by configuration. Parse result in plain if it is possible"); + +          // dummy code +          try { +            final String[] signedPayload = encryptedResult.toString().split("\\."); +            final JsonNode payLoad = mapper.getMapper() +                .readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); +            return payLoad; + +          } catch (final Exception e1) { +            log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); +            throw new SL20Exception(e.getMessage(), null, e); + +          } + +        } else { +          throw e; +        } + +      } + +    } else if (result != null) { +      return result; + +    } else { +      throw new SlCommandoParserException("Internal build error"); +    } + + +  } + +  /** +   * Extract payLoad from generic transport container. +   * +   * @param container JSON +   * @param joseTools JWS implementation +   * @return Signature verification result that contains the payLoad +   * @throws SlCommandoParserException In case of an error +   */ +  public static VerificationResult extractSL20PayLoad(final JsonNode container, +      final IJoseTools joseTools, final boolean mustBeSigned) throws SL20Exception { + +    final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); +    final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); + +    if (mustBeSigned && joseTools == null) { +      throw new SlCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); +    } + +    if (sl20Payload == null && sl20SignedPayload == null) { +      throw new SlCommandoParserException("NO payLoad OR signedPayload FOUND."); +    } else if (sl20SignedPayload == null && mustBeSigned) { +      throw new SlCommandoParserException("payLoad MUST be signed."); +    } else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) { +      return joseTools.validateSignature(sl20SignedPayload.asText()); + +    } else if (sl20Payload != null) { +      return new VerificationResult(sl20Payload); +    } else { +      throw new SlCommandoParserException("Internal build error"); +    } + + +  } + + +  /** +   * Extract generic transport container from httpResponse. +   * +   * @param httpResp Http response object +   * @return JSON with SL2.0 response +   * @throws SlCommandoParserException In case of an error +   */ +  public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) +      throws SlCommandoParserException { +    try { +      JsonNode sl20Resp = null; +      if (httpResp.getStatusLine().getStatusCode() == 303 +          || httpResp.getStatusLine().getStatusCode() == 307) { +        final Header[] locationHeader = httpResp.getHeaders("Location"); +        if (locationHeader == null) { +          throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); +        } + +        final String sl20RespString = +            new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); +        sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); + +      } else if (httpResp.getStatusLine().getStatusCode() == 200) { +        if (httpResp.getEntity().getContentType() == null) { +          throw new SlCommandoParserException("SL20 response contains NO ContentType"); +        } + +        if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { +          throw new SlCommandoParserException("SL20 response with a wrong ContentType: " +              + httpResp.getEntity().getContentType().getValue()); +        } +        sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + +      } else if ((httpResp.getStatusLine().getStatusCode() == 500) +          || (httpResp.getStatusLine().getStatusCode() == 401) +          || (httpResp.getStatusLine().getStatusCode() == 400)) { +        log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() +            + ". Search for error message"); + +        try { +          sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + +        } catch (final Exception e) { +          log.warn("SL20 response contains no valid JSON", e); +          throw new SlCommandoParserException("SL20 response with http-code: " +              + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e); + +        } + + + +      } else { +        throw new SlCommandoParserException( +            "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); +      } + +      log.info("Find JSON object in http response"); +      return sl20Resp; + +    } catch (final Exception e) { +      throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), +          e); + +    } +  } + +  private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { +    if (resp != null && resp.getContent() != null) { +      final String rawSL20Resp = EntityUtils.toString(resp); +      final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); + +      // TODO: check sl20Resp type like && sl20Resp.isJsonObject() +      if (sl20Resp != null) { +        return sl20Resp; + +      } else { +        throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); +      } + + +    } else { +      throw new SlCommandoParserException("Can NOT find content in http response"); +    } + +  } + + +  private static JsonNode getAndCheck(final JsonNode input, final String keyID, +      final boolean isRequired) throws SlCommandoParserException { +    final JsonNode internal = input.get(keyID); + +    if (internal == null && isRequired) { +      throw new SlCommandoParserException( +          "REQUIRED Element with keyId: " + keyID + " does not exist"); +    } + +    return internal; + +  } +} | 
