diff options
Diffstat (limited to 'eaaf_core')
56 files changed, 2373 insertions, 1459 deletions
| diff --git a/eaaf_core/checks/spotbugs-exclude.xml b/eaaf_core/checks/spotbugs-exclude.xml new file mode 100644 index 00000000..70f27b81 --- /dev/null +++ b/eaaf_core/checks/spotbugs-exclude.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<FindBugsFilter> +    <Match> +      <!-- only redirects to internal addresses --> +      <Class name="at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask"/> +      <Method name="performRedirectToItself" /> +      <Bug pattern="UNVALIDATED_REDIRECT" /> +    </Match> +    <Match> +      <!-- only redirects to internal addresses --> +      <Class name="at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService"/> +      <Method name="forwardToErrorHandler" /> +      <Bug pattern="UNVALIDATED_REDIRECT" /> +    </Match> +    <Match> +      <!-- the ErrorToken is only single-used as same as a CSRF token --> +      <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController"/> +      <Method name="errorHandling" /> +      <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" /> +    </Match> +    <Match> +      <!-- the ErrorToken is only single-used as same as a CSRF token --> +      <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController"/> +      <Method name="errorRedirect" /> +      <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" /> +    </Match> +    <Match> +      <!-- Only used to evaluate expressions from pre-compiled process-flows --> +      <OR> +        <Class name="at.gv.egiz.eaaf.core.impl.idp.process.springweb.SpringWebExpressionEvaluator"/> +        <Class name="at.gv.egiz.eaaf.core.impl.idp.process.spring.SpringExpressionEvaluator"/> +      </OR> +      <Bug pattern="SPEL_INJECTION" /> +    </Match> +    <Match> +      <!-- URL will be only generated from configuration path--> +      <Class name="at.gv.egiz.eaaf.core.impl.idp.conf.AbstractConfigurationImpl"/> +      <Bug pattern="PATH_TRAVERSAL_IN" /> +    </Match> +    <Match> +      <!-- Logging of request parameters is allowed for this classes -->    +      <OR> +        <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask"/> +        <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController"/> +        <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController"/> +      </OR> +      <Bug pattern="CRLF_INJECTION_LOGS" /> +    </Match> +</FindBugsFilter> diff --git a/eaaf_core/pom.xml b/eaaf_core/pom.xml index fba6e018..15628054 100644 --- a/eaaf_core/pom.xml +++ b/eaaf_core/pom.xml @@ -1,104 +1,107 @@  <?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"> +<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</groupId> -	<artifactId>eaaf</artifactId> -	<version>1.1.3-SNAPSHOT</version> +    <groupId>at.gv.egiz</groupId> +    <artifactId>eaaf</artifactId> +    <version>1.2.1-SNAPSHOT</version>    </parent>    <groupId>at.gv.egiz.eaaf</groupId>    <artifactId>eaaf-core</artifactId>    <name>EAAF core components</name>    <description>Core components for identity managment implementations</description> -      +    <dependencies> -  	<dependency> -  		<groupId>at.gv.egiz.eaaf</groupId> -  		<artifactId>eaaf_core_api</artifactId> -  	</dependency> -  	<dependency> -		<groupId>at.gv.egiz.eaaf</groupId> -  		<artifactId>eaaf_core_utils</artifactId> -  	</dependency> -   -  	<dependency> -  		<groupId>at.gv.egiz.components</groupId> -    	<artifactId>eventlog-api</artifactId> -  	</dependency> -  	<dependency> -  		<groupId>at.gv.egiz.components</groupId> -    	<artifactId>egiz-spring-api</artifactId> -  	</dependency> -  	<dependency> -  		<groupId>javax.annotation</groupId> -    	<artifactId>javax.annotation-api</artifactId> -  	</dependency> -  	<dependency> -  		<groupId>org.springframework</groupId> -		<artifactId>spring-webmvc</artifactId> -        <scope>provided</scope> -  	</dependency> -  	<dependency> -    	<groupId>org.slf4j</groupId> -    	<artifactId>slf4j-api</artifactId> -	</dependency> -	<!-- dependency> -    	<groupId>org.slf4j</groupId> -    	<artifactId>slf4j-log4j12</artifactId> -	</dependency--> -	<dependency> -		<groupId>commons-codec</groupId> -    	<artifactId>commons-codec</artifactId> -	</dependency> -	<dependency> -		<groupId>org.apache.commons</groupId> -    	<artifactId>commons-lang3</artifactId> -	</dependency> -	<dependency> -		<groupId>org.apache.commons</groupId> -    	<artifactId>commons-collections4</artifactId> -	</dependency> -	<dependency> -		<groupId>org.apache.commons</groupId> -    	<artifactId>commons-text</artifactId> -	</dependency> -	<dependency> -		<groupId>commons-fileupload</groupId> -    	<artifactId>commons-fileupload</artifactId> -	</dependency> -	<dependency> -		<groupId>javax.servlet</groupId> -		<artifactId>javax.servlet-api</artifactId> -	</dependency> -	<dependency> -		<groupId>org.apache.velocity</groupId> -		<artifactId>velocity</artifactId> -	</dependency> - 	<dependency> -		<groupId>jaxen</groupId> -    	<artifactId>jaxen</artifactId> -	</dependency> -	<dependency> -		<groupId>xerces</groupId> -    	<artifactId>xercesImpl</artifactId> -	</dependency> -	<dependency> -		<groupId>xalan</groupId> -	    <artifactId>xalan</artifactId> -	</dependency> -		 +    <dependency> +      <groupId>at.gv.egiz.eaaf</groupId> +      <artifactId>eaaf_core_api</artifactId> +    </dependency> +    <dependency> +      <groupId>at.gv.egiz.eaaf</groupId> +      <artifactId>eaaf_core_utils</artifactId> +    </dependency> + +    <dependency> +      <groupId>at.gv.egiz.components</groupId> +      <artifactId>eventlog-api</artifactId> +    </dependency> +    <dependency> +      <groupId>at.gv.egiz.components</groupId> +      <artifactId>egiz-spring-api</artifactId> +    </dependency> +    <dependency> +      <groupId>javax.annotation</groupId> +      <artifactId>javax.annotation-api</artifactId> +    </dependency> +    <dependency> +      <groupId>org.springframework</groupId> +      <artifactId>spring-webmvc</artifactId> +      <scope>provided</scope> +    </dependency> +    <dependency> +      <groupId>org.slf4j</groupId> +      <artifactId>slf4j-api</artifactId> +    </dependency> +    <!-- dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId>  +      </dependency --> +    <dependency> +      <groupId>commons-codec</groupId> +      <artifactId>commons-codec</artifactId> +    </dependency> +    <dependency> +      <groupId>org.apache.commons</groupId> +      <artifactId>commons-lang3</artifactId> +    </dependency> +    <dependency> +      <groupId>org.apache.commons</groupId> +      <artifactId>commons-collections4</artifactId> +    </dependency> +    <dependency> +      <groupId>org.apache.commons</groupId> +      <artifactId>commons-text</artifactId> +    </dependency> +    <dependency> +      <groupId>commons-fileupload</groupId> +      <artifactId>commons-fileupload</artifactId> +    </dependency> +    <dependency> +      <groupId>javax.servlet</groupId> +      <artifactId>javax.servlet-api</artifactId> +    </dependency> +    <dependency> +      <groupId>org.apache.velocity</groupId> +      <artifactId>velocity</artifactId> +    </dependency> +    <dependency> +      <groupId>commons-collections</groupId> +      <artifactId>commons-collections</artifactId>       +    </dependency> +    <dependency> +      <groupId>org.owasp.encoder</groupId> +      <artifactId>encoder</artifactId> +    </dependency> +    <dependency> +      <groupId>jaxen</groupId> +      <artifactId>jaxen</artifactId> +    </dependency> +    <dependency> +      <groupId>xerces</groupId> +      <artifactId>xercesImpl</artifactId> +    </dependency> +    <dependency> +      <groupId>xalan</groupId> +      <artifactId>xalan</artifactId> +    </dependency> +      <!-- For testing --> -	<dependency> -		<groupId>junit</groupId> -      	<artifactId>junit</artifactId> -      	<scope>test</scope> -	</dependency> -	<dependency> -		<groupId>org.springframework</groupId> -		<artifactId>spring-test</artifactId> -		<scope>test</scope> -	</dependency> +    <dependency> +      <groupId>org.springframework</groupId> +      <artifactId>spring-test</artifactId> +      <scope>test</scope> +    </dependency>      <dependency>        <groupId>at.gv.egiz.eaaf</groupId>        <artifactId>eaaf_core_utils</artifactId> @@ -106,58 +109,22 @@        <type>test-jar</type>      </dependency>    </dependencies> -   -   <build> + +  <build>      <finalName>eaaf_core</finalName> -     +      <plugins>        <plugin> -        <groupId>org.apache.maven.plugins</groupId> -        <artifactId>maven-compiler-plugin</artifactId> -        <version>3.7.0</version> +        <groupId>com.github.spotbugs</groupId> +        <artifactId>spotbugs-maven-plugin</artifactId> +        <version>${spotbugs-maven-plugin.version}</version>          <configuration> -          <source>1.8</source> -          <target>1.8</target> +          <failOnError>true</failOnError> +          <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>          </configuration> -        <executions> -        	<execution> -        		<goals> -        			<goal>compile</goal> -        			<goal>testCompile</goal> -        		</goals> -        	</execution> -        </executions>        </plugin> -      <plugin> -    	<groupId>org.apache.maven.plugins</groupId> -    	<artifactId>maven-jar-plugin</artifactId> -    	<version>3.1.0</version> -    	<executions> -        	<execution> -            	<goals> -                	<goal>test-jar</goal> -            	</goals> -        	</execution> -    	</executions> -	  </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>    </build> -   +  </project> diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java index b3e0c88f..08c48435 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java @@ -3,8 +3,6 @@ package at.gv.egiz.eaaf.core.api.utils;  import java.io.IOException;  import java.io.InputStream; -import com.google.gson.JsonParseException; -  import at.gv.egiz.eaaf.core.exceptions.EaafJsonMapperException;  public interface IJsonMapper { diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java index b0718f85..f8e64c1a 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java @@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;  import at.gv.egiz.eaaf.core.api.gui.GroupDefinition;  import at.gv.egiz.eaaf.core.api.gui.GroupDefinition.Type;  import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import lombok.Setter;  /**   * Abstract Configuration implementation for GUI Builders. @@ -63,6 +64,9 @@ public abstract class AbstractGuiFormBuilderConfiguration implements IGuiBuilder    private String authUrl = null;    private String viewName = null;    private String formSubmitEndpoint = null; +   +  @Setter +  private boolean writeAsynch = true;     private final Map<String, Object> params = new HashMap<>(); @@ -137,6 +141,13 @@ public abstract class AbstractGuiFormBuilderConfiguration implements IGuiBuilder    } +   +  @Override +  public final boolean isWriteAsynch() { +    return this.writeAsynch; +     +  } +      /**     * Define the parameters, which should be evaluated in the template. <br>     * <b>IMPORTANT:</b> external HTML escapetion is required, because it is NOT diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java index 677e3c46..4fe22feb 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java @@ -26,16 +26,18 @@ import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.Map;  import java.util.TimeZone; +import java.util.regex.Pattern; + +import javax.annotation.Nullable;  import org.apache.commons.collections4.map.HashedMap;  import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory;  import at.gv.egiz.eaaf.core.api.idp.IAuthData;  import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;  import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; -import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BpkBuilder; +import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder; +import lombok.extern.slf4j.Slf4j;  /**   * Service-Provider specific authentication data. @@ -43,12 +45,12 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BpkBuilder;   * @author tlenz   *   */ +@Slf4j  public class AuthenticationData implements IAuthData, Serializable { -  private static final Logger log = LoggerFactory.getLogger(AuthenticationData.class); -    private static final long serialVersionUID = -1042697056735596866L;    public static final String IDENTITY_LINK_DATE_FORMAT = "yyyy-MM-dd"; +  public static final String IDENTITY_LINK_DATE_REGEX = "([0-9]{4})-([0-9]{2})-([0-9]{2})";    public static final String ISSUE_INSTANT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";    private boolean isBaseIdTransferRestrication = true; @@ -66,7 +68,7 @@ public class AuthenticationData implements IAuthData, Serializable {    private String familyName;    private String givenName; -  private Date dateOfBirth; +  private String dateOfBirth;    private String encSourceId;    private String encSourceIdType; @@ -135,7 +137,6 @@ public class AuthenticationData implements IAuthData, Serializable {    }    @Override -  @Deprecated    public String getBpk() {      return bpk;    } @@ -145,28 +146,41 @@ public class AuthenticationData implements IAuthData, Serializable {     *     * @param bpk The bPK to set     */ -  @Deprecated    public void setBpk(final String bpk) {      this.bpk = bpk;    }    @Override -  public Date getDateOfBirth() { -    return getDateCopyOrNull(this.dateOfBirth); +  public String getDateOfBirth() { +    return this.dateOfBirth;    }    @Override -  public String getFormatedDateOfBirth() { -    final DateFormat pvpDateFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); -    if (getDateOfBirth() != null) { -      return pvpDateFormat.format(getDateOfBirth()); -    } else { -      return "2999-12-31"; -    } - +  public String getDateOfBirthFormated(String pattern) {         +    if (StringUtils.isNotEmpty(getDateOfBirth())) {     +      try { +        final DateFormat dateFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); +        Date parsedDate = dateFormat.parse(getDateOfBirth()); +        final String dateString = dateFormat.format(parsedDate);       +        if (getDateOfBirth().equals(dateString)) { +          final DateFormat destDateFormat = new SimpleDateFormat(pattern); +          return destDateFormat.format(parsedDate); +                     +        } else { +          log.info("DateOfBirth has an unusal format. Can not be converted to: {}", pattern); +           +        } +                         +      } catch (ParseException | IllegalArgumentException e) { +        log.error("Can not parse DateOfBirth.", e); +         +      }       +    }        +    return null; +        } - +      @Override    public String getFamilyName() {      return this.familyName; @@ -220,26 +234,16 @@ public class AuthenticationData implements IAuthData, Serializable {     *     * @param dateOfBirth The dateOfBirth to set     */ -  public void setDateOfBirth(final Date dateOfBirth) { -    this.dateOfBirth = getDateCopyOrNull(dateOfBirth); -  } - -  /** -   * Set the date of birth. -   * -   * @param dateOfBirth date of birth String as "yyyy-MM-dd" -   */ -  public void setDateOfBirth(final String dateOfBirth) { -    try { -      if (StringUtils.isNotEmpty(dateOfBirth)) { -        final DateFormat identityLinkFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); -        this.dateOfBirth = identityLinkFormat.parse(dateOfBirth); - +  public void setDateOfBirth(@Nullable final String dateOfBirth) { +    if (dateOfBirth != null) { +      if (Pattern.matches(IDENTITY_LINK_DATE_REGEX, dateOfBirth)) {          +        this.dateOfBirth = dateOfBirth; +       +      } else { +        log.error("DateOfBirth: {} does NOT match to pattern: {}",  +            dateOfBirth, IDENTITY_LINK_DATE_REGEX); +              } - -    } catch (final ParseException e) { -      log.warn("Parse dateOfBirht from IdentityLink FAILED", e); -      }    } @@ -282,7 +286,6 @@ public class AuthenticationData implements IAuthData, Serializable {    }    @Override -  @Deprecated    public String getBpkType() {      return bpkType;    } @@ -292,10 +295,9 @@ public class AuthenticationData implements IAuthData, Serializable {     *     * @param bpkType bPK type     */ -  @Deprecated    public void setBpkType(final String bpkType) {      this.bpkType = BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(bpkType); -     +    }    @Override diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java index d2365e4a..89977308 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java @@ -25,6 +25,7 @@ import java.util.ArrayList;  import java.util.Enumeration;  import java.util.List; +import javax.annotation.PostConstruct;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -34,6 +35,7 @@ import org.apache.commons.text.StringEscapeUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.IRequestStorage; @@ -66,6 +68,9 @@ public abstract class AbstractAuthenticationManager implements IAuthenticationMa    public static final int SLOTIMEOUT = 30 * 1000; // 30 sec +  @Autowired +  private ApplicationContext ctx; +      @Autowired(required = true)    protected IConfiguration authConfig;    @Autowired(required = true) @@ -76,31 +81,35 @@ public abstract class AbstractAuthenticationManager implements IAuthenticationMa    protected IRevisionLogger revisionsLogger;    @Autowired(required = false)    protected ISsoManager ssoManager; -  @Autowired +      ModuleRegistration moduleRegistration; -  /* -   * (non-Javadoc) +  @PostConstruct +  private void initializer() { +    moduleRegistration = ctx.getBean(ModuleRegistration.class); +     +  } +   +  /** +   * Add a request parameter to whitelist. All parameters that are part of the +   * white list are added into {@link ExecutionContext}     * -   * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager# -   * addParameterNameToWhiteList(java.lang .String) +   * @param httpReqParam http parameter name, but never null     */ -  @Override -  public final void addParameterNameToWhiteList(final String httpReqParam) { +  public static final void addParameterNameToWhiteList(final String httpReqParam) {      if (StringUtils.isNotEmpty(httpReqParam)) {        reqParameterWhiteListeForModules.add(httpReqParam);      }    } -  /* -   * (non-Javadoc) +  /** +   * Add a request header to whitelist. All parameters that are part of the white +   * list are added into {@link ExecutionContext}     * -   * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager# -   * addHeaderNameToWhiteList(java.lang. String) +   * @param httpReqParam http header name, but never null     */ -  @Override -  public final void addHeaderNameToWhiteList(final String httpReqParam) { +  public static final void addHeaderNameToWhiteList(final String httpReqParam) {      if (StringUtils.isNotEmpty(httpReqParam)) {        reqHeaderWhiteListeForModules.add(httpReqParam.toLowerCase());      } @@ -348,7 +357,7 @@ public abstract class AbstractAuthenticationManager implements IAuthenticationMa        if (processDefinitionId == null) {          log.warn("No suitable process found for PendingReqId " + pendingReq.getPendingRequestId()); -        throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); +        throw new EaafException("process.02", null);        } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java index 0834aa7c..db13bf71 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java @@ -69,10 +69,21 @@ public class RequestStorage implements IRequestStorage {        // search invalid pending-request for errorHandling        IRequest invalidPendingRequest = null; -      try { +      try {                  if (StringUtils.isNotEmpty(e.getInvalidInternalPendingReqId())) { +          log.debug("Searching for expired pendingRequest with Id: {} ... ", e.getInvalidInternalPendingReqId());            invalidPendingRequest =                transactionStorage.get(e.getInvalidInternalPendingReqId(), IRequest.class); +           +          // If pendingReq. was found, set transactionID and sessionID to Logger +          TransactionIdUtils.setAllLoggingVariables(invalidPendingRequest); +           +          log.debug("{} expired pendingReq. Set it into Exception ...",  +              invalidPendingRequest != null ? "Find" : "Find NO "); +           +        } else { +          log.debug("Get no internal pendingRequestId. Expired pendingRequest can not be set"); +                    }        } catch (final EaafException e1) { @@ -213,7 +224,7 @@ public class RequestStorage implements IRequestStorage {        throws EaafException {      final IRequest pendingRequest = transactionStorage.get(internalPendingReqId, IRequest.class);      if (pendingRequest == null) { -      log.info("No PendingRequst found with pendingRequestID " + internalPendingReqId); +      log.debug("No PendingRequst found with pendingRequestID " + internalPendingReqId);        return null;      } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java index c2f85fef..142dcf28 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java @@ -22,9 +22,9 @@ package at.gv.egiz.eaaf.core.impl.idp.auth.builder;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.InputStream; -import java.util.ArrayList;  import java.util.Collection; -import java.util.Map.Entry; +import java.util.HashSet; +import java.util.Set;  import org.apache.commons.lang3.StringUtils;  import org.slf4j.Logger; @@ -54,6 +54,7 @@ import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.EaafParserException;  import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;  import at.gv.egiz.eaaf.core.exceptions.XPathException; +import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;  import at.gv.egiz.eaaf.core.impl.data.Pair;  import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData;  import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; @@ -72,9 +73,13 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati    public static final String CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING =        "configuration.bugfix.enable.idl.escaping"; -  protected Collection<String> includedToGenericAuthData = null; +  private static final String GENERIC_ATTR_CONTAINER = "processAuthParam;"; +      @Autowired    protected IConfigurationWithSP basicConfig; +   +  //protected ThreadLocal<Set<String>> includedToGenericAuthData = null; +      @Override    public IAuthData buildAuthenticationData(final IRequest pendingReq) @@ -137,7 +142,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati     */    protected abstract void buildServiceSpecificAuthenticationData(IAuthData authData,        IRequest pendingReq) throws EaafException; - +      /**     * Add generic E-ID information into already existing AuthData.     * @@ -169,7 +174,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati      // includedToGenericAuthData =      // authProcessData.getGenericSessionDataStorage().keySet();      // else -    includedToGenericAuthData = new ArrayList<>(); +    initializeThreadLocalVariable(authProcessData, new HashSet<>());      // ####################################################      // set general authData info's @@ -204,24 +209,51 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati      setCitizenCountryCode(internalAuthData, authProcessData);      // set generic authProcessData to authdata -    for (final Entry<String, Object> el : authProcessData.getGenericSessionDataStorage() -        .entrySet()) { -      if (el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) { -        log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey()); -        try { -          internalAuthData.setGenericData(el.getKey(), el.getValue()); - -        } catch (final EaafStorageException e) { -          log.warn("Can NOT set authData with key: {}", el.getKey(), null, e); +    authProcessData.getGenericSessionDataStream() +        .filter(el -> el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) +        .forEach(el -> { +          log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey()); +          try { +            internalAuthData.setGenericData(el.getKey(), el.getValue()); -        } +          } catch (final EaafStorageException e) { +            log.warn("Can NOT set authData with key: {}", el.getKey(), null, e); -      } +          }            +        });    +  } +  /** +   * Initialize Thread-Local holder for generic attributes set in authenticated session. +   *  +   * @param authProcessData Current authentication data holder +   * @param data {@link Collection} of generic attribute-names +   * @throws EaafAuthenticationException In case of an error  +   */ +  protected void initializeThreadLocalVariable(@NonNull final IAuthProcessDataContainer authProcessData, +      Set<String> data)  +      throws EaafAuthenticationException { +    try { +      authProcessData.setGenericDataToSession(GENERIC_ATTR_CONTAINER, data); +       +    } catch (EaafStorageException e) { +      throw new EaafAuthenticationException("builder.11", new Object[] { e.getMessage() }, e); +            } - +        } - +   +  /** +   * Initialize Thread-Local holder for generic attributes set in authenticated session. +   *  +   * @param set {@link Collection} of generic attribute-names +   */ +  @SuppressWarnings("unchecked") +  protected Set<String> getThreadLocalVariable(@NonNull final IAuthProcessDataContainer authProcessData) { +    return authProcessData.getGenericDataFromSession(GENERIC_ATTR_CONTAINER, Set.class); +     +  } +      /**     * Parse citzen country-code into AuthData.     * @@ -232,7 +264,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati     */    private void setCitizenCountryCode(final AuthenticationData authData,        final IAuthProcessDataContainer authProcessData) throws EaafAuthenticationException { -    includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME); +    getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME);      final String pvpCccAttr = authProcessData          .getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class);      if (StringUtils.isNotEmpty(pvpCccAttr)) { @@ -265,7 +297,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati     */    private void setQaaLevel(@NonNull final AuthenticationData authData,        @NonNull final IAuthProcessDataContainer authProcessData) { -    includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); +    getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME);      String currentLoA = null;      if (StringUtils.isNotEmpty(authProcessData.getQaaLevel())) {        currentLoA = authProcessData.getQaaLevel(); @@ -331,9 +363,10 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati      if (authProcessData.getGenericSessionDataStorage() != null          && !authProcessData.getGenericSessionDataStorage().isEmpty()) { -      includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet(); +      initializeThreadLocalVariable(authProcessData,  +          authProcessData.getGenericSessionDataStorage().keySet());            } else { -      includedToGenericAuthData = new ArrayList<>(); +      initializeThreadLocalVariable(authProcessData, new HashSet<>());      }      // #################################################### @@ -348,7 +381,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati      IIdentityLink idlFromPvpAttr = null;      final IIdentityLink identityLink = authProcessData.getIdentityLink();      if (identityLink != null) { -      parseBasicUserInfosFromIdl(authData, identityLink, includedToGenericAuthData); +      parseBasicUserInfosFromIdl(authData, identityLink, getThreadLocalVariable(authProcessData));      } else {        // identityLink is not direct in MOASession @@ -362,7 +395,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati          try {            idlStream = new ByteArrayInputStream(Base64Utils.decodeFromString(pvpAttrIdl));            idlFromPvpAttr = new SimpleIdentityLinkAssertionParser(idlStream).parseIdentityLink(); -          parseBasicUserInfosFromIdl(authData, idlFromPvpAttr, includedToGenericAuthData); +          parseBasicUserInfosFromIdl(authData, idlFromPvpAttr, getThreadLocalVariable(authProcessData));            // set identitylink into AuthProcessData            authProcessData.setIdentityLink(idlFromPvpAttr); @@ -375,7 +408,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati          } finally {            try { -            includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_IDENTITY_LINK_NAME); +            getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.EID_IDENTITY_LINK_NAME);              if (idlStream != null) {                idlStream.close();              } @@ -403,11 +436,11 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati              PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME, String.class));          // remove corresponding keys from genericSessionData if exists -        includedToGenericAuthData.remove(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME); -        includedToGenericAuthData.remove(PvpAttributeDefinitions.GIVEN_NAME_NAME); -        includedToGenericAuthData.remove(PvpAttributeDefinitions.BIRTHDATE_NAME); -        includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_NAME); -        includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME); +        getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME); +        getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.GIVEN_NAME_NAME); +        getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.BIRTHDATE_NAME); +        getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.EID_SOURCE_PIN_NAME); +        getThreadLocalVariable(authProcessData).remove(PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME);        }      } @@ -625,7 +658,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati     */    @Deprecated    private void parseBasicUserInfosFromIdl(final AuthenticationData authData, -      final IIdentityLink identityLink, final Collection<String> includedGenericSessionData) { +      final IIdentityLink identityLink, final Set<String> includedGenericSessionData) {      authData.setIdentificationValue(identityLink.getIdentificationValue());      authData.setIdentificationType(identityLink.getIdentificationType()); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java deleted file mode 100644 index fed4af32..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between - * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in - * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence - * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the Licence for the specific language governing permissions and limitations under - * the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text file for details on the - * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative - * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.gv.egiz.eaaf.core.impl.idp.auth.builder; - -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map.Entry; - -import javax.annotation.Nullable; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; -import at.gv.egiz.eaaf.core.impl.data.Pair; -import lombok.extern.slf4j.Slf4j; - - -/** - * Builder for the bPK, as defined in - * <code>"Ableitung f¨r die bereichsspezifische Personenkennzeichnung"</code> - * version <code>1.0.1</code> from - * <code>"reference.e-government.gv.at"</code>. - * - */ -@Slf4j -public class BpkBuilder { -     -  private static final String ERROR_MSG_WRONG_TARGET_FORMAT = "bPK-target format must be full URI"; -   -  /** -   * Calculates an area specific unique person-identifier from a baseID. -   * -   * @param baseID           baseId from user but never null -   * @param targetIdentifier target identifier for area specific identifier -   *                         calculation but never null -   * @return Pair consists of (unique person identifier for this target, -   *         targetArea) but never null -   * @throws EaafBuilderException if some input data are not valid -   */ -  public static Pair<String, String> generateAreaSpecificPersonIdentifier(final String baseID, -      final String targetIdentifier) throws EaafBuilderException { -    return generateAreaSpecificPersonIdentifier(baseID, EaafConstants.URN_PREFIX_BASEID, -        targetIdentifier); - -  } - -  /** -   * Calculates an area specific unique person-identifier from an unique -   * identifier with a specific type. -   * -   * @param baseID           baseId from user but never null -   * @param baseIdType       Type of the baseID but never null -   * @param targetIdentifier target identifier for area specific identifier -   *                         calculation but never null -   * @return Pair consists of (unique person identifier for this target, -   *         targetArea) but never null -   * @throws EaafBuilderException if some input data are not valid -   */ -  public static Pair<String, String> generateAreaSpecificPersonIdentifier(final String baseID, -      final String baseIdType, final String targetIdentifier) throws EaafBuilderException { -    if (StringUtils.isEmpty(baseID)) { -      throw new EaafBuilderException("builder.00", new Object[] { "baseID is empty or null" }, -          "BaseId is empty or null"); -    } - -    if (StringUtils.isEmpty(baseIdType)) { -      throw new EaafBuilderException("builder.00", -          new Object[] { "the type of baseID is empty or null" }, "Type of baseId is empty or null"); -    } - -    if (StringUtils.isEmpty(targetIdentifier)) { -      throw new EaafBuilderException("builder.00", -          new Object[] { "SP specific target identifier is empty or null" }, -          "SP specific target identifier is empty or null"); -    } - -    if (baseIdType.equals(EaafConstants.URN_PREFIX_BASEID)) { -      log.trace("Find baseID. Starting unique identifier caluclation for this target"); - -      if (targetIdentifier.startsWith(EaafConstants.URN_PREFIX_CDID)) { -        log.trace("Calculate bPK identifier for target: " + targetIdentifier); -        return Pair.newInstance(calculatebPKwbPK(baseID + "+" + targetIdentifier), -            targetIdentifier); - -      } else if (targetIdentifier.startsWith(EaafConstants.URN_PREFIX_WBPK)) { -        log.trace("Calculate  wbPK identifier for target: " + targetIdentifier); -        return Pair.newInstance(calculatebPKwbPK( -            baseID + "+" + normalizeBpkTargetIdentifierToCalculationFormat(targetIdentifier)), -            normalizeBpkTargetIdentifierToCommonFormat(targetIdentifier)); -         -      } else if (targetIdentifier.startsWith(EaafConstants.URN_PREFIX_EIDAS)) { -        log.trace("Calculate eIDAS identifier for target: " + targetIdentifier); -        final String[] splittedTarget = targetIdentifier.split("\\+"); -        final String cititzenCountryCode = splittedTarget[1]; -        final String eidasOutboundCountry = splittedTarget[2]; - -        if (cititzenCountryCode.equalsIgnoreCase(eidasOutboundCountry)) { -          log.warn("Suspect configuration FOUND!!! CitizenCountry equals DestinationCountry"); - -        } -        return buildEidasIdentifer(baseID, baseIdType, cititzenCountryCode, eidasOutboundCountry); - -      } else { -        throw new EaafBuilderException("builder.00", -            new Object[] { "Target identifier: " + targetIdentifier + " is NOT allowed or unknown" }, -            "Target identifier: " + targetIdentifier + " is NOT allowed or unknown"); -      } - -    } else { -      log.trace("BaseID is not of type " + EaafConstants.URN_PREFIX_BASEID -          + ". Check type against requested target ..."); -      if (baseIdType.equals(targetIdentifier)) { -        log.debug("Unique identifier is already area specific. Is nothing todo"); -        return Pair.newInstance(baseID, targetIdentifier); - -      } else { -        log.warn("Get unique identifier for target: " + baseIdType + " but target: " -            + targetIdentifier + " is required!"); -        throw new EaafBuilderException("builder.00", -            new Object[] { "Get unique identifier for target: " + baseIdType + " but target: " -                + targetIdentifier + " is required" }, -            "Get unique identifier for target: " + baseIdType + " but target: " + targetIdentifier -                + " is required"); - -      } -    } -  } - - - -  /** -   * Create an encrypted bPK. -   * -   * @param bpk       unencrypted bPK -   * @param target    bPK target in full form -   * @param publicKey Public-Key used for encryption -   * @return encrypted bPK -   * @throws EaafBuilderException In case of an error -   */ -  public static String encryptBpk(final String bpk, String target, final PublicKey publicKey) -      throws EaafBuilderException { -    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); -     -    if (!target.startsWith(EaafConstants.URN_PREFIX_WITH_COLON)) { -      throw new EaafBuilderException("builder.32",  -          null, ERROR_MSG_WRONG_TARGET_FORMAT); -       -    } -     -    target = normalizeBpkTargetIdentifierToCalculationFormat(target); - -    final String input = -        "V1::" + target + "::" + bpk + "::" + sdf.format(new Date()); -    // System.out.println(input); -    byte[] result; -    try { -      final byte[] inputBytes = input.getBytes("ISO-8859-1"); -      result = encrypt(inputBytes, publicKey); -      return new String(Base64Utils.encode(result), "ISO-8859-1").replaceAll("\r\n", ""); -      // return new String(Base64Utils.encode(result, -      // "ISO-8859-1")).replaceAll("\r\n", ""); - -    } catch (final Exception e) { -      throw new EaafBuilderException("bPK encryption FAILED", null, e.getMessage(), e); - -    } -  } - -  /** -   * Decrypt an encrypted bPK. -   * -   * @param encryptedBpk encrypted bPK -   * @param target       bPK target in full form -   * @param privateKey   private-key for decryption -   * @return bPK Pair consists of (unique person identifier for this target, -   *         targetArea) but never null -   * @throws EaafBuilderException In case of an error -   */ -  public static Pair<String, String> decryptBpk(final String encryptedBpk, String target, -      final PrivateKey privateKey) throws EaafBuilderException { -    String decryptedString; -     -    if (!target.startsWith(EaafConstants.URN_PREFIX_WITH_COLON)) { -      throw new EaafBuilderException("builder.32",  -          null, ERROR_MSG_WRONG_TARGET_FORMAT); -       -    } -     -    try { -      final byte[] encryptedBytes = Base64Utils.decode(encryptedBpk.getBytes("ISO-8859-1")); -      final byte[] decryptedBytes = decrypt(encryptedBytes, privateKey); -      decryptedString = new String(decryptedBytes, "ISO-8859-1"); - -    } catch (final Exception e) { -      throw new EaafBuilderException("bPK decryption FAILED", null, e.getMessage(), e); - -    } - -    String[] parts = decryptedString.split("::"); -    if (parts.length != 4) { -      log.trace("Encrypted bPK has value: {}", decryptedString); -      throw new EaafBuilderException("builder.31", new Object[] {parts.length},  -          "encBpk has a suspect format"); -       -    } -     -    final String sector = parts[1]; -    final String bPK = parts[2]; - -    if (target.equals(normalizeBpkTargetIdentifierToCommonFormat(sector))) { -      return Pair.newInstance(bPK, target); -       -    } else { -      throw new EaafBuilderException("builder.30", new Object[] {sector, target},  -          "Decrypted bPK-target does not match"); -       -    } -  } - -  /** -   * Normalize wbPK target identifier for FN, ZVR, and ERSB to XFN, XZVR, and XERSB. -   *  -   * <p>If the target is not of this types the target will be returned as it is</p> -   * @param targetIdentifier bPK input target -   * @return XFN, XZVR, XERSB, or targetIdentfier if no normalization is required  -   */ -  @Nullable -  public static String normalizeBpkTargetIdentifierToCommonFormat(@Nullable String targetIdentifier) { -    if (targetIdentifier != null  -        && !targetIdentifier.startsWith(EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X)) { -      for (Entry<String, String> mapper : EaafConstants.URN_WBPK_TARGET_X_TO_NONE_MAPPER.entrySet()) { -        if (targetIdentifier.startsWith(mapper.getValue())) { -          String wbpkTarget = mapper.getKey() + targetIdentifier.substring(mapper.getValue().length());  -          log.trace("Normalize wbPK target: {} to {}", targetIdentifier, wbpkTarget); -          return wbpkTarget; -         -        } -      } -    }  -     -    return targetIdentifier; -  } -   -  /** -   * Normalize wbPK target identifier for XFN, XZVR, and XERSB to bPK calculation format like, FN, ZVR, and ERSB. -   *  -   * <p>If the target is not of this types the target will be returned as it is</p> -   *  -   * @param targetIdentifier bPK input target -   * @return FN, ZVR, ERSB, or targetIdentfier if no normalization is required  -   */ -  @Nullable -  public static String normalizeBpkTargetIdentifierToCalculationFormat(@Nullable String targetIdentifier) { -    if (targetIdentifier != null && targetIdentifier.startsWith(EaafConstants.URN_PREFIX_WBPK)) { -      for (Entry<String, String> mapper : EaafConstants.URN_WBPK_TARGET_X_TO_NONE_MAPPER.entrySet()) { -        if (targetIdentifier.startsWith(mapper.getKey())) { -          String wbpkTarget = mapper.getValue() + targetIdentifier.substring(mapper.getKey().length());  -          log.trace("Find new wbPK target: {}. Replace it by: {}", targetIdentifier, wbpkTarget); -          return wbpkTarget; -       -        } -      } -    } -     -    return targetIdentifier;     -  } -   -  /** -   * Builds the eIDAS from the given parameters. -   * -   * @param baseId             baseID of the citizen -   * @param baseIdType         Type of the baseID -   * @param sourceCountry      CountryCode of that country, which build the eIDAs -   *                           ID -   * @param destinationCountry CountryCode of that country, which receives the -   *                           eIDAs ID -   * -   * @return Pair eIDAs/bPKType in a BASE64 encoding -   * @throws EaafBuilderException if some input data are not valid -   */ -  private static Pair<String, String> buildEidasIdentifer(final String baseId, -      final String baseIdType, final String sourceCountry, final String destinationCountry) -      throws EaafBuilderException { -    String bpk = null; -    String bpkType = null; - -    // check if we have been called by public sector application -    if (baseIdType.startsWith(EaafConstants.URN_PREFIX_BASEID)) { -      bpkType = EaafConstants.URN_PREFIX_EIDAS + sourceCountry + "+" + destinationCountry; -      log.debug("Building eIDAS identification from: [identValue]+" + bpkType); -      bpk = calculatebPKwbPK(baseId + "+" + bpkType); - -    } else { // if not, sector identification value is already calculated by BKU -      log.debug("eIDAS eIdentifier already provided by BKU"); -      bpk = baseId; -    } - -    if (StringUtils.isEmpty(bpk) || StringUtils.isEmpty(sourceCountry) -        || StringUtils.isEmpty(destinationCountry)) { -      throw new EaafBuilderException("builder.00", -          new Object[] { "eIDAS-ID", -              "Unvollständige Parameterangaben: identificationValue=" + bpk + ", Zielland=" -                  + destinationCountry + ", Ursprungsland=" + sourceCountry }, -          "eIDAS-ID: Unvollständige Parameterangaben: identificationValue=" + bpk + ", Zielland=" -              + destinationCountry + ", Ursprungsland=" + sourceCountry); -    } - -    log.trace("eIDAS pseudonym generation finished. "); -    final String eIdentifier = sourceCountry + "/" + destinationCountry + "/" + bpk; - -    return Pair.newInstance(eIdentifier, bpkType); -  } -   -  private static String calculatebPKwbPK(final String basisbegriff) throws EaafBuilderException { -    try { -      final MessageDigest md = MessageDigest.getInstance("SHA-1"); -      final byte[] hash = md.digest(basisbegriff.getBytes("ISO-8859-1")); -      final String hashBase64 = -          new String(Base64Utils.encode(hash), "ISO-8859-1").replaceAll("\r\n", ""); // Base64Utils.encode(hash); -      return hashBase64; - -    } catch (final Exception ex) { -      throw new EaafBuilderException("builder.00", new Object[] { "bPK/wbPK", ex.toString() }, -          ex.getMessage(), ex); - -    } - -  } - -  private static byte[] encrypt(final byte[] inputBytes, final PublicKey publicKey) -      throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, -      IllegalBlockSizeException, BadPaddingException { -    byte[] result; -    Cipher cipher = null; -    try { -      cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle - -    } catch (final NoSuchAlgorithmException e) { -      cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider -    } -    cipher.init(Cipher.ENCRYPT_MODE, publicKey); -    result = cipher.doFinal(inputBytes); - -    return result; -  } - -  private static byte[] decrypt(final byte[] encryptedBytes, final PrivateKey privateKey) -      throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, -      IllegalBlockSizeException, BadPaddingException { -    byte[] result; -    Cipher cipher = null; -    try { -      cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle - -    } catch (final NoSuchAlgorithmException e) { -      cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider - -    } -    cipher.init(Cipher.DECRYPT_MODE, privateKey); -    result = cipher.doFinal(encryptedBytes); -    return result; - -  } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java index 8eef4a8e..368652be 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java @@ -22,9 +22,11 @@ package at.gv.egiz.eaaf.core.impl.idp.auth.data;  import java.text.ParseException;  import java.text.SimpleDateFormat;  import java.util.Date; -import java.util.HashMap;  import java.util.Map; +import java.util.Map.Entry;  import java.util.TimeZone; +import java.util.stream.Collectors; +import java.util.stream.Stream;  import javax.annotation.Nullable; @@ -264,16 +266,20 @@ public class AuthProcessDataWrapper     * getGenericSessionDataStorage()     */    @Override -  public Map<String, Object> getGenericSessionDataStorage() { -    final Map<String, Object> result = new HashMap<>(); -    for (final Map.Entry<String, Object> el : authProcessData.entrySet()) { -      if (el.getKey().startsWith(GENERIC_PREFIX)) { -        result.put(el.getKey().substring(GENERIC_PREFIX.length()), el.getValue()); -      } - -    } - -    return result; +  public Map<String, Object> getGenericSessionDataStorage() {     +    return authProcessData.entrySet().stream() +        .filter(el -> el.getKey().startsWith(GENERIC_PREFIX)) +        .collect( +            Collectors.toMap( +                el -> el.getKey().substring(GENERIC_PREFIX.length()),  +                value -> value.getValue())); +     +  } +   +  @Override +  public Stream<Entry<String, Object>> getGenericSessionDataStream() { +    return getGenericSessionDataStorage().entrySet().stream(); +        }    /* diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/EidAuthProcessDataWrapper.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/EidAuthProcessDataWrapper.java new file mode 100644 index 00000000..48a2206b --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/EidAuthProcessDataWrapper.java @@ -0,0 +1,34 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.data; + +import java.util.Map; + +import at.gv.egiz.eaaf.core.api.idp.auth.data.IEidAuthProcessData; + +/** + * Authentication session-data that adds ID Austria specific information.   + *  + * @author tlenz + * + */ +public class EidAuthProcessDataWrapper extends AuthProcessDataWrapper implements IEidAuthProcessData { + +  private static final String VALUE_INTERNAL_TEST_IDENTITY_PROCESS = "direct_is_testidentity"; +   +  public EidAuthProcessDataWrapper(Map<String, Object> authProcessData) { +    super(authProcessData); +     +  } +   +  @Override +  public boolean isTestIdentity() { +    return wrapStoredObject(VALUE_INTERNAL_TEST_IDENTITY_PROCESS, false, Boolean.class); + +  } + +  @Override +  public void setTestIdentity(boolean flag) { +    authProcessData.put(VALUE_INTERNAL_TEST_IDENTITY_PROCESS, flag); + +  } +   +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java index ee1037a1..8327b544 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java @@ -23,15 +23,20 @@ import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.Serializable;  import java.security.PublicKey; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date;  import javax.xml.transform.TransformerException; -import org.w3c.dom.Element; -  import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;  import at.gv.egiz.eaaf.core.impl.utils.DomUtils;  import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; +import org.w3c.dom.Element; + +import lombok.extern.slf4j.Slf4j; +  /**   * Data contained in an identity link issued by BMI, relevant to the MOA ID   * component. <br> @@ -41,10 +46,13 @@ import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;   * @author Paul Ivancsics   * @version $Id$   */ +@Slf4j  public class IdentityLink implements Serializable, IIdentityLink {    private static final long serialVersionUID = 1L; +  public static final String PATTERN_ISSUE_INSTANT = "yyyy-MM-dd'T'HH:mm:ssXXX"; +    /**     * <code>"identificationValue"</code> is the translation of     * <code>"Stammzahl"</code>. @@ -372,6 +380,23 @@ public class IdentityLink implements Serializable, IIdentityLink {      return issueInstant;    } +  @Override +  public Date getIssueInstantDate() { +    final SimpleDateFormat f = new SimpleDateFormat(PATTERN_ISSUE_INSTANT); +    try { +      if (issueInstant != null) { +        return f.parse(issueInstant); + +      } + +    } catch (final ParseException e) { +      log.error("Can NOT parse Date from String: {}", issueInstant, null, e); + +    } + +    return null; +  } +    /*     * (non-Javadoc)     * diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java index 3d093a9f..5b5d0aa8 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java @@ -45,6 +45,7 @@ import org.springframework.core.io.ResourceLoader;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.EaafEventCodes;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; @@ -155,6 +156,36 @@ public abstract class AbstractAuthServletTask extends AbstractTask {    }    /** +   * Stopping the current authentication process by User decision. +   *  +   * @param executionContext Current execution context +   * @param request Http request +   * @param response Http response +   * @throws TaskExecutionException In case of an error during process-stopping +   */ +  protected void stopProcessFromUserDecision(final ExecutionContext executionContext, +      final HttpServletRequest request, final HttpServletResponse response) +      throws TaskExecutionException { +    try { +      revisionsLogger.logEvent(pendingReq, EaafEventCodes.PROCESS_STOPPED_BY_USER); +      pendingReq.setAbortedByUser(true); +      pendingReq.setAuthenticated(false); +      performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); + +      log.trace("Set process-cancelation flag"); +      executionContext.setCanceleProcessFlag(); + +    } catch (final EaafException e) { +      throw new TaskExecutionException(pendingReq, e.getMessage(), e); + +    } catch (final Exception e) { +      log.warn("Stopping auth.process FAILED", e); +      throw new TaskExecutionException(pendingReq, e.getMessage(), e); + +    } +  } +   +  /**     * Parses the request input stream for parameters, assuming parameters are     * encoded UTF-8 (no standard exists how browsers should encode them).     * @@ -268,4 +299,21 @@ public abstract class AbstractAuthServletTask extends AbstractTask {        return url + "&" + param;      }    } + +  /** +   * Get a {@link Boolean} parameter from http request. +   * +   * @param httpReq http Request object +   * @param paramName http Parameter name +   * @return <code>true</code> if the parameter exists and the <code>Boolean.parseBoolean(value)</code> +   *     evaluates to <code>true</code>, otherwise <code>false</code> +   */ +  protected boolean evaluteBooleanReqParam(final HttpServletRequest httpReq, final String paramName) { +    final String value = httpReq.getParameter(paramName); +    if (value != null) { +      return Boolean.parseBoolean(value); +    } else { +      return false; +    } +  }  } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java index c4f1b505..c1593cb1 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java @@ -100,7 +100,7 @@ public class ModuleRegistration {     */    private void initSpringModules() {      log.debug("Discovering Spring modules."); -    final Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class); +    final Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class);          for (final AuthModule module : modules.values()) {        registerModuleProcessDefinitions(module);        priorizedModules.add(module); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java new file mode 100644 index 00000000..e41905a6 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java @@ -0,0 +1,111 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.services; + +import java.text.MessageFormat; +import java.util.HashSet; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import lombok.Builder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DefaultErrorService implements IErrorService { +  private static final String TECH_LOG_MSG = "errorCode={0} Message={1}";   +  private static final String CONFIG_PROP_LOGGER_ON_INFO_LEVEL = "core.logging.level.info.errorcodes"; + +  @Autowired IConfiguration basicConfig; +  @Autowired IStatusMessenger statusMessager;  + +  private final HashSet<String> logOnInfoLevel = new HashSet<>(); +   +  @Override +  public String getExternalCodeFromInternal(String internalCode) { +    return statusMessager.mapInternalErrorToExternalError(internalCode); +     +  } + +  @Override +  public IHandleData createHandleData(Throwable throwable, boolean supportRedirctToSp) throws EaafException { +    String internalErrorId = extractInternalErrorCode(throwable);     +     +    return HandleData.builder() +        .throwable(throwable) +        .internalErrorCode(internalErrorId) +        .actionType(ActionType.NO_TICKET) +        .logLevel(logOnInfoLevel.contains(internalErrorId) ? LogLevel.INFO : LogLevel.WARN) +        .build();    +     +  } + +  @Override +  public void displayErrorData(ModifyableGuiBuilderConfiguration c, IHandleData errorData,  +      HttpServletRequest httpReq) throws EaafException { +    log.trace("Do nothing because Tickets are not supported by: {}", DefaultErrorService.class.getName()); +         +  } +   +  private String extractInternalErrorCode(Throwable throwable) { +    Throwable originalException; +    if (throwable instanceof TaskExecutionException +        && ((TaskExecutionException) throwable).getOriginalException() != null) { +      originalException = ((TaskExecutionException) throwable).getOriginalException(); + +    } else { +      originalException = throwable; + +    } + +    if (!(originalException instanceof EaafException)) { +      return IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC; + +    } else { +      return ((EaafException) originalException).getErrorId(); + +    } +  } +   +  @PostConstruct +  private void initialize() throws EaafException { +    log.info("initErrorTicketService"); + +    logOnInfoLevel.addAll(KeyValueUtils.getListOfCsvValues( +        basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL))); +    log.info("Set errorCodes={} to LogLevel:INFO", String.join(",", logOnInfoLevel)); +     +  } +   +  @Builder +  static class HandleData implements IHandleData { +     +    @Getter +    private String errorIdTokenForRedirect; +     +    @Getter +    private final Throwable throwable; +     +    @Getter +    private String internalErrorCode; +     +    @Getter +    private ActionType actionType; + +    @Getter +    private LogLevel logLevel; +     +    public String getPreFormatedErrorMessage() { +      return MessageFormat.format(TECH_LOG_MSG, internalErrorCode, throwable.getMessage()); +       +    } +     +  } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java new file mode 100644 index 00000000..b6bc1056 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java @@ -0,0 +1,164 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.services; + +import javax.annotation.Nonnull; +import javax.servlet.http.HttpServletRequest; + +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +public interface IErrorService { +   +  /** +   * Describes the kind of action that should be taken. +   */ +  enum ActionType { +    TICKET("ticket"), NO_TICKET("no_ticket"), ERRORPAGE("errorpage"); + +    private final String name; + +    ActionType(final String text) { +      this.name = text; +    } + + +    /** +     * Get flow type for error-handling from String representation. +     * +     * @param s Config parameter +     * @return Error-handling flow +     */ +    public static ActionType fromString(final String s) { +      try { +        return ActionType.valueOf(s.toUpperCase()); + +      } catch (IllegalArgumentException | NullPointerException e) { +        return null; +         +      } +    } +     +    @Override +    public String toString() { +      return name; +    } +  } + +  /** +   * Defines the LogLevel for this types of errors. +   */ +  enum LogLevel { +    ERROR("error"), WARN("warn"), INFO("info"), DEBUG("debug"); + +    private final String level; + +    LogLevel(final String logLevel) { +      this.level = logLevel; +       +    } + + +    /** +     * Get the log-level from String representation. +     * +     * @param s Config parameter +     * @return Log-Level from configuration or ERROR as backup +     */ +    public static LogLevel fromString(final String s) { +      try { +        return LogLevel.valueOf(s.toUpperCase()); + +      } catch (IllegalArgumentException | NullPointerException e) { +        return LogLevel.ERROR;         +         +      } +    } +     +    @Override +    public String toString() { +      return level; +    } +     +  } +   +  String PARAM_GUI_TICKET = "supportTicket"; +  String PARAM_GUI_REDIRECT = "redirectLink"; + +  /** +   * Maps internal error codes to external ones. +   * @param internalCode internal error code +   * @return external error code +   */ +  @Nonnull +  String getExternalCodeFromInternal(@Nonnull String internalCode); + +  /** +   * Creates error handling data. +   * +   * @param throwable Error that should be handled  +   * @param supportRedirctToSp <code>true</code> if the current process-state supports redirect  +   *     to Service-Provider, otherwise <code>false</code> +   * @return Information how the error should be handled  +   * @throws EaafException In case of an internal error +   */ +  @Nonnull +  IHandleData createHandleData(@Nonnull Throwable throwable, boolean supportRedirctToSp) throws EaafException; + +  /** +   * Displays the error using suitable errordata. +   * +   * @param c         guibuilder +   * @param errorData Data to handle +   * @param httpReq Current HTTP request  +   * @throws EaafException In case of an internal error +   */ +  void displayErrorData(@Nonnull ModifyableGuiBuilderConfiguration c, @Nonnull IErrorService.IHandleData errorData,  +      @Nonnull HttpServletRequest httpReq) throws EaafException; + +  /** +   * Contains all the Model data for Error Handling. +   */ +  interface IHandleData { +     +    /** +     * Get a new pendingReqId that can be used to store the error for SP forwarding. +     *  +     * @return errorToken as pendingRequest +     */ +    String getErrorIdTokenForRedirect(); +     +    /** +     * Describes the kind of action that should be taken. +     * +     * @return The appropriate action +     */ +    ActionType getActionType(); + +    /** +     * Get internal errorCode describing the problem. +     * +     * @return internal error Code. +     */ +    String getInternalErrorCode(); + +    /** +     * Get the original throwable of the error. +     * +     * @return causing throwable +     */ +    Throwable getThrowable(); +    +    /** +     * Get the log-level for this internal errorId. +     *  +     * @return Level to Log the error +     */ +    LogLevel getLogLevel(); +     +    /**  +     * Get pre-formated text for log message. +     *  +     * @return log message +     */ +    String getPreFormatedErrorMessage(); +  } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java index 5f84d118..ca2c92b1 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java @@ -15,16 +15,13 @@   * This product combines work with different licenses. See the "NOTICE" text file for details on the   * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative   * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ + */  package at.gv.egiz.eaaf.core.impl.idp.auth.services;  import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.List; +import javax.annotation.PostConstruct;  import javax.naming.ConfigurationException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -32,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang3.ArrayUtils;  import org.apache.commons.lang3.StringUtils;  import org.apache.commons.text.StringEscapeUtils; +import org.owasp.encoder.Encode;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; @@ -39,12 +37,14 @@ import org.springframework.context.ApplicationContext;  import org.springframework.lang.NonNull;  import org.springframework.lang.Nullable;  import org.springframework.stereotype.Service; +import org.springframework.util.SerializationUtils;  import at.gv.egiz.components.eventlog.api.EventConstants;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.ExceptionContainer;  import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration;  import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory;  import at.gv.egiz.eaaf.core.api.gui.IGuiFormBuilder; @@ -60,6 +60,7 @@ import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService  import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;  import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;  import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;  import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;  import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;  import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; @@ -72,6 +73,9 @@ import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException;  import at.gv.egiz.eaaf.core.impl.data.Pair;  import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration;  import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.ActionType; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.IHandleData; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.LogLevel;  import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController;  import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;  import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; @@ -80,9 +84,6 @@ import at.gv.egiz.eaaf.core.impl.utils.ServletUtils;  public class ProtocolAuthenticationService implements IProtocolAuthenticationService {    private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class); -  private static final List<String> ERROR_LOGGER_ON_INFO_LEVEL = -      Arrays.asList(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP); -    @Autowired(required = true)    private ApplicationContext applicationContext;    @Autowired(required = true) @@ -98,13 +99,21 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer    @Autowired(required = true)    IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; +  @Autowired(required = true) +  private IErrorService errorTicketService; +    @Autowired(required = false)    private ISsoManager ssoManager; +    @Autowired    private IStatisticLogger statisticLogger; +    @Autowired    private IRevisionLogger revisionsLogger; +  @Autowired(required = true) +  protected ITransactionStorage transactionStorage; +    private IGuiFormBuilder guiBuilder;    /* @@ -130,8 +139,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer          final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration();          if (oaParam == null) { -          throw new EaafAuthenticationException( -              IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, +          throw new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG,                new Object[] { pendingReq.getSpEntityId() });          } @@ -142,8 +150,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer            finalizeAuthentication(req, resp, pendingReq);            // transaction is finished, log transaction finished event -          revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, -              pendingReq.getUniqueTransactionIdentifier()); +          revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq +              .getUniqueTransactionIdentifier());          } @@ -170,7 +178,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer    @Override    public void finalizeAuthentication(final HttpServletRequest req, final HttpServletResponse resp,        final IRequest pendingReq) throws EaafException, IOException { -    log.debug("Finalize PendingRequest with ID " + pendingReq.getPendingRequestId()); +    log.debug("Finalize PendingRequest with ID={} ", pendingReq.getPendingRequestId());      try {        // check if pending-request has 'abortedByUser' flag set @@ -178,15 +186,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer          // send authentication aborted error to Service Provider          buildProtocolSpecificErrorResponse(              new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, -                new Object[] {}), -            req, resp, pendingReq); - -        // do not remove the full active SSO-Session -        // in case of only one Service-Provider authentication request is aborted -        if (!pendingReq.needSingleSignOnFunctionality()) { -          requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); - -        } +                new Object[] {}), req, +            resp, pendingReq);          // check if pending-request are authenticated        } else if (pendingReq.isAuthenticated() && !pendingReq.isNeedUserConsent()) { @@ -194,11 +195,12 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer        } else {          // suspect state: pending-request is not aborted but also are not authenticated -        log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", -            pendingReq.isAuthenticated(), pendingReq.isNeedUserConsent()); +        log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", pendingReq +            .isAuthenticated(), +            pendingReq.isNeedUserConsent());          if (pendingReq.isNeedUserConsent()) { -          log.error( -              "PendingRequest NEEDS user-consent. Can NOT fininalize authentication --> Abort authentication process!"); +          log.error("PendingRequest NEEDS user-consent. " +              + "Can NOT fininalize authentication --> Abort authentication process!");          } else {            log.error("PendingRequest is NOT authenticated --> Abort authentication process!"); @@ -210,66 +212,106 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer        }      } catch (final Exception e) { -      log.error("Finalize authentication protocol FAILED.", e); +      log.info("Finalize authentication protocol FAILED. Reason: {}", e.getMessage());        buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); +    } finally { +      // remove pending-request +      requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); +      revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq +          .getUniqueTransactionIdentifier());      } -    // remove pending-request -    requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); -    revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, -        pendingReq.getUniqueTransactionIdentifier()); -    }    @Override -  public void buildProtocolSpecificErrorResponse(final Throwable throwable, -      final HttpServletRequest req, final HttpServletResponse resp, final IRequest protocolRequest) -      throws EaafException, IOException { +  public void buildProtocolSpecificErrorResponse(final Throwable throwable, final HttpServletRequest req, +      final HttpServletResponse resp, final IRequest protocolRequest) throws EaafException, IOException {      try { +       +      final IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, true); -      final Class<?> clazz = Class.forName(protocolRequest.requestedModule()); - -      if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) { -        log.error( -            "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); -        throw new Exception( -            "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +      // log Error to technical log +      logExceptionToTechnicalLog(errorData); -      } - -      final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); +      // log Error Message +      statisticLogger.logErrorOperation(throwable, protocolRequest); + +      // write revision log entries +      revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, +          protocolRequest.getUniqueTransactionIdentifier()); + +      if (ActionType.TICKET.equals(errorData.getActionType()) +          || ActionType.ERRORPAGE.equals(errorData.getActionType())) { + +        if (errorData.getErrorIdTokenForRedirect() != null) { +          // Put pending request +          final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); +          final byte[] serialized = SerializationUtils.serialize(exceptionContainer); +          log.debug("Put error into cache to support SP forwarding ... "); +          String internalErrorToken = pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks( +              errorData.getErrorIdTokenForRedirect()); +          log.trace("errorIdToken: {}", internalErrorToken); +          transactionStorage.put(internalErrorToken, serialized, -1); +           +        } else { +          log.debug("No errorTokenId. Forwarding to SP will not be available"); +           +        } -      if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) { +        // render GUI +        displayException(req, resp, errorData); -        // log Error to technical log -        logExceptionToTechnicalLog(throwable); +      } else { +        final IModulInfo handlingModule = extractShibbolethHandling(protocolRequest, applicationContext); +        if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) { +          log.debug("Error-response to SP successfully written"); -        // log Error Message -        statisticLogger.logErrorOperation(throwable, protocolRequest); +        } else { +          log.info("Error-response to SP FAILED. Writing error message into GUI ... "); +          displayException(req, resp, errorData); -        // write revision log entries -        revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, -            protocolRequest.getUniqueTransactionIdentifier()); +        } +      } -        return; +    } catch (final Throwable e) { +      // if building error response results in error, we try with with +      // handleErrorNoRedirect +      log.error("ErrorHandling has an internel error. Show process-error in GUI ... ", e);       +      handleErrorNoRedirect(throwable, req, resp, false); -      } else { -        handleErrorNoRedirect(throwable, req, resp, true); +    } +  } -      } +  /** +   * Retrieves shibboleth module info. +   * +   * @param protocolRequest    current request +   * @param applicationContext spring context +   * @return IModulInfo +   * @throws ClassNotFoundException If no shibboleth handling implementation found +   */ +  public static IModulInfo extractShibbolethHandling(IRequest protocolRequest, +      ApplicationContext applicationContext) +      throws ClassNotFoundException { +    final Class<?> clazz = Class.forName(protocolRequest.requestedModule()); -    } catch (final Throwable e) { -      handleErrorNoRedirect(throwable, req, resp, true); +    if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) { +      log.error("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +      throw new ClassCastException( +          "Requested protocol module Class is NULL or does not implement the IModulInfo interface.");      } +    return (IModulInfo) applicationContext.getBean(clazz);    }    @Override    public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req, -      final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) -      throws IOException, EaafException { +      final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws EaafException, +      IOException { + +    final IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, false);      // log Exception into statistic database      if (writeExceptionToStatisticLog) { @@ -277,61 +319,61 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer      }      // write errror to console -    logExceptionToTechnicalLog(throwable); +    logExceptionToTechnicalLog(errorData); + +    // render GUI +    displayException(req, resp, errorData); + +  } + +  private void logExceptionToTechnicalLog(IHandleData errorData) { +    // In case of a TaskExecutionException, which is only a container for +    // process-errors, +    // extract internal exception + +    // Log exception +    if (!(errorData.getThrowable() instanceof EaafException) +        || LogLevel.ERROR.equals(errorData.getLogLevel())) { +      log.error(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + +    } else if (LogLevel.WARN.equals(errorData.getLogLevel())) { +      log.warn(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + +    } else if (LogLevel.INFO.equals(errorData.getLogLevel())) { +      log.info(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + +    } else if (LogLevel.DEBUG.equals(errorData.getLogLevel())) { +      log.debug(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); -    // return error to Web browser -    if (throwable instanceof EaafException || throwable instanceof ProcessExecutionException) { -      internalMoaidExceptionHandler(req, resp, (Exception) throwable, false);      } else { -      // write generic message for general exceptions -      final String msg = -          statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); -      writeHtmlErrorResponse(req, resp, msg, "9199", null, (Exception) throwable); +      log.warn("Get unsupported LogLevelType: {}. Use {} as default", +          errorData.getLogLevel(), LogLevel.ERROR); +      log.error(errorData.getPreFormatedErrorMessage(), errorData.getThrowable());      } -    }    @Override    public void forwardToErrorHandler(Pair<IRequest, Throwable> errorToHandle, String errorKey,        final HttpServletRequest req, final HttpServletResponse resp) throws GuiBuildException { -    IGuiBuilderConfiguration parentHopGuiConfig =  -        evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(), errorKey); +    final IGuiBuilderConfiguration parentHopGuiConfig = evaluateRequiredErrorHandlingMethod(errorToHandle +        .getFirst(), +        errorKey);      if (parentHopGuiConfig != null) {        log.trace("iFrame to parent hop requested. Building GUI step for error handling ... ");        guiBuilder.build(req, resp, parentHopGuiConfig, "iFrame-to-parent"); -       -    } else {       + +    } else {        // build up redirect URL        final String redirectUrl = generateErrorRedirectUrl(req, errorKey);        resp.setContentType("text/html");        resp.setStatus(302);        resp.addHeader("Location", redirectUrl); -      log.debug("REDIRECT TO: " + redirectUrl); -       +      log.debug("REDIRECT TO: {}", redirectUrl); +      }    } -   -  private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) { -    if (first != null && first.isProcessInIframe()) { -      return guiConfigFactory.getDefaultIFrameParentHopGui(first,  -          "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, -          errorId); -     -    } -    return null; -  } -   -  private String generateErrorRedirectUrl(final HttpServletRequest req, String errorKey) { -    String redirectUrl = null; -    redirectUrl = ServletUtils.getBaseUrl(req); -    redirectUrl += "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" -        + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; -    return redirectUrl; - -  } -      public void setGuiBuilder(final IGuiFormBuilder guiBuilder) {      this.guiBuilder = guiBuilder;    } @@ -339,15 +381,14 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer    /**     * Finalize the requested protocol operation.     * -   * @param httpReq         HttpServletRequest -   * @param httpResp        HttpServletResponse -   * @param protocolRequest Authentication request which is actually in process -   * @param moaSession      MOASession object, which is used to generate the -   *                        protocol specific authentication information +   * @param req        HttpServletRequest +   * @param resp       HttpServletResponse +   * @param pendingReq Authentication request which is actually in process     * @throws Exception In case of an error     */    protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, -      final HttpServletResponse resp, final IRequest pendingReq) throws Exception { +      final HttpServletResponse resp, +      final IRequest pendingReq) throws Exception {      String newSsoSessionId = null; @@ -369,8 +410,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer      final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq);      // execute the protocol-specific action -    final SloInformationInterface sloInformation = -        executeProtocolSpecificAction(req, resp, pendingReq, authData); +    final SloInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, +        authData);      // Store OA specific SSO session information if an SSO cookie is set      if (StringUtils.isNotEmpty(newSsoSessionId)) { @@ -390,21 +431,24 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer      }      // Advanced statistic logging -    statisticLogger.logSuccessOperation(pendingReq, authData, -        StringUtils.isNotEmpty(newSsoSessionId)); +    statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSsoSessionId)); + +  } + +  @PostConstruct +  private void initializer() { +    log.trace("Initializing {} ...", ProtocolAuthenticationService.class.getName());    }    /**     * Executes the requested protocol action.     * -   * @param httpReq         HttpServletRequest -   * @param httpResp        HttpServletResponse -   * @param protocolRequest Authentication request which is actually in process -   * @param authData        Service-provider specific authentication data -   * +   * @param httpReq    HttpServletRequest +   * @param httpResp   HttpServletResponse +   * @param pendingReq Authentication request which is actually in process +   * @param authData   Service-provider specific authentication data     * @return Return Single LogOut information or null if protocol supports no SSO -   *     * @throws Exception in case of an error     */    private SloInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq, @@ -416,7 +460,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer        if (clazz == null || !IAction.class.isAssignableFrom(clazz)) {          log.error(              "Requested protocol-action processing Class is NULL or does not implement the IAction interface."); -        throw new Exception( +        throw new ClassCastException(              "Requested protocol-action processing Class is NULL or does not implement the IAction interface.");        } @@ -427,153 +471,130 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer      } catch (final ClassNotFoundException e) {        log.error(            "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); -      throw new Exception( -          "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); +      throw new ClassNotFoundException( +          "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface.", +          e);      }    } -  /** -   * Write a Exception to the MOA-ID-Auth internal technical log. -   * -   * @param loggedException Exception to log -   */ -  protected void logExceptionToTechnicalLog(final Throwable loggedException) { -    if (!(loggedException instanceof EaafException -        || loggedException instanceof ProcessExecutionException)) { -      log.error("Receive an internal error: Message=" + loggedException.getMessage(), -          loggedException); - -    } else { -      if (loggedException instanceof EaafAuthenticationException && ERROR_LOGGER_ON_INFO_LEVEL -          .contains(((EaafAuthenticationException) loggedException).getErrorId())) { -        if (log.isDebugEnabled() || log.isTraceEnabled()) { -          log.info(loggedException.getMessage(), loggedException); - -        } else { -          log.info(loggedException.getMessage()); - -        } - -      } else { -        if (log.isDebugEnabled() || log.isTraceEnabled()) { -          log.warn(loggedException.getMessage(), loggedException); - -        } else { -          log.warn(loggedException.getMessage()); - -        } -      } -    } -  } +  // private void writeHtmlErrorResponse(@NonNull final HttpServletRequest +  // httpReq, +  // @NonNull final HttpServletResponse httpResp, @NonNull final String msg, +  // @NonNull final String errorCode, +  // @Nullable final Object[] params, String externalErrorCode) throws +  // EaafException { +  // this.writeHtmlErrorResponse(httpReq, httpResp, msg, errorCode, params, +  // externalErrorCode, null, null); +  // }    private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, -      @NonNull final HttpServletResponse httpResp, @NonNull final String msg, -      @NonNull final String errorCode, @Nullable final Object[] params, -      @NonNull final Exception error) throws IOException, EaafException { +      @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode, +      @Nullable final Object[] params, String externalErrorCode, IErrorService.IHandleData errorData) +      throws EaafException {      try { -      final IGuiBuilderConfiguration config = -          guiConfigFactory.getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq)); +      final IGuiBuilderConfiguration config = guiConfigFactory +          .getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq)); +              String[] errorCodeParams = null;        if (params == null) {          errorCodeParams = new String[] {}; +                } else {          errorCodeParams = new String[params.length];          for (int i = 0; i < params.length; i++) {            if (params[i] != null) { -            errorCodeParams[i] = params[i].toString(); +            /* replace all single-quotes by two single-quotes for escaping purposes to mitigate +             * Thymeleaf error in:  +             *    th:text="${#messages.msgWithParams('__${msg.errorCode}__', '__${msg.errorParams}__')}" +             */             +            errorCodeParams[i] = params[i].toString().replaceAll("'", "''"); +                                    } else {              errorCodeParams[i] = "null"; +                        } -          }        }        // add errorcode and errormessage        if (config instanceof ModifyableGuiBuilderConfiguration) { -        ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( -            AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg); -        ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( -            AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode); -        ((ModifyableGuiBuilderConfiguration) config).putCustomParameterWithOutEscaption( -            AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODEPARAMS, -            ArrayUtils.toString(errorCodeParams)); - -        // add stacktrace if debug is enabled -        if (log.isTraceEnabled()) { -          ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( -              AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORSTACKTRACE, -              getStacktraceFromException(error)); - -        } +        final ModifyableGuiBuilderConfiguration c = (ModifyableGuiBuilderConfiguration) config; +        c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg); +        c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, +            errorCode); +        // TODO: should we keep the internal errorcode secret? +        c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, +            PARAM_GUI_EXTERNAL_ERRORCODE, +            externalErrorCode); +        c.putCustomParameterWithOutEscaption(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, +            PARAM_GUI_ERRORCODEPARAMS, ArrayUtils.toString(errorCodeParams)); +        errorTicketService.displayErrorData(c, errorData, httpReq);        } else { -        log.info( -            "Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); +        log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable ");        }        guiBuilder.build(httpReq, httpResp, config, "Error-Message");      } catch (final GuiBuildException e) {        log.warn("Can not build error-message GUI.", e); -      throw new EaafException("9199", null, e); +      throw new EaafException("internal.99", new Object[] {e.getMessage()}, e);      }    } -  private String getStacktraceFromException(final Exception ex) { -    final StringWriter errors = new StringWriter(); -    ex.printStackTrace(new PrintWriter(errors)); -    return errors.toString(); +  private void displayException(final HttpServletRequest req, final HttpServletResponse resp, +      final IErrorService.IHandleData errorData) throws IOException, EaafException { +    final Throwable e = errorData.getThrowable(); +    final String internalErrorCode = errorData.getInternalErrorCode(); -  } - -  private void internalMoaidExceptionHandler(final HttpServletRequest req, -      final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog) -      throws IOException, EaafException { +    // send error response      if (e instanceof ProtocolNotActiveException) { -      resp.getWriter().write(e.getMessage()); +      resp.getWriter().write(Encode.forHtml(e.getMessage()));        resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8);        resp.sendError(HttpServletResponse.SC_FORBIDDEN,            StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); -    } else if (e instanceof AuthnRequestValidatorException) { -      final AuthnRequestValidatorException ex = (AuthnRequestValidatorException) e; -      // log Error Message -      if (writeExceptionToStatisicLog) { -        statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); -      } - +    } else if (e instanceof AuthnRequestValidatorException || e instanceof InvalidProtocolRequestException +        || e instanceof ProcessExecutionException || e instanceof ConfigurationException) {        // write error message -      // writeBadRequestErrorResponse(req, resp, (EAAFException) e); -      writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), -          null, e); - -    } else if (e instanceof InvalidProtocolRequestException) { -      // send error response -      // writeBadRequestErrorResponse(req, resp, (EAAFException) e); -      writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), -          null, e); - -    } else if (e instanceof ConfigurationException) { -      // send HTML formated error message -      writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), -          null, e); +      writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null, +          statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData);      } else if (e instanceof EaafException) {        // send HTML formated error message -      writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), -          ((EaafException) e).getParams(), e); +      writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, ((EaafException) e).getParams(), +          statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData); -    } else if (e instanceof ProcessExecutionException) { -      // send HTML formated error message -      writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), -          null, e); +    } else { +      // write generic message for general exceptions +      final String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); +      writeHtmlErrorResponse(req, resp, msg, internalErrorCode, null, +          statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData);      } +  } + +  private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) { +    if (first != null && first.isProcessInIframe()) { +      return guiConfigFactory +          .getDefaultIFrameParentHopGui(first, ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, +              errorId); + +    } +    return null; +  } + +  private String generateErrorRedirectUrl(final HttpServletRequest req, String errorKey) { +    String redirectUrl = null; +    redirectUrl = ServletUtils.getBaseUrl(req); +    redirectUrl += ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" +        + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; +    return redirectUrl;    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/AttributeBuilderRegistration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/AttributeBuilderRegistration.java new file mode 100644 index 00000000..b554ad05 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/AttributeBuilderRegistration.java @@ -0,0 +1,88 @@ +package at.gv.egiz.eaaf.core.impl.idp.builder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.ServiceLoader; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AttributeBuilderRegistration { + +  private static HashMap<String, IAttributeBuilder> builders; +   +  private static ServiceLoader<IAttributeBuilder> attributBuilderLoader = +      ServiceLoader.load(IAttributeBuilder.class); + +  private static void addBuilder(final IAttributeBuilder builder) { +    builders.put(builder.getName(), builder); +  } + +  static { +    builders = new HashMap<>(); + +    log.info("Loading protocol attribut-builder modules:"); +    if (attributBuilderLoader != null) { +      final Iterator<IAttributeBuilder> moduleLoaderInterator = attributBuilderLoader.iterator();            +      while (moduleLoaderInterator.hasNext()) { +        try { +          final IAttributeBuilder modul = moduleLoaderInterator.next(); +          log.info("Loading attribut-builder Modul Information: " + modul.getName()); +          addBuilder(modul); + +        } catch (final Throwable e) { +          log.error("Check configuration! " + "Some attribute-builder modul" +              + " is not a valid IAttributeBuilder", e); +        } +      } +    } + +    log.info("Loading attribute-builder modules done"); + +  } +   +  /** +   * Get a specific attribute builder. +   * +   * @param name Attribute-builder friendly name +   * +   * @return Attribute-builder with this name or null if builder does not exists +   */ +  public static IAttributeBuilder getAttributeBuilder(final String name) { +    return builders.get(name); + +  } +   +  /** +   * Check if a specific attribute-builder is available. +   *  +   * @param name Attribute-builder friendly name +   * @return <code>true</code> if the builder is registered, otherwise <code>false</code> +   */ +  public static boolean containsBuilder(final String name) { +    return builders.containsKey(name); +     +  } +   +  /** +   * Get all registered attribute-builder. +   *  +   * @return {@link Iterator} of all available builders +   */ +  public static Iterator<IAttributeBuilder> getAllRegistratedBuilder() { +    return builders.values().iterator(); +     +  } +   +  /** +   * Get the number of currently register attribute builders. +   *  +   * @return number of attribute builders +   */ +  public static int getNumberOfRegisteredBuilders() { +    return builders.size(); +     +  } +   +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java index 19500cb3..a82a1a55 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java @@ -19,8 +19,7 @@  package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import org.apache.commons.lang3.StringUtils;  import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;  import at.gv.egiz.eaaf.core.api.idp.IAuthData; @@ -41,11 +40,8 @@ public class BirthdateAttributeBuilder implements IPvpAttributeBuilder {    public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData,        final IAttributeGenerator<ATT> g) throws AttributeBuilderException { -    if (authData.getDateOfBirth() != null) { -      final DateFormat pvpDateFormat = new SimpleDateFormat(BIRTHDATE_FORMAT_PATTERN); -      final String dateString = pvpDateFormat.format(authData.getDateOfBirth()); - -      return g.buildStringAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME, dateString); +    if (StringUtils.isNotEmpty(authData.getDateOfBirth())) { +      return g.buildStringAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME, authData.getDateOfBirth());      } else {        throw new UnavailableAttributeException(BIRTHDATE_NAME); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java index e18cc1a8..5cbfec01 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java @@ -19,27 +19,23 @@  package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; -import javax.annotation.Nonnull; -  import org.apache.commons.lang3.StringUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import org.springframework.util.Assert; -import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;  import at.gv.egiz.eaaf.core.api.idp.IAuthData;  import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;  import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;  @PvpMetadata  public class BpkAttributeBuilder implements IPvpAttributeBuilder {    private static final Logger log = LoggerFactory.getLogger(BpkAttributeBuilder.class); -  public static final String DELIMITER_BPKTYPE_BPK = ":"; - +      @Override    public String getName() {      return BPK_NAME; @@ -60,12 +56,13 @@ public class BpkAttributeBuilder implements IPvpAttributeBuilder {    }    protected String getBpkForSP(final IAuthData authData) throws UnavailableAttributeException { -    final String bpk = attrMaxSize(authData.getBpk()); -    final String type = removeBpkTypePrefix(authData.getBpkType()); - -    if (StringUtils.isEmpty(bpk)) { +    if (StringUtils.isEmpty(authData.getBpk()) || StringUtils.isEmpty(authData.getBpkType())) {        throw new UnavailableAttributeException(BPK_NAME); +            } +     +    final String bpk = attrMaxSize(authData.getBpk()); +    final String type = BpkBuilder.removeBpkTypePrefix(authData.getBpkType());      return type + DELIMITER_BPKTYPE_BPK + bpk; @@ -78,23 +75,5 @@ public class BpkAttributeBuilder implements IPvpAttributeBuilder {      return attr;    } - -  @Nonnull -  protected String removeBpkTypePrefix(@Nonnull final String type) { -    Assert.isTrue(type != null, "bPKType is 'NULL'"); -    if (type.startsWith(EaafConstants.URN_PREFIX_WBPK)) { -      return type.substring(EaafConstants.URN_PREFIX_WBPK.length()); -       -    } else if (type.startsWith(EaafConstants.URN_PREFIX_CDID)) { -      return type.substring(EaafConstants.URN_PREFIX_CDID.length()); -       -    } else if (type.startsWith(EaafConstants.URN_PREFIX_EIDAS)) { -      return type.substring(EaafConstants.URN_PREFIX_EIDAS.length()); -       -    } else { -      return type; -       -    } - -  } +    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java index 27b78059..03c16aef 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java @@ -31,7 +31,8 @@ public class EidCcsUrl implements IPvpAttributeBuilder {        }      } else { -      log.info(EID_CCS_URL_FRIENDLY_NAME + " is only available in MOA-ID context"); +      log.info(EID_CCS_URL_FRIENDLY_NAME + " is only available in E-ID context"); +            }      throw new UnavailableAttributeException(EID_CCS_URL_NAME); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java index ee51564e..8345dcf8 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java @@ -1,8 +1,5 @@  package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -  import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;  import at.gv.egiz.eaaf.core.api.idp.IAuthData;  import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; @@ -10,11 +7,11 @@ import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;  import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import lombok.extern.slf4j.Slf4j; +@Slf4j  @PvpMetadata  public class EidIdentityStatusLevelAttributeBuiler implements IPvpAttributeBuilder { -  private static final Logger log = -      LoggerFactory.getLogger(EidIdentityStatusLevelAttributeBuiler.class);    @Override    public String getName() { @@ -28,12 +25,15 @@ public class EidIdentityStatusLevelAttributeBuiler implements IPvpAttributeBuild      if (authData instanceof IEidAuthData) {        if (((IEidAuthData) authData).getEidStatus() == null) {          throw new UnavailableAttributeException(getName()); +                }        return g.buildStringAttribute(getFriendlyName(), getName(),            ((IEidAuthData) authData).getEidStatus().getUri()); +            } else {        log.info(getFriendlyName() + " is only available in EAAF context"); +            }      throw new UnavailableAttributeException(getName()); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java index fd85871c..90e8c285 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java @@ -41,7 +41,7 @@ public class EidIssuingNationAttributeBuilder implements IPvpAttributeBuilder {      final String countryCode = authData.getCiticenCountryCode();      if (StringUtils.isNotEmpty(countryCode)) {        return g.buildStringAttribute(EID_ISSUING_NATION_FRIENDLY_NAME, EID_ISSUING_NATION_NAME, -          countryCode); +          countryCode.toUpperCase());      } else {        return null;      } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java index 48d7a3a3..ba993b0c 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java @@ -27,7 +27,7 @@ import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;  import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BpkBuilder; +import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;  @PvpMetadata  public class EidSectorForIdAttributeBuilder implements IPvpAttributeBuilder { @@ -48,7 +48,7 @@ public class EidSectorForIdAttributeBuilder implements IPvpAttributeBuilder {      return g.buildStringAttribute(EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME,          EID_SECTOR_FOR_IDENTIFIER_NAME,  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(bpktype)); +        BpkBuilder.normalizeBpkTargetIdentifierToNonXFormat(bpktype));    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java index 6f857779..daed8455 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java @@ -53,16 +53,17 @@ public class EidSignerCertificate implements IPvpAttributeBuilder {                EID_SIGNER_CERTIFICATE_NAME, Base64Utils.encodeToString(signerCertificate));          } else { -          log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in MOA-ID context"); +          log.debug("{} is not available", EID_SIGNER_CERTIFICATE_FRIENDLY_NAME); +                    }        } catch (final Exception e) { -        log.info("Signer certificate BASE64 encoding error"); +        log.info("{} BASE64 encoding error", EID_SIGNER_CERTIFICATE_FRIENDLY_NAME);        }      } else { -      log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in AuthHandler context"); +      log.info("{} is only available in AuthHandler context", EID_SIGNER_CERTIFICATE_FRIENDLY_NAME);      }      throw new UnavailableAttributeException(EID_SIGNER_CERTIFICATE_NAME); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PiiTransactionIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PiiTransactionIdAttributeBuilder.java new file mode 100644 index 00000000..08911ac7 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PiiTransactionIdAttributeBuilder.java @@ -0,0 +1,37 @@ +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PiiTransactionIdAttributeBuilder implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + +  @Override +  public String getName() { +    return EID_PII_TRANSACTION_ID_NAME; +     +  } + +  @Override +  public <ATT> ATT build(ISpConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) +      throws AttributeBuilderException {     +    String piiTransactionId = authData.getGenericData(EID_PII_TRANSACTION_ID_NAME, String.class);     +    log.trace("{} piiTransactionId: {} as attribute",  +        piiTransactionId != null ? "Set" : "Notset", log.isTraceEnabled() ? piiTransactionId : "********"); +    return g.buildStringAttribute(EID_PII_TRANSACTION_ID_FRIENDLY_NAME, EID_PII_TRANSACTION_ID_NAME, +        piiTransactionId); +     +  } + +  @Override +  public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { +    return g.buildEmptyAttribute(EID_PII_TRANSACTION_ID_FRIENDLY_NAME, EID_PII_TRANSACTION_ID_NAME); +     +  } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpMandateModeAttributeBuilder.java index 44ff4e50..3240cfca 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpMandateModeAttributeBuilder.java @@ -26,11 +26,11 @@ import at.gv.egiz.eaaf.core.api.idp.IAuthData;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -public class SpUsesMandates implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { +public class SpMandateModeAttributeBuilder implements IAttributeBuilder, ExtendedPvpAttributeDefinitions {    @Override    public String getName() { -    return SP_USESMANDATES_NAME; +    return SP_USED_MANDATE_TYPE_NAME;    }    @Override @@ -44,7 +44,7 @@ public class SpUsesMandates implements IAttributeBuilder, ExtendedPvpAttributeDe    @Override    public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { -    return g.buildEmptyAttribute(SP_USESMANDATES_FRIENDLY_NAME, SP_USESMANDATES_NAME); +    return g.buildEmptyAttribute(SP_USED_MANDATE_TYPE_FRIENDLY_NAME, SP_USED_MANDATE_TYPE_NAME);    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpMandateProfilesAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpMandateProfilesAttributeBuilder.java new file mode 100644 index 00000000..e0d00f7d --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpMandateProfilesAttributeBuilder.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class SpMandateProfilesAttributeBuilder implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + +  @Override +  public String getName() { +    return SP_USED_MANDATE_PROFILES_NAME; +  } + +  @Override +  public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, +      final IAttributeGenerator<ATT> g) +      throws AttributeBuilderException { +    // this attribute can not generated yet +    return null; + +  } + +  @Override +  public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { +    return g.buildEmptyAttribute(SP_USED_MANDATE_PROFILES_FRIENDLY_NAME, SP_USED_MANDATE_PROFILES_NAME); + +  } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/TransactionIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/TransactionIdAttributeBuilder.java new file mode 100644 index 00000000..17b830dc --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/TransactionIdAttributeBuilder.java @@ -0,0 +1,33 @@ +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; + +public class TransactionIdAttributeBuilder implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + +  @Override +  public String getName() { +    return EID_TRANSACTION_ID_NAME; +     +  } + +  @Override +  public <ATT> ATT build(ISpConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) +      throws AttributeBuilderException { +    return g.buildStringAttribute(EID_TRANSACTION_ID_FRIENDLY_NAME, EID_TRANSACTION_ID_NAME, +        TransactionIdUtils.getTransactionId()); +     +  } + +  @Override +  public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { +    return g.buildEmptyAttribute(EID_TRANSACTION_ID_FRIENDLY_NAME, EID_TRANSACTION_ID_NAME); +     +  } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java index fc62af45..b05d8df0 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -26,11 +26,11 @@ import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.text.StringEscapeUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.context.ApplicationContext; +import org.springframework.util.SerializationUtils;  import org.springframework.web.bind.annotation.ExceptionHandler;  import at.gv.egiz.components.eventlog.api.EventConstants; @@ -42,12 +42,12 @@ import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;  import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService;  import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;  import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;  import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;  import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.core.impl.utils.Random;  /**   * Basic application controller that implements core error-handling. @@ -69,10 +69,13 @@ public abstract class AbstractController {    protected ITransactionStorage transactionStorage;    @Autowired(required = true)    protected IStatusMessenger statusMessager; -   +    @Autowired    protected IRevisionLogger revisionsLogger; +  @Autowired +  protected IPendingRequestIdGenerationStrategy reqIdGenerationStrategy; +      /**     * EAAF framework exception handler.     * @@ -92,11 +95,11 @@ public abstract class AbstractController {        protAuthService.handleErrorNoRedirect(e, req, resp, true);      } catch (final EaafException e1) { +      log.warn("ErrorHandling failed with error: ", e.getMessage(), e);        log.warn("Can NOT handle an 'EAAFException'. Forwarding to generic error ... ", e);        ioExceptionHandler(resp, e);      } -    }    /** @@ -106,20 +109,23 @@ public abstract class AbstractController {     * This handler wrote an internal server error into http response     * </p>     * -   * @param resp      http response -   * @param exception exception +   * @param req  http request +   * @param resp http response +   * @param e Catched exception     * @throws IOException In case of an internal error.     */    @ExceptionHandler({ Exception.class }) -  public void genericExceptionHandler(final HttpServletResponse resp, final Exception exception) -      throws IOException { -    log.error("Internel Server Error.", exception); -    resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); -    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" -        + "(Errorcode=9199" + " | Description=" -        + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage())) -        + ")"); +  public void genericExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp,  +      final Exception e) throws IOException { +    try { +      protAuthService.handleErrorNoRedirect(e, req, resp, true); + +    } catch (final EaafException e1) { +      log.warn("ErrorHandling failed with error: ", e.getMessage(), e); +      log.error("Can NOT handle a generic 'Exception'. Forwarding to generic error ... ", e); +      ioExceptionHandler(resp, e); +    }        }    /** @@ -150,8 +156,6 @@ public abstract class AbstractController {      try {        final String errorKey = storeErrorAndGetErrorToken(errorToHandle);        protAuthService.forwardToErrorHandler(errorToHandle, errorKey, req, resp); -       -      return;      } catch (final Exception e) {        log.warn("Default error-handling FAILED. Exception can not be stored ....", e); @@ -169,18 +173,30 @@ public abstract class AbstractController {      }      // put exception into transaction store for redirect -    final String errorKey = Random.nextLongRandom(); +    final String errorToken = reqIdGenerationStrategy.generateExternalPendingRequestId();     +    final String errorKey = reqIdGenerationStrategy.getPendingRequestIdWithOutChecks(errorToken); +                  if (errorToHandle.getFirst() != null) {        revisionsLogger.logEvent(errorToHandle.getFirst(), EventConstants.TRANSACTION_ERROR); -      transactionStorage.put(errorKey, new ExceptionContainer(errorToHandle.getFirst(), errorToHandle -          .getSecond()), -1); + +      log.trace("Serializing {} ... ", ExceptionContainer.class.getName()); +      final byte[] serializedError = SerializationUtils.serialize( +          new ExceptionContainer(errorToHandle.getFirst(), errorToHandle.getSecond())); + +      log.debug("Put 'ExceptionContainer' into cache with id: {}... ", errorKey); +      transactionStorage.put(errorKey, serializedError, -1);      } else { -      transactionStorage.put(errorKey, new ExceptionContainer(null, errorToHandle.getSecond()), -1); +      log.trace("Serializing {} ... ", ExceptionContainer.class.getName()); +      final byte[] serializedError = SerializationUtils.serialize( +          new ExceptionContainer(null, errorToHandle.getSecond())); + +      log.trace("Put 'ExceptionContainer' into cache with id: {}... ",errorKey); +      transactionStorage.put(errorKey, serializedError, -1);      } -    return errorKey; +    return errorToken;    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java index 098bca4c..ea481bdb 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java @@ -36,6 +36,7 @@ import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine;  import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.EaafIllegalStateException; +import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;  import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;  /** @@ -78,13 +79,16 @@ public abstract class AbstractProcessEngineSignalController extends AbstractCont        // process instance is mandatory        if (pendingReq.getProcessInstanceId() == null) {          throw new EaafIllegalStateException( -            new Object[] { "MOA session does not provide process instance id." }); +            new Object[] { "PendingRequest does not provide process-instance id." });        }        // wake up next task        processEngine.signal(pendingReq); +    } catch (PendingReqIdValidationException e) { +      handleError(null, e, req, resp, e.getInvalidPendingReq()); +            } catch (final Exception ex) {        handleError(null, ex, req, resp, pendingReq); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java index 17da63f5..a22cbe9d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java @@ -15,7 +15,7 @@   * This product combines work with different licenses. See the "NOTICE" text file for details on the   * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative   * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ + */  package at.gv.egiz.eaaf.core.impl.idp.controller; @@ -29,6 +29,7 @@ import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Controller; +import org.springframework.util.SerializationUtils;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod; @@ -38,22 +39,107 @@ import at.gv.egiz.eaaf.core.api.IRequestStorage;  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; +import at.gv.egiz.eaaf.core.api.idp.IModulInfo; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;  import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;  /**   * Protocol finialization end-point.   *   * @author tlenz - *   */  @Controller  public class ProtocolFinalizationController extends AbstractController {    private static final Logger log = LoggerFactory.getLogger(ProtocolFinalizationController.class); -  public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol"; -  public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; +  public static final String ENDPOINT_FINALIZEPROTOCOL =  +      EaafConstants.ENDPOINT_PREFIX_SECURED + "/finalizeAuthProtocol"; +  public static final String ENDPOINT_ERRORHANDLING =  +      EaafConstants.ENDPOINT_PREFIX_SECURED + "/errorHandling"; +  public static final String ENDPOINT_ERROR_REDIRECT =  +      EaafConstants.ENDPOINT_PREFIX_SECURED + "/errorRedirect";    @Autowired(required = true)    IRequestStorage requestStorage; +  @Autowired +  IPendingRequestIdGenerationStrategy requestIdValidationStragegy; + + +  /** +   * Handles incoming requests for redirects to IDP. +   * @param req  http request +   * @param resp http response +   * @throws EaafException In case of an internal error +   * @throws IOException   In case of a servlet error +   */ +  @RequestMapping(value = ENDPOINT_ERROR_REDIRECT, method = {RequestMethod.GET, RequestMethod.POST}) +  public void errorRedirect(final HttpServletRequest req, final HttpServletResponse resp) +      throws EaafException, IOException { + +    final String errorToken = StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); +    if (errorToken != null) { +      IRequest pendingReq = null; +      try { +        String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken); +        log.debug("Searching exception with internal error-token: {}", errorId); + +        // load stored exception from database +        final byte[] containerSerialized = transactionStorage.get(errorId, byte[].class); +        if (containerSerialized != null) { +          // remove exception if it was found +          transactionStorage.remove(errorId); +          log.trace("Find exception with internal error-token: {}", errorId); + +          //final Object containerObj = EaafSerializationUtils.deserialize(containerSerialized, +          //    Arrays.asList( +          //        ExceptionContainer.class.getName() +          //        )); +          final Object containerObj = SerializationUtils.deserialize(containerSerialized); + +          if (containerObj instanceof ExceptionContainer) { +            final ExceptionContainer container = (ExceptionContainer) containerObj; +            final Throwable throwable = container.getExceptionThrown(); +            pendingReq = container.getPendingRequest(); + +            if (pendingReq != null) { +              IModulInfo handlingModule = ProtocolAuthenticationService +                  .extractShibbolethHandling(pendingReq, applicationContext); +              if (!handlingModule.generateErrorMessage(throwable, req, resp, pendingReq)) { +                protAuthService.handleErrorNoRedirect(new EaafException("process.90", null), req, resp, false); +                 +              }               +            } +          }         +        } else { +          log.info("Find no exception with internal error-token: {}", errorId); +          protAuthService +              .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, null), +                  req, resp, false); +           +        } +         +      } catch (Throwable e) { +        log.error(e.getMessage(), e); +        protAuthService.handleErrorNoRedirect(e, req, resp, false); +         +      } finally { +        // remove pending-request +        if (pendingReq != null) { +          requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); +          revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); + +        } +      } +       +    } else { +      log.debug("Request contains NO ErrorId"); +      protAuthService +          .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req, +              resp, false); + +    } +  }    /**     * End-Point to handle errors. @@ -63,42 +149,62 @@ public class ProtocolFinalizationController extends AbstractController {     * @throws EaafException In case of an internal error     * @throws IOException   In case of a servlet error     */ -  @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET, RequestMethod.POST }) +  @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = {RequestMethod.GET, RequestMethod.POST})    public void errorHandling(final HttpServletRequest req, final HttpServletResponse resp)        throws EaafException, IOException {      // receive an authentication error -    final String errorid = -        StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); -    if (errorid != null) { +    final String errorToken = StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); +    if (errorToken != null) {        IRequest pendingReq = null;        try { +        String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken); +        log.debug("Searching exception with internal error-token: {}", errorId); +          // load stored exception from database -        final ExceptionContainer container = -            transactionStorage.get(errorid, ExceptionContainer.class); -        if (container != null) { +        final byte[] containerSerialized = transactionStorage.get(errorId, byte[].class); +        if (containerSerialized != null) {            // remove exception if it was found -          transactionStorage.remove(errorid); +          transactionStorage.remove(errorId); +          log.trace("Find exception with internal error-token: {}", errorId); + +          //final Object containerObj = EaafSerializationUtils.deserialize(containerSerialized,  +          //    Arrays.asList( +          //        ExceptionContainer.class.getName() +          //        )); +          final Object containerObj = SerializationUtils.deserialize(containerSerialized); + +          if (containerObj instanceof ExceptionContainer) { +            final ExceptionContainer container = (ExceptionContainer) containerObj; +            final Throwable throwable = container.getExceptionThrown(); +            pendingReq = container.getPendingRequest(); -          final Throwable throwable = container.getExceptionThrown(); -          pendingReq = container.getPendingRequest(); +            if (pendingReq != null) { +              //set MDC variables +              TransactionIdUtils.setAllLoggingVariables(pendingReq); -          if (pendingReq != null) { -            // build protocol-specific error message if possible -            protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); +              // build protocol-specific error message if possible +              protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); -            // remove active user-session -            transactionStorage.remove(pendingReq.getPendingRequestId()); +              // remove active user-session +              transactionStorage.remove(pendingReq.getPendingRequestId()); -            return; +            } else { +              protAuthService.handleErrorNoRedirect(throwable, req, resp, true); + +            }            } else { -            protAuthService.handleErrorNoRedirect(throwable, req, resp, true); +            protAuthService +                .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null), req, +                    resp, false);            } +          } else { -          protAuthService.handleErrorNoRedirect( -              new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), -              req, resp, false); +          log.info("Find no exception with internal error-token: {}", errorId); +          protAuthService +              .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), +                  req, resp, false);          } @@ -110,18 +216,20 @@ public class ProtocolFinalizationController extends AbstractController {          // remove pending-request          if (pendingReq != null) {            requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); -          revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, -              pendingReq.getUniqueTransactionIdentifier()); +          revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier());          } +        //remove all Logger variables +        TransactionIdUtils.removeAllLoggingVariables(); +        }      } else {        log.debug("Request contains NO ErrorId"); -      protAuthService.handleErrorNoRedirect( -          new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req, -          resp, false); +      protAuthService +          .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req, +              resp, false);      } @@ -135,7 +243,7 @@ public class ProtocolFinalizationController extends AbstractController {     * @throws EaafException In case of an internal error     * @throws IOException   In case of a servlet error     */ -  @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = { RequestMethod.GET }) +  @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = {RequestMethod.GET})    public void finalizeAuthProtocol(final HttpServletRequest req, final HttpServletResponse resp)        throws EaafException, IOException { @@ -145,14 +253,19 @@ public class ProtocolFinalizationController extends AbstractController {      final IRequest pendingReq = requestStorage.getPendingRequest(pendingRequestID);      if (pendingReq == null) { -      log.error("No PendingRequest with ID " + pendingRequestID + " found.!"); +      log.info("PendingReqId was valid but no PendingRequest with ID: {}. Looks already used",  +          pendingRequestID);        protAuthService.handleErrorNoRedirect( -          new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, -              new Object[] { pendingRequestID, }), -          req, resp, false); +          new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, new Object[]{pendingRequestID,}), req, +          resp, false);      } else { +      //set MDC variables +      TransactionIdUtils.setAllLoggingVariables(pendingReq); + +      //perform protocol finalization steps        protAuthService.finalizeAuthentication(req, resp, pendingReq); +      }    } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java index dcd5a1d1..007c3e1d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java @@ -11,9 +11,7 @@ import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.data.EaafEventCodes;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -53,29 +51,6 @@ public abstract class AbstractLocaleAuthServletTask extends AbstractAuthServletT    } -  protected void stopProcessFromUserDecision(final ExecutionContext executionContext, -      final HttpServletRequest request, final HttpServletResponse response) -      throws TaskExecutionException { -    try { -      revisionsLogger.logEvent(pendingReq, EaafEventCodes.PROCESS_STOPPED_BY_USER); -      pendingReq.setAbortedByUser(true); -      pendingReq.setAuthenticated(false); -      performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); - -      log.trace("Set process-cancelation flag"); -      executionContext.setCanceleProcessFlag(); - -    } catch (final EaafException e) { -      throw new TaskExecutionException(pendingReq, e.getMessage(), e); - -    } catch (final Exception e) { -      log.warn("Stopping auth.process FAILED", e); -      throw new TaskExecutionException(pendingReq, e.getMessage(), e); - -    } - -  } -    protected boolean parseFlagFromHttpRequest(final HttpServletRequest httpReq,        final String httpParamName, final boolean defaultValue) {      final String flag = httpReq.getParameter(httpParamName); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java index 328a25c5..7a664915 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java @@ -19,8 +19,6 @@  package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; -import java.util.Set; -  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -32,6 +30,7 @@ import org.springframework.stereotype.Component;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine;  import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException;  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.idp.auth.modules.ModuleRegistration; @@ -73,12 +72,9 @@ public class RestartAuthProzessManagement extends AbstractAuthServletTask {        } else {          // create a new execution context and copy all elements to new context          final ExecutionContext newec = new ExecutionContextImpl(); -        final Set<String> entries = executionContext.keySet(); -        for (final String key : entries) { -          newec.put(key, executionContext.get(key)); - -        } - +        executionContext.keySet().stream().forEach( +            key -> newec.put(key, executionContext.get(key))); +                  log.debug("Select new auth.-process and restart restart process-engine ... ");          // select and create new process instance @@ -87,7 +83,7 @@ public class RestartAuthProzessManagement extends AbstractAuthServletTask {          if (processDefinitionId == null) {            log.warn("No suitable authentication process found for SessionID "                + pendingReq.getPendingRequestId()); -          throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); +          throw new EaafException("process.02", null);          }          final String processInstanceId = @@ -112,10 +108,18 @@ public class RestartAuthProzessManagement extends AbstractAuthServletTask {          processEngine.start(pendingReq);        } - -    } catch (final EaafException e) { -      throw new TaskExecutionException(pendingReq, e.getMessage(), e); - +       +    } catch (final ProcessExecutionException e) { +      //check if Task in already selected process failed or if process selection failed +      if (e.getCause() != null && e.getCause() instanceof TaskExecutionException) { +        log.info("New process was started, but one Task in process failed. Reason: {}", e.getMessage()); +        throw (TaskExecutionException)e.getCause(); +         +      } else { +        throw new TaskExecutionException(pendingReq, e.getMessage(), e); +         +      } +                 } catch (final Exception e) {        log.warn("RestartAuthProzessManagement has an internal error", e);        throw new TaskExecutionException(pendingReq, e.getMessage(), e); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java index 14537d44..edca0fba 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java @@ -101,6 +101,7 @@ public class ProcessDefinitionParser {        // Standard implementation of XMLInputFactory seems not to be thread-safe        final XMLInputFactory inputFactory = XMLInputFactory.newInstance(); +      inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);        reader = inputFactory.createXMLEventReader(processDefinitionInputStream);        final List<StartElement> transitionElements = new ArrayList<>(); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java index 9274ea81..6e83a201 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java @@ -21,15 +21,13 @@ package at.gv.egiz.eaaf.core.impl.idp.process;  import java.io.InputStream;  import java.io.Serializable; +import java.text.MessageFormat;  import java.util.HashMap;  import java.util.Map; -import java.util.Map.Entry;  import java.util.concurrent.ConcurrentHashMap;  import org.apache.commons.collections4.IterableUtils;  import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory;  import org.slf4j.MDC;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.context.ApplicationContext; @@ -51,14 +49,17 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessNode;  import at.gv.egiz.eaaf.core.impl.idp.process.model.StartEvent;  import at.gv.egiz.eaaf.core.impl.idp.process.model.TaskInfo;  import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; +import lombok.extern.slf4j.Slf4j;  /**   * Process engine implementation allowing starting and continuing processes as   * well as providing means for cleanup actions.   */ +@Slf4j  public class ProcessEngineImpl implements ProcessEngine { -  private final Logger log = LoggerFactory.getLogger(getClass()); +  private static final String ERROR_PROCESS_OBJECT_NOT_EXIST =  +      "Process instance: {0} does not exist for pendingReq: {0}";    @Autowired    ProcessInstanceStoreDao piStoreDao; @@ -156,15 +157,16 @@ public class ProcessEngineImpl implements ProcessEngine {        if (StringUtils.isEmpty(pendingReq.getProcessInstanceId())) {          log.error("Pending-request with id:" + pendingReq.getPendingRequestId()              + " includes NO 'ProcessInstanceId'"); -        throw new ProcessExecutionException("Pending-request with id:" -            + pendingReq.getPendingRequestId() + " includes NO 'ProcessInstanceId'"); +        throw new ProcessExecutionException(MessageFormat.format(ERROR_PROCESS_OBJECT_NOT_EXIST,  +            pendingReq.getProcessInstanceId(), pendingReq.getPendingRequestId())); +                }        final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId());        if (pi == null) { -        throw new ProcessExecutionException( -            "Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist."); +        throw new ProcessExecutionException(MessageFormat.format(ERROR_PROCESS_OBJECT_NOT_EXIST,  +            pendingReq.getProcessInstanceId(), pendingReq.getPendingRequestId()));        } @@ -449,11 +451,9 @@ public class ProcessEngineImpl implements ProcessEngine {      final ExecutionContext executionContext =          new ExecutionContextImpl(piStore.getProcessInstanceId()); - -    final Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); -    for (final Entry<String, Serializable> el : executionContextData.entrySet()) { -      executionContext.put(el.getKey(), el.getValue()); -    } +     +    piStore.getExecutionContextData().entrySet().stream().forEach( +        el -> executionContext.put(el.getKey(), el.getValue()));      final ProcessInstance pi = new ProcessInstance(          processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java index cca8872f..611572c0 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java @@ -72,7 +72,7 @@ public class ProcessInstanceStoreDaoImpl implements ProcessInstanceStoreDao {        log.debug("Found process instance store for instance '{}'.", processInstanceId);      } else { -      log.debug("Unable to find process instance store for instance '{}'.", processInstanceId); +      log.info("Unable to find process instance store for instance '{}'.", processInstanceId);      } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java index 01b063aa..4b8a7a04 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java @@ -33,6 +33,7 @@ import java.util.Map.Entry;  import java.util.Set;  import java.util.Vector; +import javax.xml.XMLConstants;  import javax.xml.parsers.DocumentBuilder;  import javax.xml.parsers.DocumentBuilderFactory;  import javax.xml.parsers.ParserConfigurationException; @@ -111,10 +112,10 @@ public class DomUtils {    private static final String EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY =        "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; -  private static final String EXTERNAL_GENERAL_ENTITIES_FEATURE = +  public static final String EXTERNAL_GENERAL_ENTITIES_FEATURE =        "http://xml.org/sax/features/external-general-entities"; -  private static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = +  public static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE =        "http://xml.org/sax/features/external-parameter-entities";    public static final String DISALLOW_DOCTYPE_FEATURE = @@ -785,6 +786,7 @@ public class DomUtils {        throws TransformerException, IOException {      final TransformerFactory transformerFactory = TransformerFactory.newInstance(); +    transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);      final Transformer transformer = transformerFactory.newTransformer();      final ByteArrayOutputStream bos = new ByteArrayOutputStream(16384); @@ -1211,6 +1213,7 @@ public class DomUtils {      // StringWriter stringWriter = new StringWriter();      final Result result = new StreamResult(out);      final TransformerFactory factory = TransformerFactory.newInstance(); +    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);      final Transformer transformer = factory.newTransformer();      transformer.transform(source, result);      return out.toByteArray(); diff --git a/eaaf_core/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder b/eaaf_core/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder index 30f1cb57..e581a4d7 100644 --- a/eaaf_core/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder +++ b/eaaf_core/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder @@ -12,4 +12,10 @@ at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidIdentityLinkBuilder  at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidEidTokenBuilder  at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidSignerCertificate  at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidIdentityStatusLevelAttributeBuiler -at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidCcsUrl
\ No newline at end of file +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.EidCcsUrl +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.TransactionIdAttributeBuilder +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PiiTransactionIdAttributeBuilder +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpFriendlyNameAttributeBuilder +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpUniqueIdAttributeBuilder +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpMandateProfilesAttributeBuilder +at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpMandateModeAttributeBuilder diff --git a/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties b/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties index 064554b9..c5cb1bb1 100644 --- a/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties +++ b/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties @@ -4,4 +4,16 @@ builder.08=Authentication process could NOT completed. Reason: {0}  builder.30=Decrypted bPK target: {0} does not match to required target: {1}  builder.31=Encrypted bPK has a suspect format and consists of #{0} elements  builder.32=bPK-target format must be full URI +builder.33=bPK caluclation not possible. Reason: {0} + + +process.01=Can not execute authentication process +process.02=Find no applicable authentication process for current state or user-selection. +process.03=Can not resume the authentication process. Reason: {0} +process.04=Can not execute authentication process. Problem with an internal state + +process.90=Forward to service-provider not possible, because it's not supported.  + +process.98=Not supported internal state. Reason: {0} +process.99=Validation of RequestId: {0} FAILED. Reason: {1}
\ No newline at end of file diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/AuthenticationDataBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/AuthenticationDataBuilderTest.java index 33bd1010..19054634 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/AuthenticationDataBuilderTest.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/AuthenticationDataBuilderTest.java @@ -307,7 +307,7 @@ public class AuthenticationDataBuilderTest {        throw new Exception("GivenName wrong");      } -    if (!authData.getFormatedDateOfBirth().equals("1973-06-04")) { +    if (!authData.getDateOfBirth().equals("1973-06-04")) {        throw new Exception("DateOfBirth wrong");      } diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BirthdayAttrBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BirthdayAttrBuilderTest.java index 21cf71a9..f155b3b4 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BirthdayAttrBuilderTest.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BirthdayAttrBuilderTest.java @@ -29,7 +29,7 @@ public class BirthdayAttrBuilderTest extends AbstractAttributeBuilderTest {        final DateFormat format =            new SimpleDateFormat(PvpAttributeDefinitions.BIRTHDATE_FORMAT_PATTERN);        Assert.assertEquals("Birthday does NOT match", authData.getDateOfBirth(), -          format.parse(value)); +          value);      } catch (final Exception e) {        Assert.assertTrue("Attr. builder has an exception", e == null); diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BpkAttributeBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BpkAttributeBuilderTest.java index 1ad75abc..0619d4d6 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BpkAttributeBuilderTest.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/BpkAttributeBuilderTest.java @@ -9,6 +9,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder;  import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData;  import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.BpkAttributeBuilder;  @RunWith(SpringJUnit4ClassRunner.class) @@ -16,6 +17,21 @@ import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.BpkAttributeBuilder;  public class BpkAttributeBuilderTest extends AbstractAttributeBuilderTest {    private final IAttributeBuilder attrBuilde = new BpkAttributeBuilder(); + +  @Test +  public void organwalterBpkTest() throws Exception { +    spConfigMap.put("target", "urn:publicid:gv.at:cdid+ZP-MH"); +         +    final IAuthData authData = buildAuthData(); +    ((AuthenticationData) authData).setBpkType("urn:publicid:gv.at:cdid+OW"); +     +    final String value = attrBuilde.build(spConfig, authData, gen); + +    Assert.assertEquals("Wrong bPK",  +        "OW:" + authData.getBpk(),  +        value); +       +  }    @Test    public void performTestBpk() throws Exception { diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/PiiTransactionIdAttributeBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/PiiTransactionIdAttributeBuilderTest.java new file mode 100644 index 00000000..82ac0abf --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/PiiTransactionIdAttributeBuilderTest.java @@ -0,0 +1,64 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.attributes; + +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PiiTransactionIdAttributeBuilder; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; + +/** + * Attribute builder to generate an attribute that holds the unique TransactionId for this process.  + * <br> + * The attribute-value is read from {@link TransactionIdUtils} with method <code>getTransactionId()</code> + *  + * @author tlenz + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class PiiTransactionIdAttributeBuilderTest extends AbstractAttributeBuilderTest { + +  private final IAttributeBuilder attrBuilder = new PiiTransactionIdAttributeBuilder(); +   +  @Test +  public void attributeName() { +    Assert.assertEquals("Wrong attribute name",  +        "urn:eidgvat:attributes.piiTransactionId", attrBuilder.getName()); +     +  } +   +  @Test +  public void checkEmptyAttribute() {     +    String value = attrBuilder.buildEmpty(gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +  +  @Test +  public void noPiiTransactionId() throws AttributeBuilderException, Exception {            +    String value = attrBuilder.build(spConfig, buildAuthData(), gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +  @Test +  public void withPiiTransactionId() throws AttributeBuilderException, Exception {     +    String piiTransId = UUID.randomUUID().toString(); +    IAuthData authData = buildAuthData(); +    ((AuthenticationData)authData).setGenericData("urn:eidgvat:attributes.piiTransactionId", piiTransId); +     +    String value = attrBuilder.build(spConfig, authData, gen);     +    Assert.assertEquals("piiTransactionId", piiTransId, value); +         +  } +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateModeAttributeBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateModeAttributeBuilderTest.java new file mode 100644 index 00000000..dae37a5c --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateModeAttributeBuilderTest.java @@ -0,0 +1,64 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.attributes; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.util.NoSuchElementException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpMandateModeAttributeBuilder; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class SpMandateModeAttributeBuilderTest extends AbstractAttributeBuilderTest { +   +  private final IAttributeBuilder attrBuilder = new SpMandateModeAttributeBuilder(); +   +  @Test +  public void attributeName() { +    Assert.assertEquals("Wrong attribute name",  +        "urn:eidgvat:attributes.ServiceProviderMandateType", attrBuilder.getName()); +     +  } +   +  @Test +  public void checkEmptyAttribute() {     +    String value = attrBuilder.buildEmpty(gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +  @Test +  public void checkyAttribute() throws AttributeBuilderException, Exception {     +    String value = attrBuilder.build(spConfig, buildAuthData(), gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +  @Test +  public void mandateModeEnumValid() {     +    SpMandateModes mode = SpMandateModes.fromString("forceLegal");     +    assertEquals("wrong mode", SpMandateModes.LEGAL_FORCE, mode); +    assertEquals("wrong mode toString", "forceLegal", mode.getMode()); +    assertEquals("wrong mode getMode", "forceLegal", mode.toString()); +         +  } +   +  @Test +  public void mandateModeEnumInvalid() {      +    assertThrows(NoSuchElementException.class,  +        () -> SpMandateModes.fromString(RandomStringUtils.randomAlphanumeric(5))); +     +  } +   +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateProfilesAttributeBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateProfilesAttributeBuilderTest.java new file mode 100644 index 00000000..77459975 --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/SpMandateProfilesAttributeBuilderTest.java @@ -0,0 +1,40 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.attributes; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.SpMandateProfilesAttributeBuilder; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class SpMandateProfilesAttributeBuilderTest extends AbstractAttributeBuilderTest { +   +  private final IAttributeBuilder attrBuilder = new SpMandateProfilesAttributeBuilder(); +   +  @Test +  public void attributeName() { +    Assert.assertEquals("Wrong attribute name",  +        "urn:eidgvat:attributes.ServiceProviderMandateProfiles", attrBuilder.getName()); +     +  } +   +  @Test +  public void checkEmptyAttribute() {     +    String value = attrBuilder.buildEmpty(gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +  @Test +  public void checkyAttribute() throws AttributeBuilderException, Exception {     +    String value = attrBuilder.build(spConfig, buildAuthData(), gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/TransactionIdAttributeBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/TransactionIdAttributeBuilderTest.java new file mode 100644 index 00000000..d82bdf5c --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/attributes/TransactionIdAttributeBuilderTest.java @@ -0,0 +1,60 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.attributes; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.TransactionIdAttributeBuilder; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; + +/** + * Attribute builder to generate an attribute that holds the unique TransactionId for this process.  + * <br> + * The attribute-value is read from {@link TransactionIdUtils} with method <code>getTransactionId()</code> + *  + * @author tlenz + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class TransactionIdAttributeBuilderTest extends AbstractAttributeBuilderTest { + +  private final IAttributeBuilder attrBuilder = new TransactionIdAttributeBuilder(); +   +  @Test +  public void attributeName() { +    Assert.assertEquals("Wrong attribute name",  +        "urn:eidgvat:attributes.transactionId", attrBuilder.getName()); +     +  } +   +  @Test +  public void checkEmptyAttribute() {     +    String value = attrBuilder.buildEmpty(gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +  +  @Test +  public void noTransactionId() throws AttributeBuilderException, Exception {            +    String value = attrBuilder.build(spConfig, buildAuthData(), gen);     +    Assert.assertNull("Attr. not null", value); +         +  } +   +  @Test +  public void withTransactionId() throws AttributeBuilderException, Exception {     +    TransactionIdUtils.setTransactionId(); +    String transId = TransactionIdUtils.getTransactionId(); +    Assert.assertNull("Inputdata is null", transId); +     +    String value = attrBuilder.build(spConfig, buildAuthData(), gen);     +    Assert.assertEquals("TransactionId", transId, value); +         +  } +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilderTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilderTest.java deleted file mode 100644 index 64c13781..00000000 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilderTest.java +++ /dev/null @@ -1,453 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.idp.auth.builder; - -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; - -import org.apache.commons.lang3.RandomStringUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.BlockJUnit4ClassRunner; - -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; -import at.gv.egiz.eaaf.core.impl.data.Pair; - -@RunWith(BlockJUnit4ClassRunner.class) -public class BpkBuilderTest { - -  private static final String BASEID = "RUxHQVRlc3RQQjBYWFjFkHpnw7xyX1hYWFTDvHpla8OnaQ=="; -   -  private KeyPair keyPair; -   -   -  /** -   * jUnit test initializer. -   * @throws NoSuchProviderException In case of an error -   * @throws NoSuchAlgorithmException  In case of an error -   */ -  @Before -  public void initialize() throws NoSuchAlgorithmException, NoSuchProviderException { -    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); -    keyPair = keyGen.generateKeyPair(); -     -  } -   -  @Test -  public void encBpkWrongTarget() throws InvalidKeyException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = RandomStringUtils.randomAlphanumeric(25); -     -    try { -      BpkBuilder.encryptBpk(bpk, target, keyPair.getPublic()); -      Assert.fail("Wrong parameters not detected"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorMsg", "builder.32", e.getErrorId()); -       -    } -  } -   -  @Test -  public void decBpkWrongTarget() throws InvalidKeyException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = RandomStringUtils.randomAlphanumeric(25); -     -    try { -      BpkBuilder.decryptBpk(bpk, target, keyPair.getPrivate()); -      Assert.fail("Wrong parameters not detected"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorMsg", "builder.32", e.getErrorId()); -       -    } -  } -   -  @Test -  public void decBpkWrongTargetInEncBpk() throws InvalidKeyException, EaafBuilderException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = EaafConstants.URN_PREFIX_CDID + "AA"; -     -    String encBpk = BpkBuilder.encryptBpk(bpk, target, keyPair.getPublic()); -    try { -      BpkBuilder.decryptBpk(encBpk,  -          EaafConstants.URN_PREFIX_CDID + "BB", keyPair.getPrivate()); -      Assert.fail("Wrong parameters not detected"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorMsg", "builder.30", e.getErrorId()); -       -    } -  } -   -  @Test -  public void encBpkSuccess() throws EaafBuilderException, InvalidKeyException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = EaafConstants.URN_PREFIX_CDID + "AA"; -     -    String encBpk = BpkBuilder.encryptBpk(bpk, target, keyPair.getPublic()); -     -    Assert.assertNotNull("encBpk", encBpk); -     -    Pair<String, String> decBpk = BpkBuilder.decryptBpk(encBpk, target, keyPair.getPrivate()); -     -    Assert.assertEquals("wrong bBK", bpk, decBpk.getFirst()); -    Assert.assertEquals("wrong bBK-Target", target, decBpk.getSecond()); -     -  } -   -  @Test -  public void encWbpkSuccess() throws EaafBuilderException, InvalidKeyException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = EaafConstants.URN_PREFIX_WBPK + "XFN+123456i"; -     -    String encBpk = BpkBuilder.encryptBpk(bpk, target, keyPair.getPublic()); -     -    Assert.assertNotNull("encBpk", encBpk); -     -    Pair<String, String> decBpk = BpkBuilder.decryptBpk(encBpk, target, keyPair.getPrivate()); -     -    Assert.assertEquals("wrong bBK", bpk, decBpk.getFirst()); -    Assert.assertEquals("wrong bBK-Target", target, decBpk.getSecond()); -     -  } -   -  @Test -  public void encWbpkSuccessSecond() throws EaafBuilderException, InvalidKeyException { -    String bpk = RandomStringUtils.randomAlphanumeric(25); -    String target = EaafConstants.URN_PREFIX_WBPK + "FN+123456i"; -     -    String encBpk = BpkBuilder.encryptBpk(bpk, target, keyPair.getPublic()); -     -    Assert.assertNotNull("encBpk", encBpk); -     -    Pair<String, String> decBpk = BpkBuilder.decryptBpk(encBpk,  -        EaafConstants.URN_PREFIX_WBPK + "XFN+123456i", keyPair.getPrivate()); -     -    Assert.assertEquals("wrong bBK", bpk, decBpk.getFirst()); -    Assert.assertEquals("wrong bBK-Target",  -        EaafConstants.URN_PREFIX_WBPK + "XFN+123456i", decBpk.getSecond()); -     -  } -   -   -  @Test -  public void noBaseId() { -    try { -      BpkBuilder.generateAreaSpecificPersonIdentifier(null, EaafConstants.URN_PREFIX_CDID + "AA"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorCode", "builder.00", e.getErrorId()); -    } -  } -   -  @Test -  public void noTarget() { -    try { -      BpkBuilder.generateAreaSpecificPersonIdentifier(BASEID, null); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorCode", "builder.00", e.getErrorId()); -    } -  } -   -  @Test -  public void noBaseIdType() { -    try { -      BpkBuilder.generateAreaSpecificPersonIdentifier(BASEID,  -          null, EaafConstants.URN_PREFIX_CDID + "AA"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorCode", "builder.00", e.getErrorId()); -    } -  } -   -  @Test -  public void wrongBaseIdType() { -    try { -      BpkBuilder.generateAreaSpecificPersonIdentifier(BASEID,  -          EaafConstants.URN_PREFIX_CDID + "BB", EaafConstants.URN_PREFIX_CDID + "AA"); -       -    } catch (EaafBuilderException e) { -      Assert.assertEquals("Wrong errorCode", "builder.00", e.getErrorId()); -    } -  } -   -  @Test -  public void baseIdTypeEqualsTarget() throws EaafBuilderException { -    Pair<String, String> result1 =  BpkBuilder.generateAreaSpecificPersonIdentifier(BASEID,  -          EaafConstants.URN_PREFIX_CDID + "AA", EaafConstants.URN_PREFIX_CDID + "AA"); -     -    Assert.assertEquals("first bPK", BASEID, -        result1.getFirst()); -    Assert.assertEquals("first bPK", "urn:publicid:gv.at:cdid+AA", -        result1.getSecond()); -   -  } -   -  @Test -  public void buildBpk() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_CDID + "AA"); -    Pair<String, String> result2 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_CDID + "BB"); -     -    Assert.assertEquals("first bPK", "b1Ip610zZq/Or/uCqgb51lnAdZM=", -        result1.getFirst()); -    Assert.assertEquals("first bPK", "urn:publicid:gv.at:cdid+AA", -        result1.getSecond()); -     -    Assert.assertEquals("second bPK", "uYst6hjKJvyp7s/ezD8zsnkcj9k=", -        result2.getFirst()); -    Assert.assertEquals("second bPK", "urn:publicid:gv.at:cdid+BB", -        result2.getSecond()); -     -  } -   -  @Test -  public void buildWbpkFn() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "FN+123456i"); -     -    Assert.assertEquals("wbPK", "k65HRxpVcoZ2OPZHo3j2LEn/JQE=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XFN+123456i", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkZvr() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "ZVR+123456"); -     -    Assert.assertEquals("wbPK", "g4JRKGS+AJxd9FU8k2tG8Lxrx6M=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XZVR+123456", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkErsb() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "ERSB+123456"); -     -    Assert.assertEquals("wbPK", "Bjnl0BofeJGgqynJP1r/ff6E1Rk=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XERSB+123456", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkXFn() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "XFN+123456i"); -     -    Assert.assertEquals("wbPK", "k65HRxpVcoZ2OPZHo3j2LEn/JQE=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XFN+123456i", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkXZvr() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "XZVR+123456"); -     -    Assert.assertEquals("wbPK", "g4JRKGS+AJxd9FU8k2tG8Lxrx6M=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XZVR+123456", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkXErsb() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "XERSB+123456"); -     -    Assert.assertEquals("wbPK", "Bjnl0BofeJGgqynJP1r/ff6E1Rk=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XERSB+123456", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildWbpkOthers() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_WBPK + "XABC+123456"); -     -    Assert.assertEquals("wbPK", "wv96/xKUyi6YoYGv7IcIlFTsJIk=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:wbpk+XABC+123456", -        result1.getSecond()); -     -  } -   -  @Test -  public void buildEidasId() throws EaafBuilderException { -     -    Pair<String, String> result1 = BpkBuilder.generateAreaSpecificPersonIdentifier( -        BASEID, EaafConstants.URN_PREFIX_EIDAS + "AT+ES"); -     -    Assert.assertEquals("eidas", "AT/ES/7AuLZNKsiRr97yvLsQ16SZ6r0q0=", -        result1.getFirst()); -    Assert.assertEquals("wbPK", "urn:publicid:gv.at:eidasid+AT+ES", -        result1.getSecond()); -     -  } -   -  @Test -  public void normalizeNullTarget() { -    Assert.assertNull("Wrong normalized target",   -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(null)); -      -  } -   -  @Test -  public void normalizeBpkTarget() { -    String target = EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(target)); -     -  } -   -  @Test -  public void normalizeWbpkTargetWithX() { -    String target = EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(target)); -     -  } -   -  @Test -  public void normalizeWbpkTargetWithOutXNoMapping() { -    String target = EaafConstants.URN_PREFIX_WBPK + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(target)); -     -  } -   -  @Test -  public void normalizeWbpkTargetWithOutXMappingFn() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "XFN+123456i",  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(EaafConstants.URN_PREFIX_WBPK + "FN+123456i")); -     -  } -   -  @Test -  public void normalizeWbpkTargetWithOutXMappingZvr() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "XZVR+1122334455",  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(EaafConstants.URN_PREFIX_WBPK + "ZVR+1122334455")); -     -  } -   -  @Test -  public void normalizeWbpkTargetWithOutXMappingErsb() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "XERSB+998877665544",  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(EaafConstants.URN_PREFIX_WBPK + "ERSB+998877665544")); -     -  } -   -  @Test -  public void normalizeEidasTarget() { -    String target = EaafConstants.URN_PREFIX_EIDAS + RandomStringUtils.randomAlphabetic(2)  -        + "+" + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCommonFormat(target)); -     -  } -   -  @Test -  public void calcNormalizeNullTarget() { -    Assert.assertNull("Wrong normalized target",   -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(null)); -      -  } -   -  @Test -  public void calcNormalizeBpkTarget() { -    String target = EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(target)); -     -  } -   -  @Test -  public void calcNormalizeWbpkTargetWithoutX() { - -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "FN+123456i",  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(EaafConstants.URN_PREFIX_WBPK + "FN+123456i")); -     -  } -   -  @Test -  public void calcNormalizeWbpkTargetWithOutXNoMapping() { -    String target = EaafConstants.URN_PREFIX_WBPK + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(target)); -     -  } -   -  @Test -  public void calcNormalizeWbpkTargetWithXMappingFn() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "FN+123456i",  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(EaafConstants.URN_PREFIX_WBPK + "XFN+123456i")); -     -  } -   -  @Test -  public void calcNormalizeWbpkTargetWithXMappingZvr() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "ZVR+1122334455",  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(EaafConstants.URN_PREFIX_WBPK + "XZVR+1122334455")); -     -  } -   -  @Test -  public void calcNormalizeWbpkTargetWithXMappingErsb() { -    Assert.assertEquals("Wrong normalized target",  -        EaafConstants.URN_PREFIX_WBPK + "ERSB+998877665544",  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat( -            EaafConstants.URN_PREFIX_WBPK + "XERSB+998877665544")); -     -  } -   -  @Test -  public void calcNormalizeEidasTarget() { -    String target = EaafConstants.URN_PREFIX_EIDAS + RandomStringUtils.randomAlphabetic(2)  -        + "+" + RandomStringUtils.randomAlphabetic(2); -    Assert.assertEquals("Wrong normalized target",  -        target,  -        BpkBuilder.normalizeBpkTargetIdentifierToCalculationFormat(target)); -     -  } -   -} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/controller/ProtocolFinalizationControllerTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/controller/ProtocolFinalizationControllerTest.java new file mode 100644 index 00000000..4341d141 --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/controller/ProtocolFinalizationControllerTest.java @@ -0,0 +1,359 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.controller; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.SerializationUtils; + +import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; +import at.gv.egiz.eaaf.core.api.gui.GroupDefinition; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.auth.dummy.DummyDefaultErrorService; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.ActionType; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.LogLevel; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; +import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiFormBuilder; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/SpringTest-context_eaaf_core.xml", "/SpringTest-context_eaaf_auth.xml"}) +public class ProtocolFinalizationControllerTest { + +  @Autowired IConfiguration config; +  @Autowired ProtocolFinalizationController controller; +  @Autowired DummyGuiBuilderConfigurationFactory guiConfigFactory; +  @Autowired DummyGuiFormBuilder guiBuilder; +  @Autowired IPendingRequestIdGenerationStrategy requestIdValidationStragegy; +  @Autowired ITransactionStorage storage; +  @Autowired DummyDefaultErrorService errorService; +   +  /** +   * jUnit test initializer. +   */ +  @Before +  public void initialize() { +    errorService.setErrorIdTokenForRedirect(null); +    errorService.setLogLevel(LogLevel.WARN); +    errorService.setTicketType(ActionType.NO_TICKET); +     +  } +   +  @Test +  public void performErrorRedirectNoToken() throws EaafException, IOException { +     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    // perform test +    controller.errorRedirect(httpReq, httpResp);     +     +    //validate state +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "auth.26", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("auth.26")); +     +    assertFalse("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +            +  } +   +  @Test +  public void performErrorRedirect() throws EaafException, IOException { +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    String token = requestIdValidationStragegy.generateExternalPendingRequestId(); +    httpReq.setParameter(EaafConstants.PARAM_HTTP_ERROR_CODE, token); +     +    TestRequestImpl protocolRequest = new TestRequestImpl(); +    Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); +     +    protocolRequest.setSpConfig(new DummySpConfiguration(spConfig, config)); +    Throwable throwable = new EaafException("internal.00"); +    final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); +    final byte[] serialized = SerializationUtils.serialize(exceptionContainer); +    storage.put(token, serialized, -1); +     +    // perform test +    controller.errorRedirect(httpReq, httpResp);     +     +    //validate state +    assertNull("Exception not removed from cache", storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(token))); +     +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "internal.00", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("internal.00")); +            +    assertFalse("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +     +  } +   +  @Test +  public void performErrorHandlingNoToken() throws EaafException, IOException { +     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    // perform test +    controller.errorHandling(httpReq, httpResp);     +     +    //validate state +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "auth.26", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("auth.26")); +    +    assertFalse("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +     +  } + +  @Test +  public void performErrorHandlingWithToken() throws EaafException, IOException {     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    String token = requestIdValidationStragegy.generateExternalPendingRequestId(); +    httpReq.setParameter(EaafConstants.PARAM_HTTP_ERROR_CODE, token); +     +    TestRequestImpl protocolRequest = new TestRequestImpl(); +    Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); +     +    protocolRequest.setSpConfig(new DummySpConfiguration(spConfig, config)); +    Throwable throwable = new EaafException("internal.00"); +    final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); +    final byte[] serialized = SerializationUtils.serialize(exceptionContainer); +    storage.put(token, serialized, -1); +     +    // perform test +    controller.errorHandling(httpReq, httpResp);     +     +    //validate state +     +    assertNull("Exception not removed from cache", storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(token))); +     +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "internal.00", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("internal.00")); +            +     +    assertFalse("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +  } +   +  @Test +  public void performErrorHandlingWithTokenAndRedirect() throws EaafException, IOException {     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    String token = requestIdValidationStragegy.generateExternalPendingRequestId(); +    httpReq.setParameter(EaafConstants.PARAM_HTTP_ERROR_CODE, token); +     +    TestRequestImpl protocolRequest = new TestRequestImpl(); +    Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); +     +    protocolRequest.setSpConfig(new DummySpConfiguration(spConfig, config)); +    protocolRequest.setTransactionId(RandomStringUtils.randomAlphanumeric(10)); +     +    Throwable throwable = new EaafException("internal.00"); +    final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); +    final byte[] serialized = SerializationUtils.serialize(exceptionContainer); +    storage.put(token, serialized, -1); +     +    String secondErrorTicket = requestIdValidationStragegy.generateExternalPendingRequestId(); +    errorService.setErrorIdTokenForRedirect(secondErrorTicket); +    errorService.setTicketType(ActionType.TICKET); +     +     +    // perform test +    controller.errorHandling(httpReq, httpResp);     +     +    //validate state +    assertNull("Exception not removed from cache", storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(token))); +     +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "internal.00", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("internal.00")); +            +    byte[] secondErrorSerialized = storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(secondErrorTicket), byte[].class); +    assertNotNull("Exception not removed from cache", secondErrorSerialized); +    ExceptionContainer secondError = (ExceptionContainer)  SerializationUtils.deserialize(secondErrorSerialized); +    assertEquals("wrong pengingReq", protocolRequest.getUniqueTransactionIdentifier(),  +        secondError.getPendingRequest().getUniqueTransactionIdentifier()); +    assertEquals("wrong exception", throwable.getMessage(), secondError.getExceptionThrown().getMessage()); +     +    assertTrue("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +     +  } +   +  @Test +  public void performErrorHandlingWithoutTokenAndRedirect() throws EaafException, IOException {     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpReq.addHeader("Accept", "application/json"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse();     +    guiConfigFactory.setErrorGuiConfig( +        new DummyGuiBuilderConfig("https://localhost/authhandler", "jUnitView", "/junitSubmit")); +     +    String token = requestIdValidationStragegy.generateExternalPendingRequestId(); +    httpReq.setParameter(EaafConstants.PARAM_HTTP_ERROR_CODE, token); +     +    TestRequestImpl protocolRequest = new TestRequestImpl(); +    Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); +     +    protocolRequest.setSpConfig(new DummySpConfiguration(spConfig, config)); +    protocolRequest.setTransactionId(RandomStringUtils.randomAlphanumeric(10)); +     +    Throwable throwable = new EaafException("internal.00"); +    final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); +    final byte[] serialized = SerializationUtils.serialize(exceptionContainer); +    storage.put(token, serialized, -1); +     +    String secondErrorTicket = requestIdValidationStragegy.generateExternalPendingRequestId(); +    errorService.setErrorIdTokenForRedirect(secondErrorTicket); +    errorService.setTicketType(ActionType.ERRORPAGE); +     +    // perform test +    controller.errorHandling(httpReq, httpResp);     +     +    //validate state +    assertNull("Exception not removed from cache", storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(token))); +     +    assertNotNull("No gui builder request", guiBuilder.getConfig()); +    assertFalse("No GUI form infos", guiBuilder.getConfig().getViewParameters().isEmpty()); +    assertTrue("No GUI form infos", guiBuilder.getConfig().getViewParameters().containsKey("msg"));     +    Map<String, Object> params = ((Map<String, Object>) guiBuilder.getConfig().getViewParameters().get("msg")); +    assertFalse("No GUI form infos", params.isEmpty());     +    assertEquals("wrong intErrorCode", "internal.00", params.get("errorCode")); +    assertTrue("wrong extErrorCode", ((String) params.get("extErrorCode")).contains("internal.00")); +            +    byte[] secondErrorSerialized = storage.get( +        requestIdValidationStragegy.getPendingRequestIdWithOutChecks(secondErrorTicket), byte[].class); +    assertNotNull("Exception not removed from cache", secondErrorSerialized); +    ExceptionContainer secondError = (ExceptionContainer)  SerializationUtils.deserialize(secondErrorSerialized); +    assertEquals("wrong pengingReq", protocolRequest.getUniqueTransactionIdentifier(),  +        secondError.getPendingRequest().getUniqueTransactionIdentifier()); +    assertEquals("wrong exception", throwable.getMessage(), secondError.getExceptionThrown().getMessage()); +     +    assertTrue("GUI sp redirect", guiBuilder.getConfig().getViewParameters() +        .containsKey(DummyDefaultErrorService.JUNIT_EL_SPREDIRECT)); +     +  } +   +   +  private class DummyGuiBuilderConfig extends AbstractGuiFormBuilderConfiguration  +      implements ModifyableGuiBuilderConfiguration { +     +    /** +     * DummyGuiBuilderConfiguration. +     *  +     * @param authUrl AuthUrl +     * @param viewName viewName +     * @param formSubmitEndpoint submit endpoint +     */ +    DummyGuiBuilderConfig(String authUrl, String viewName, String formSubmitEndpoint) { +      super(authUrl, viewName, formSubmitEndpoint); +       +    } + +    @Override +    public String getDefaultContentType() { +      return null; +       +    } +     +    @Override +    protected void putSpecificViewParameters() { +       +       +    } +     +    @Override +    protected GroupDefinition getFromGroup() { +      return null; +       +    } + +    @Override +    public void putCustomParameterWithOutEscaption(GroupDefinition group, String key, Object value) { +      setViewParameter(group, key, value); +       +    } + +    @Override +    public void putCustomParameter(GroupDefinition group, String key, String value) { +      setViewParameter(group, key, value); +       +    } +  }; +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthenticationDataTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthenticationDataTest.java new file mode 100644 index 00000000..9d99b158 --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthenticationDataTest.java @@ -0,0 +1,85 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.data; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; + +@RunWith(BlockJUnit4ClassRunner.class) +public class AuthenticationDataTest { + +  @Test +  public void formatedDateButNotSet() { +    AuthenticationData authData = new AuthenticationData(); +    assertNull("formatedDateOfBirth", authData.getDateOfBirthFormated("dd/MM/yyy")); +     +  } +   +  @Test +  public void formatedDateButInvalidPattern() { +    AuthenticationData authData = new AuthenticationData(); +    authData.setDateOfBirth("1940-01-01");     +    assertNull("formatedDateOfBirth", authData.getDateOfBirthFormated("aa-bb-cccc")); +     +  } +   +  @Test +  public void validDateStatic() {     +    AuthenticationData authData = new AuthenticationData(); +     +    String date = "1940-01-01"; +    authData.setDateOfBirth(date);     +         +    assertNotNull("birthday", authData.getDateOfBirth());     +    assertEquals("birthday attribute", date,  +        authData.getDateOfBirth());     +    assertEquals("birthday attribute", "01/01/1940",  +        authData.getDateOfBirthFormated("dd/MM/yyy")); +     +  } +   +   +  @Test +  public void validButNotUsal() {     +    AuthenticationData authData = new AuthenticationData(); +    authData.setDateOfBirth("1970-00-00");     +         +    assertNotNull("birthday", authData.getDateOfBirth());     +    assertEquals("birthday attribute", "1970-00-00",  +        authData.getDateOfBirth());     +    assertNull("formatedDateOfBirth", authData.getDateOfBirthFormated("dd/MM/yyy")); +     +  } +   +  @Test +  public void invalidDate() {     +    AuthenticationData authData = new AuthenticationData(); +    authData.setDateOfBirth("1970/00/00");     +         +    assertNull("birthday", authData.getDateOfBirth());     +    assertNull("formatedDateOfBirth", authData.getDateOfBirthFormated("dd/MM/yyy")); +     +  } +   +     +  @Test +  public void validDateRandom() {     +    AuthenticationData authData = new AuthenticationData(); +     +    String date = RandomStringUtils.randomNumeric(4) + "-" + RandomStringUtils.randomNumeric(2)  +        + "-" + RandomStringUtils.randomNumeric(2); +    authData.setDateOfBirth(date);     +         +    assertNotNull("birthday", authData.getDateOfBirth());     +    assertEquals("birthday attribute", date,  +        authData.getDateOfBirth()); +     +  } +   +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/dummy/DummyDefaultErrorService.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/dummy/DummyDefaultErrorService.java new file mode 100644 index 00000000..347f9b5c --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/auth/dummy/DummyDefaultErrorService.java @@ -0,0 +1,115 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.dummy; + +import java.text.MessageFormat; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +public class DummyDefaultErrorService implements IErrorService { +  private static final String TECH_LOG_MSG = "errorCode={0} Message={1}";   +  +  public static final String JUNIT_EL_SPREDIRECT = "spRedirect"; +   +  @Autowired IConfiguration basicConfig; +  @Autowired IStatusMessenger statusMessager;  +   +  @Setter +  private ActionType ticketType = ActionType.NO_TICKET; +   +  @Setter +  private LogLevel logLevel = LogLevel.WARN; +  +  @Setter +  private String errorIdTokenForRedirect; +   +  @Override +  public String getExternalCodeFromInternal(String internalCode) { +    return statusMessager.mapInternalErrorToExternalError(internalCode); +     +  } + +  @Override +  public IHandleData createHandleData(Throwable throwable, boolean supportRedirctToSp) throws EaafException { +    String internalErrorId = extractInternalErrorCode(throwable);     +     +    return HandleData.builder() +        .throwable(throwable) +        .internalErrorCode(internalErrorId) +        .actionType(ticketType) +        .logLevel(logLevel) +        .errorIdTokenForRedirect(errorIdTokenForRedirect) +        .allowSpRedirct(supportRedirctToSp) +        .build();    +     +  } + +  @Override +  public void displayErrorData(ModifyableGuiBuilderConfiguration c, IHandleData errorData,  +      HttpServletRequest httpReq) throws EaafException {     +    if (((HandleData)errorData).isAllowSpRedirct()) { +      c.putCustomParameter(null, JUNIT_EL_SPREDIRECT, "toSpWithToken:" + errorData.getErrorIdTokenForRedirect()); +       +    } +     +         +  } +   +  private String extractInternalErrorCode(Throwable throwable) { +    Throwable originalException; +    if (throwable instanceof TaskExecutionException +        && ((TaskExecutionException) throwable).getOriginalException() != null) { +      originalException = ((TaskExecutionException) throwable).getOriginalException(); + +    } else { +      originalException = throwable; + +    } + +    if (!(originalException instanceof EaafException)) { +      return IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC; + +    } else { +      return ((EaafException) originalException).getErrorId(); + +    } +  } +     +  @Builder +  static class HandleData implements IHandleData { +     +    @Getter +    private boolean allowSpRedirct; +     +    @Getter +    private String errorIdTokenForRedirect; +     +    @Getter +    private final Throwable throwable; +     +    @Getter +    private String internalErrorCode; +     +    @Getter +    private ActionType actionType; + +    @Getter +    private LogLevel logLevel; +     +    public String getPreFormatedErrorMessage() { +      return MessageFormat.format(TECH_LOG_MSG, internalErrorCode, throwable.getMessage()); +       +    } +     +  } +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiFormBuilder.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiFormBuilder.java new file mode 100644 index 00000000..5e12e7bc --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiFormBuilder.java @@ -0,0 +1,44 @@ +package at.gv.egiz.eaaf.core.impl.idp.module.gui; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGuiFormBuilder; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import lombok.Getter; + +@Getter +public class DummyGuiFormBuilder implements IGuiFormBuilder { + +  private String loggerName; +   +  private IGuiBuilderConfiguration config; +   +  private String contentType; +   +  @Override +  public void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IGuiBuilderConfiguration config, +      String loggerName) throws GuiBuildException { +    this.loggerName = loggerName; +    this.config = config; + +  } + +  @Override +  public void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IGuiBuilderConfiguration config, +      String contentType, String loggerName) throws GuiBuildException { +    this.loggerName = loggerName; +    this.config = config; +    this.contentType = contentType; +     +  } + +  @Override +  public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config, +      String loggerName) throws GuiBuildException { +    return null; +     +  } + +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java index e2cdd1ee..8fe9e2eb 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java @@ -2,6 +2,11 @@ package at.gv.egiz.eaaf.core.impl.idp.module.gui;  import java.io.InputStream; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.http.MediaType; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration;  import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;  import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;  import at.gv.egiz.eaaf.core.impl.gui.AbstractVelocityGuiFormBuilderImpl; @@ -30,6 +35,13 @@ public class DummyVelocityGuiFormBuilder extends AbstractVelocityGuiFormBuilderI      this.internalTemplate = internalTemplate;    } +  @Override +  public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config, +      String loggerName) throws GuiBuildException { +    return MediaType.TEXT_XML_VALUE; +     +  } + diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummySpConfiguration.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummySpConfiguration.java index 87e91609..ed113683 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummySpConfiguration.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummySpConfiguration.java @@ -1,7 +1,12 @@  package at.gv.egiz.eaaf.core.impl.idp.module.test; +import java.util.Arrays; +import java.util.Collections; +import java.util.List;  import java.util.Map; +import org.apache.commons.lang3.StringUtils; +  import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  import at.gv.egiz.eaaf.core.impl.idp.conf.SpConfigurationImpl; @@ -19,5 +24,12 @@ public class DummySpConfiguration extends SpConfigurationImpl {      return getConfigurationValue("target");    } +   +  @Override +  public List<String> getRequiredLoA() { +    String loa = getConfigurationValue("loa");     +    return StringUtils.isNotEmpty(loa) ? Arrays.asList(loa) : Collections.emptyList();   +         +  }  } diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/test/SpringExpressionEvaluatorTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/test/SpringExpressionEvaluatorTest.java index 4aa32360..01fc6bb8 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/test/SpringExpressionEvaluatorTest.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/test/SpringExpressionEvaluatorTest.java @@ -59,8 +59,17 @@ public class SpringExpressionEvaluatorTest {    @Test    public void testEvaluateExpressionWithCtx() { -    ctx.put("myProperty", false); +    ctx.put("myProperty", false);     +    ctx.put("stringProperty", "aabbccddee"); +     +    //check basic boolean flags      assertFalse(expressionEvaluator.evaluate(ctx, "ctx['myProperty']")); +     +    //check String flags +    assertTrue(expressionEvaluator.evaluate(ctx, "'aabbccddee'.equals(ctx['stringProperty'])")); +    assertFalse(expressionEvaluator.evaluate(ctx, "'aabbccddee'.equals(ctx['notExist'])")); +    assertFalse(expressionEvaluator.evaluate(ctx, "'aabbccddee'.equals(ctx['myProperty'])")); +        }    @Test diff --git a/eaaf_core/src/test/resources/SpringTest-context_eaaf_auth.xml b/eaaf_core/src/test/resources/SpringTest-context_eaaf_auth.xml new file mode 100644 index 00000000..0cb8fa24 --- /dev/null +++ b/eaaf_core/src/test/resources/SpringTest-context_eaaf_auth.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" +  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +  xmlns:context="http://www.springframework.org/schema/context" +  xmlns:tx="http://www.springframework.org/schema/tx" +  xmlns:aop="http://www.springframework.org/schema/aop" +  xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd +    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd +    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd +    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + +  <import resource="classpath:/spring/eaaf_utils.beans.xml"/> + +  <bean id="protocolAuthService" +        class="at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService"> +    <property name="guiBuilder" ref="dummyGuiFormBuilder" /> +         +  </bean> + +  <bean id="protocolFinalizationController" +        class="at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController" /> + +  <bean id="dummyErrorService" +        class="at.gv.egiz.eaaf.core.impl.idp.auth.dummy.DummyDefaultErrorService" /> + +  <!-- Dummy services for testing --> +  <bean id="dummyGuiBuilderConfigFactory"  +        class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory"/> +   +  <bean id="dummyGuiFormBuilder" +        class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiFormBuilder"/> +   +  <bean id="dummyAuthManager" +        class="at.gv.egiz.eaaf.core.impl.idp.auth.DummyAuthManager" /> +   +  <bean id="dummyRevisionLogger" +        class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> + +  <bean id="dummyStatisticLogger" +        class="at.gv.egiz.eaaf.core.impl.logging.DummyStatisticLogger" /> + +  <bean id="DummyTransactionStorage" +        class="at.gv.egiz.eaaf.core.impl.idp.process.spring.test.DummyTransactionStorage" /> + +  <bean id="DummyStatusMessager" +        class="at.gv.egiz.eaaf.core.impl.logging.DummyStatusMessager" /> + +  <bean id="springElAwareExpressionEvaluator" +        class="at.gv.egiz.eaaf.core.impl.idp.process.spring.SpringExpressionEvaluator" /> + +  <bean id="processEngine" +        class="at.gv.egiz.eaaf.core.impl.idp.process.ProcessEngineImpl"> +    <property name="transitionConditionExpressionEvaluator" +              ref="springElAwareExpressionEvaluator" /> +  </bean> + +  <bean id="moduleRegistration" +        class="at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration" /> + +  <bean id="ProcessInstanceStoreage" +        class="at.gv.egiz.eaaf.core.impl.idp.process.dao.ProcessInstanceStoreDaoImpl" /> + +  <bean id="RequestStorage" +        class="at.gv.egiz.eaaf.core.impl.idp.auth.RequestStorage" /> + +  <bean id="simplePendingRequestIdGenerationStrategy" +        class="at.gv.egiz.eaaf.core.impl.utils.SimplePendingRequestIdGenerationStrategy" /> + +</beans> | 
