diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20')
32 files changed, 1579 insertions, 345 deletions
diff --git a/eaaf_modules/eaaf_module_auth_sl20/pom.xml b/eaaf_modules/eaaf_module_auth_sl20/pom.xml index b87c5c98..c4bb0714 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/pom.xml +++ b/eaaf_modules/eaaf_module_auth_sl20/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.1.3-SNAPSHOT</version> + <version>1.2.1-SNAPSHOT</version> </parent> <artifactId>eaaf_module_auth_sl20</artifactId> <name>Generic SL2.0 authentication</name> @@ -32,7 +32,6 @@ <dependency> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf-core</artifactId> - <version>${egiz.eaaf.version}</version> </dependency> <dependency> <groupId>org.bitbucket.b_c</groupId> @@ -52,6 +51,39 @@ <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.asitplus.hsmfacade</groupId> + <artifactId>provider</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>iaik.prod</groupId> + <artifactId>iaik_jce_full</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>iaik.prod</groupId> + <artifactId>iaik_eccelerate</artifactId> + <scope>test</scope> + </dependency> + </dependencies> <build> @@ -61,32 +93,7 @@ </resource> </resources> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.0</version> - <configuration> - <source>${java.version}</source> - <target>${java.version}</target> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>3.1.1</version> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <addDefaultImplementationEntries>true</addDefaultImplementationEntries> - <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> - </manifest> - </archive> - </configuration> - </plugin> - + <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> @@ -99,23 +106,20 @@ </filesets> </configuration> </plugin> - - <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> </plugins> </build> + <repositories> + <repository> + <id>MOA_Sig_local</id> + <name>MOA-Sig Dependencies</name> + <releases> + <enabled>true</enabled> + <checksumPolicy>ignore</checksumPolicy> + </releases> + <layout>default</layout> + <url>file://${basedir}/../eaaf_module_moa-sig/repository</url> + </repository> + </repositories> + </project>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java index e9932ae8..d561a0bc 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java @@ -29,11 +29,9 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule private int priority = 3; public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4"); - + @Autowired(required = true) protected IConfiguration authConfig; - @Autowired(required = true) - private AbstractAuthenticationManager authManager; @Override public int getPriority() { @@ -51,9 +49,9 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule @PostConstruct protected void initalSL20Authentication() { - // parameter to whiteList - authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); - authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); + // parameter to whiteList + AbstractAuthenticationManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); + AbstractAuthenticationManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java index 11fd41fb..74d67d01 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java @@ -7,37 +7,41 @@ public class Constants { public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX + ".vda.authblock.transformation.id"; - + //KeyStore configuration - public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE = CONFIG_PROP_PREFIX + ".security.keystore.type"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME = CONFIG_PROP_PREFIX + ".security.keystore.name"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX + ".security.keystore.password"; - - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = + + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX + ".security.sign.password"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX + ".security.encryption.alias"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX + ".security.encryption.password"; //TrustStore configuration - public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE = + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE = CONFIG_PROP_PREFIX + ".security.truststore.type"; - public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME = + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME = CONFIG_PROP_PREFIX + ".security.truststore.name"; - public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH = + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH = CONFIG_PROP_PREFIX + ".security.truststore.path"; - public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD = + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD = CONFIG_PROP_PREFIX + ".security.truststore.password"; - - + + public static final String CONFIG_PROP_SECURITY_SIG_ALG_RSA = + CONFIG_PROP_PREFIX + ".security.sigalg.rsa"; + public static final String CONFIG_PROP_SECURITY_SIG_ALG_ECC = + CONFIG_PROP_PREFIX + ".security.sigalg.ecc"; + public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java index af155206..62779072 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java @@ -12,5 +12,5 @@ public class EventCodes { public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112; public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; - public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113; + public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4114; } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java index a14fbe9e..f0d993ca 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java @@ -1,15 +1,26 @@ package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; public class SL20EidDataValidationException extends SL20Exception { - private static final long serialVersionUID = 1L; + + private static final long serialVersionUID = -2604130523926584663L; public SL20EidDataValidationException(final Object[] parameters) { - super("sl20.07", parameters); + this("99", parameters); } - + public SL20EidDataValidationException(final Object[] parameters, final Throwable e) { - super("sl20.07", parameters, e); + this("99", parameters, e); + + } + + public SL20EidDataValidationException(final String subErrorId, final Object[] parameters) { + super("sl20.07." + subErrorId, parameters); + + } + + public SL20EidDataValidationException(final String subErrorId, final Object[] parameters, final Throwable e) { + super("sl20.07." + subErrorId, parameters, e); } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java index 12921ad6..08373a2d 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java @@ -4,7 +4,7 @@ import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; public class SL20Exception extends EaafAuthenticationException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = -6716465236880571576L; public SL20Exception(final String messageId, final Object[] parameters) { super(messageId, parameters); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java index 6c11fa63..9dcfbe75 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java @@ -1,25 +1,29 @@ package at.gv.egiz.eaaf.modules.auth.sl20.tasks; import java.io.Serializable; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; import java.security.cert.CertificateEncodingException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; +import org.apache.commons.lang3.time.StopWatch; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.message.BasicNameValuePair; import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -33,7 +37,6 @@ import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; import at.gv.egiz.eaaf.modules.auth.sl20.Constants; import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; @@ -42,12 +45,16 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants.VdaAuthMethod; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils.Sl20ResponseHolder; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; +import lombok.extern.slf4j.Slf4j; +@Slf4j public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualEidRequestTask.class); + private static final String FRIENDLYNAME_HTTP_CLIENT = "A-Trust Client"; + @Autowired(required = true) private IHttpClientFactory httpClientFactory; @Autowired(required = true) @@ -60,7 +67,8 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl log.debug("Starting SL2.0 authentication process .... "); revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth"); - + + String vdaQualEidDUrl = null; try { // get service-provider configuration final ISpConfiguration oaConfig = pendingReq.getServiceProviderConfiguration(); @@ -72,7 +80,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl } // get basic configuration parameters - final String vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext); + vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext); if (StringUtils.isEmpty(vdaQualEidDUrl)) { log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")"); throw new SL20Exception("sl20.03", new Object[] { "NO VDA URL for qualified eID" }); @@ -89,55 +97,48 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl // build request container final String qualEidReqId = Random.nextProcessReferenceValue(); - final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, null, null, - signedQualEidCommand); + final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, + pendingReq.getUniqueTransactionIdentifier(), null, signedQualEidCommand); // build http POST request final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualEidDUrl).build()); final List<NameValuePair> parameters = new ArrayList<>(); parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, - Base64Url.encode(sl20Req.toString().getBytes("UTF-8")))); - - //set specific authentication method if it was selection by process step before - VdaAuthMethod authMethod = getVdaAuthMethodFromContext(executionContext); - if (authMethod != null) { - log.debug("Request VDA with authType: {}", authMethod); - parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_AUTH_METHOD_PARAM, - authMethod.getAuthMethod())); - } + Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8)))); - //set VDA sessionId if it was available on context - String vdaSessionId = getVdaSessionIdFromContext(executionContext); - if (vdaSessionId != null) { - log.trace("Request VDA with sessionId: {}", vdaSessionId); - parameters.add(new BasicNameValuePair( - SL20Constants.PARAM_SL20_REQ_AUTH_VDA_SESSIONID, - vdaSessionId)); - - } - - - - httpReq.setEntity(new UrlEncodedFormEntity(parameters)); + //inject additional request parameters + injectAdditionalSL20RequestParams(parameters, executionContext, request); - // build http GET request - // URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); - // sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, - // Base64Url.encode(sl20Req.toString().getBytes())); - // HttpGet httpReq = new HttpGet(sl20ReqUri.build()); + httpReq.setEntity(new UrlEncodedFormEntity(parameters)); // set native client header httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE); - log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes("UTF-8"))); + log.trace("Request VDA via SL20 with: {}", + Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8))); // request VDA - final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); - - // parse response - log.info("Receive response from VDA ... "); - final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp); - final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); + + final StopWatch watch = StopWatch.createStarted(); + log.info("Requesting {} for authentication ... ", FRIENDLYNAME_HTTP_CLIENT); + final Sl20ResponseHolder httpResp = httpClientFactory.getHttpClient(false).execute( + httpReq, SL20HttpBindingUtils.sl20ResponseHandler()); + + watch.stop(); + log.info("Respone from {} received after: {}[ms] with statusCode: {}", FRIENDLYNAME_HTTP_CLIENT, + watch.getTime(TimeUnit.MILLISECONDS), httpResp.getResponseStatus().getStatusCode()); + + //check on error on http channel + if (httpResp.getError() != null) { + log.info("Basic SL2.0 response processing has an error. HTTP-StatusCode: {} ErrorMsg: {}", + httpResp.getResponseStatus().getStatusCode(), httpResp.getError().getMessage()); + throw httpResp.getError(); + + } + + // parse response + final VerificationResult respPayloadContainer = + SL20JsonExtractorUtils.extractSL20PayLoad(httpResp.getResponseBody(), null, false); if (respPayloadContainer.isValidSigned() == null) { log.debug("Receive unsigned payLoad from VDA"); @@ -158,10 +159,10 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false); // create forward SL2.0 command - final ObjectNode sl20Forward = sl20Resp.deepCopy(); + final ObjectNode sl20Forward = httpResp.getResponseBody().deepCopy(); SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, command.deepCopy(), signedCommand); - + // store pending request pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, qualEidReqId); @@ -201,21 +202,58 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl } catch (final EaafAuthenticationException e) { throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); + } catch (final SocketException | SocketTimeoutException e) { + log.error("SL2.0 Authentication has a VDA connector error. Endpoint: {}", + vdaQualEidDUrl, e); + throw new TaskExecutionException(pendingReq, e.getMessage(), + new SL20Exception("sl20.02", new Object[] { e.getMessage()}, e)); + } catch (final Exception e) { log.warn("SL2.0 Authentication FAILED with a generic error.", e); throw new TaskExecutionException(pendingReq, e.getMessage(), e); - } finally { - TransactionIdUtils.removeTransactionId(); - TransactionIdUtils.removeSessionId(); + } + + } + protected void injectAdditionalSL20RequestParams(List<NameValuePair> parameters, + ExecutionContext executionContext, HttpServletRequest request) { + //set specific authentication method if it was selection by process step before + final VdaAuthMethod authMethod = getVdaAuthMethodFromContext(executionContext); + if (authMethod != null) { + log.debug("Request VDA with authType: {}", authMethod); + parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_AUTH_METHOD_PARAM, + authMethod.getAuthMethod())); } + //set VDA sessionId if it was available on context + final String vdaSessionId = getVdaSessionIdFromContext(executionContext); + if (vdaSessionId != null) { + log.trace("Request VDA with sessionId: {}", vdaSessionId); + parameters.add(new BasicNameValuePair( + SL20Constants.PARAM_SL20_REQ_AUTH_VDA_SESSIONID, + vdaSessionId)); + + } + + //set i18n language into VDA request + final Locale locale = LocaleContextHolder.getLocale(); + final String language = locale.getLanguage(); + if (StringUtils.isNotEmpty(language)) { + log.trace("Find i18n context). Inject locale: {} into VDA request", locale.getLanguage()); + parameters.add(new BasicNameValuePair( + SL20Constants.PARAM_SL20_REQ_AUTH_VDA_LOCALE, + language.toUpperCase(locale))); + + } else { + log.info("Find i18n context, but Language is UNKNOWN. It will be ignored"); + + } } /** - * Get ExecutionContext parameter-key for VDA AuthMethod information. - * + * Get ExecutionContext parameter-key for VDA AuthMethod information. + * * @return Key to get AuthMethod from {@link ExecutionContext} */ protected abstract String getAuthMethodContextParamKey(); @@ -231,34 +269,34 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl */ protected abstract String buildSignedQualifiedEidCommand() throws CertificateEncodingException, SL20Exception; - + private VdaAuthMethod getVdaAuthMethodFromContext(ExecutionContext executionContext) { - Serializable authMethodRaw = executionContext.get(getAuthMethodContextParamKey()); + final Serializable authMethodRaw = executionContext.get(getAuthMethodContextParamKey()); if (authMethodRaw instanceof String) { log.trace("Find authMethod parameter: {} on context", authMethodRaw); return VdaAuthMethod.fromString((String) authMethodRaw); - + } - + return null; } - + private String getVdaSessionIdFromContext(ExecutionContext executionContext) { - Serializable vdaSessionId = executionContext.get( + final Serializable vdaSessionId = executionContext.get( SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID); - if (vdaSessionId instanceof String + if (vdaSessionId instanceof String && StringUtils.isNotEmpty((CharSequence) vdaSessionId)) { executionContext.remove( SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID); - + log.trace("Find vdaSessionId parameter: {} on context", vdaSessionId); return (String) vdaSessionId; - + } - + return null; } - + private String extractVdaUrlForSpecificOa(final ISpConfiguration oaConfig, final ExecutionContext executionContext) { // load SP specific config for development and testing purposes diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java index 4786ff39..dfa05a89 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java @@ -8,8 +8,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.fasterxml.jackson.core.JsonParseException; @@ -22,7 +20,6 @@ import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder; import at.gv.egiz.eaaf.core.impl.utils.StreamUtils; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; import at.gv.egiz.eaaf.modules.auth.sl20.Constants; import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; @@ -35,9 +32,10 @@ import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20ResponseUtils; +import lombok.extern.slf4j.Slf4j; +@Slf4j public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class); @Autowired(required = true) private IJoseTools joseTools; @@ -82,13 +80,14 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result)); } catch (final JsonParseException e) { - log.warn("SL2.0 command or result is NOT valid JSON.", e); - log.debug("SL2.0 msg: " + sl20Result); + log.error("SL2.0 command or result is NOT valid JSON. Received msg: {}", sl20Result, e); throw new SL20Exception("sl20.02", new Object[] { "SL2.0 command or result is NOT valid JSON." }, e); } + log.info("Receive response from A-Trust. Starting response-message validation ... "); + // check on errorMessage final VerificationResult payLoadContainerErrorCheck = SL20JsonExtractorUtils.extractSL20PayLoad( sl20ReqObj, @@ -117,7 +116,7 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask log.debug("VDA provides an optional sessionId. Inject it to internal error-holder "); ex.setVdaSessionId(vdaSessionId); - } + } throw ex; } else { @@ -161,7 +160,6 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask } } catch (final EaafAuthenticationException e) { - log.warn("SL2.0 processing error:", e); if (sl20Result != null) { log.debug("Received SL2.0 result: " + sl20Result); } @@ -170,8 +168,8 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); } catch (final Exception e) { - log.warn("ERROR:", e); - log.warn("SL2.0 Authentication FAILED with a generic error.", e); + + if (sl20Result != null) { log.debug("Received SL2.0 result: " + sl20Result); } @@ -212,11 +210,6 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); } - - } finally { - TransactionIdUtils.removeTransactionId(); - TransactionIdUtils.removeSessionId(); - } } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java new file mode 100644 index 00000000..5b221bbe --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java @@ -0,0 +1,374 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.PublicKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.jose4j.jca.ProviderContext; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwx.Headers; +import org.jose4j.jwx.JsonWebStructure; +import org.jose4j.keys.resolvers.X509VerificationKeyResolver; +import org.jose4j.lang.JoseException; +import org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.exception.EaafKeyUsageException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.utils.X509Utils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * {@link JoseUtils} provides static methods JWS and JWE processing. + * + * @author tlenz + * + */ +@Slf4j +public class JoseUtils { + + private static final Provider provider = new BouncyCastleProvider(); + + /** + * Create a JWS signature. + * + * <p> + * Use {@link org.jose4j.jws.AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case + * of a RSA based key and + * {@link org.jose4j.jws.AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256} + * in case of an ECC based key. + * </p> + * + * @param keyStore KeyStore that should be used + * @param keyAlias Alias of the private key + * @param keyPassword Password to access the key + * @param payLoad PayLoad to sign + * @param addFullCertChain If true the full certificate chain will be + * added, otherwise only the + * X509CertSha256Fingerprint is added into JOSE + * header + * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging + * purposes only + * @return Signed PayLoad in serialized form + * @throws EaafException In case of a key-access or key-usage error + * @throws JoseException In case of a JOSE error + */ + public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, + @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, + @Nonnull final String payLoad, boolean addFullCertChain, + @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { + return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, Collections.emptyMap(), + AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, + friendlyNameForLogging); + + } + + /** + * Create a JWS signature. + * + * <p> + * Use {@link org.jose4j.jws.AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case + * of a RSA based key and + * {@link org.jose4j.jws.AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256} + * in case of an ECC based key. + * </p> + * + * @param keyStore KeyStore that should be used + * @param keyAlias Alias of the private key + * @param keyPassword Password to access the key + * @param payLoad PayLoad to sign + * @param addFullCertChain If true the full certificate chain will be + * added, otherwise only the + * X509CertSha256Fingerprint is added into JOSE + * header + * @param joseHeaders HeaderName and HeaderValue that should be set + * into JOSE header + * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging + * purposes only + * @return Signed PayLoad in serialized form + * @throws EaafException In case of a key-access or key-usage error + * @throws JoseException In case of a JOSE error + */ + public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, + @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, + @Nonnull final String payLoad, boolean addFullCertChain, + @Nonnull final Map<String, String> joseHeaders, + @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { + return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, joseHeaders, + AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, + friendlyNameForLogging); + + } + + /** + * Create a JWS signature. + * + * @param keyStore KeyStore that should be used + * @param keyAlias Alias of the private key + * @param keyPassword Password to access the key + * @param payLoad PayLoad to sign + * @param addFullCertChain If true the full certificate chain will be + * added, otherwise only the + * X509CertSha256Fingerprint is added into JOSE + * header + * @param joseHeaders HeaderName and HeaderValue that should be set + * into JOSE header + * @param rsaAlgToUse Signing algorithm that should be used in case + * of a signing key based on RSA + * @param eccAlgToUse Signing algorithm that should be used in case + * of a signing key based on ECC + * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging + * purposes only + * @return Signed PayLoad in serialized form + * @throws EaafException In case of a key-access or key-usage error + * @throws JoseException In case of a JOSE error + */ + public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, + @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, + @Nonnull final String payLoad, boolean addFullCertChain, + @Nonnull final Map<String, String> joseHeaders, + @Nonnull final String rsaAlgToUse, @Nonnull final String eccAlgToUse, + @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { + + final JsonWebSignature jws = new JsonWebSignature(); + + // set payload + jws.setPayload(payLoad); + + // set JOSE headers + for (final Entry<String, String> el : joseHeaders.entrySet()) { + log.trace("Set JOSE header: {} with value: {} into JWS", el.getKey(), el.getValue()); + jws.setHeader(el.getKey(), el.getValue()); + + } + + // set signing information + final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore.getFirst(), keyAlias, keyPassword, true, friendlyNameForLogging); + + // set verification key + jws.setKey(convertToBcKeyIfRequired(signingCred.getFirst())); + + jws.setAlgorithmHeaderValue(getKeyOperationAlgorithmFromCredential( + jws.getKey(), rsaAlgToUse, eccAlgToUse, friendlyNameForLogging)); + + // set special provider if required + if (keyStore.getSecond() != null) { + log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName()); + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(keyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jws.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jws.setProviderContext(providerCtx); + + } + + if (addFullCertChain) { + jws.setCertificateChainHeaderValue(signingCred.getSecond()); + + } + + jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]); + + return jws.getCompactSerialization(); + + } + + /** + * Verify a JOSE signature. + * + * @param serializedContent Serialized content that should be verified + * @param trustedCerts Trusted certificates that should be used for + * verification + * @param constraints {@link AlgorithmConstraints} for verification + * @return {@link JwsResult} object + * @throws JoseException In case of a signature verification error + * @throws IOException In case of a general error + */ + public static JwsResult validateSignature(@Nonnull final String serializedContent, + @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints) + throws JoseException, IOException { + final JsonWebSignature jws = new JsonWebSignature(); + // set payload + jws.setCompactSerialization(serializedContent); + + // set security constrains + jws.setAlgorithmConstraints(constraints); + + // load signinc certs + Key selectedKey = null; + final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); + final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); + if (x5cCerts != null) { + log.debug("Found x509 certificate in JOSE header ... "); + log.trace("Sorting received X509 certificates ... "); + final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + + + + if (trustedCerts.contains(sortedX5cCerts.get(0))) { + selectedKey = sortedX5cCerts.get(0).getPublicKey(); + + } else { + log.info("Can NOT find JOSE certificate in truststore."); + if (log.isDebugEnabled()) { + try { + log.debug("Cert: {}", Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); + + } catch (final CertificateEncodingException e) { + log.warn("Can not create DEBUG output", e); + + } + } + } + + } else if (StringUtils.isNotEmpty(x5t256)) { + log.debug("Found x5t256 fingerprint in JOSE header .... "); + final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver( + trustedCerts); + selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); + + } else { + throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); + + } + + if (selectedKey == null) { + throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); + + } + + //set BouncyCastleProvider as default provider + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jws.setProviderContext(providerCtx); + + // set verification key + jws.setKey(convertToBcKeyIfRequired(selectedKey)); + + // load payLoad + return new JwsResult( + jws.verifySignature(), + jws.getUnverifiedPayload(), + jws.getHeaders(), + x5cCerts); + + } + + + /** + * Convert an ECC public-key into BouncyCastle implementation. + * + * <p> IAIK JCE / Eccelerate ECC Keys are not compatible to JWS impl.</p> + * @param input Key + * @return input Key, or BC ECC-Key in case of a ECC Key + */ + public static Key convertToBcKeyIfRequired(Key input) { + try { + if (input instanceof ECPublicKey + && "iaik.security.ec.common.ECPublicKey".equals(input.getClass().getName())) { + + //convert Key to BouncyCastle KeyImplemenation because there is an + //incompatibility with IAIK EC Keys and JWS signature-verfification implementation + PublicKey publicKey = KeyFactory.getInstance( + input.getAlgorithm(), provider).generatePublic( + new X509EncodedKeySpec(input.getEncoded())); + return publicKey; + + } else if (input instanceof ECPrivateKey + && "iaik.security.ec.common.ECPrivateKey".equals(input.getClass().getName())) { + //convert Key to BouncyCastle KeyImplemenation because there is an + //incompatibility with IAIK EC Keys and JWS signature-creation implementation + Key privateKey = KeyFactory.getInstance( + input.getAlgorithm(), provider).generatePrivate( + new PKCS8EncodedKeySpec(input.getEncoded())); + + return privateKey; + + } + + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + log.warn("Can NOT convert {} to {}. The verification may FAIL.", + input.getClass().getName(), PublicKey.class.getName(), e); + + } + + return input; + + } + + /** + * Select signature algorithm for a given credential. + * + * @param key {@link X509Credential} that will be used for + * key operations + * @param rsaSigAlgorithm RSA based algorithm that should be used in case + * of RSA credential + * @param ecSigAlgorithm EC based algorithm that should be used in case + * of RSA credential + * @param friendlyNameForLogging KeyStore friendlyName for logging purposes + * @return either the RSA based algorithm or the EC based algorithm + * @throws EaafKeyUsageException In case of an unsupported private-key type + */ + private static String getKeyOperationAlgorithmFromCredential(Key key, + String rsaSigAlgorithm, String ecSigAlgorithm, String friendlyNameForLogging) + throws EaafKeyUsageException { + if (key instanceof RSAPrivateKey) { + return rsaSigAlgorithm; + + } else if (key instanceof ECPrivateKey) { + return ecSigAlgorithm; + + } else { + log.warn("Could NOT select the cryptographic algorithm from Private-Key type"); + throw new EaafKeyUsageException(EaafKeyUsageException.ERROR_CODE_01, + friendlyNameForLogging, + "Can not select cryptographic algorithm"); + + } + + } + + private JoseUtils() { + + } + + @Getter + @AllArgsConstructor + public static class JwsResult { + final boolean valid; + final String payLoad; + final Headers fullJoseHeader; + final List<X509Certificate> x5cCerts; + + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index 43c44647..58e3e41c 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -14,15 +14,14 @@ import javax.annotation.Nonnull; import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jose4j.jca.ProviderContext; import org.jose4j.jwa.AlgorithmConstraints; import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; import org.jose4j.jwe.JsonWebEncryption; import org.jose4j.jws.AlgorithmIdentifiers; -import org.jose4j.jws.JsonWebSignature; -import org.jose4j.jwx.JsonWebStructure; +import org.jose4j.jwx.HeaderParameterNames; import org.jose4j.keys.X509Util; -import org.jose4j.keys.resolvers.X509VerificationKeyResolver; import org.jose4j.lang.JoseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,6 +36,7 @@ import com.fasterxml.jackson.databind.JsonNode; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; @@ -49,6 +49,7 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JoseUtils.JwsResult; @Service public class JsonSecurityUtils implements IJoseTools { @@ -125,40 +126,16 @@ public class JsonSecurityUtils implements IJoseTools { @Override public String createSignature(final String payLoad, boolean addFullCertChain) throws SlCommandoBuildException { try { - final JsonWebSignature jws = new JsonWebSignature(); - - // set payload - jws.setPayload(payLoad); - - // set basic header - jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND); - - // set signing information - jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); - final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates( - keyStore.getFirst(), getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE); - jws.setKey(signingCred.getFirst()); - - // set special provider if required - if (keyStore.getSecond() != null) { - log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName()); - final ProviderContext providerCtx = new ProviderContext(); - providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( - keyStore.getSecond().getName()); - jws.setProviderContext(providerCtx); - - } - - if (addFullCertChain) { - jws.setCertificateChainHeaderValue(signingCred.getSecond()); - - } - - jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]); - - return jws.getCompactSerialization(); + return JoseUtils.createSignature(keyStore, getSigningKeyAlias(), getSigningKeyPassword(), + payLoad, addFullCertChain, + Collections.singletonMap( + HeaderParameterNames.CONTENT_TYPE, + SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND), + getRsaSigningAlgorithm(), + getEccSigningAlgorithm(), + FRIENDLYNAME_KEYSTORE); - } catch (final JoseException | EaafKeyAccessException e) { + } catch (final JoseException | EaafException e) { log.warn("Can NOT sign SL2.0 command.", e); throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e); @@ -179,61 +156,12 @@ public class JsonSecurityUtils implements IJoseTools { public VerificationResult validateSignature(@Nonnull final String serializedContent, @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints) throws JoseException, IOException { - final JsonWebSignature jws = new JsonWebSignature(); - // set payload - jws.setCompactSerialization(serializedContent); - - // set security constrains - jws.setAlgorithmConstraints(constraints); - - // load signinc certs - Key selectedKey = null; - final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); - final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); - if (x5cCerts != null) { - log.debug("Found x509 certificate in JOSE header ... "); - log.trace("Sorting received X509 certificates ... "); - final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); - - if (trustedCerts.contains(sortedX5cCerts.get(0))) { - selectedKey = sortedX5cCerts.get(0).getPublicKey(); - - } else { - log.info("Can NOT find JOSE certificate in truststore."); - try { - log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); - - } catch (final CertificateEncodingException e) { - e.printStackTrace(); - } - - } - - } else if (StringUtils.isNotEmpty(x5t256)) { - log.debug("Found x5t256 fingerprint in JOSE header .... "); - final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver( - trustedCerts); - selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); - - } else { - throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); - - } - - if (selectedKey == null) { - throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); - - } - - // set verification key - jws.setKey(selectedKey); - - // load payLoad + final JwsResult result = JoseUtils.validateSignature(serializedContent, trustedCerts, constraints); return new VerificationResult( - mapper.getMapper().readTree(jws.getHeaders().getFullHeaderAsJsonString()), - mapper.getMapper().readTree(jws.getPayload()), - x5cCerts, jws.verifySignature()); + mapper.getMapper().readTree(result.getFullJoseHeader().getFullHeaderAsJsonString()), + mapper.getMapper().readTree(result.getPayLoad()), + result.getX5cCerts(), result.isValid()); } @@ -241,7 +169,7 @@ public class JsonSecurityUtils implements IJoseTools { @Nonnull public VerificationResult validateSignature(@Nonnull final String serializedContent) throws SL20Exception { try { - final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, + final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.PERMIT, SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); @@ -251,7 +179,7 @@ public class JsonSecurityUtils implements IJoseTools { if (!result.isValidSigned()) { log.info("JWS signature invalide. Stopping authentication process ..."); - log.debug("Received JWS msg: " + serializedContent); + log.debug("Received JWS msg: {}", serializedContent); throw new SL20SecurityException("JWS signature invalide."); } @@ -278,11 +206,11 @@ public class JsonSecurityUtils implements IJoseTools { // set security constrains receiverJwe.setAlgorithmConstraints( - new AlgorithmConstraints(ConstraintType.WHITELIST, + new AlgorithmConstraints(ConstraintType.PERMIT, SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()]))); receiverJwe.setContentEncryptionAlgorithmConstraints( - new AlgorithmConstraints(ConstraintType.WHITELIST, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION + new AlgorithmConstraints(ConstraintType.PERMIT, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()]))); // set payload @@ -292,6 +220,21 @@ public class JsonSecurityUtils implements IJoseTools { keyStore.getFirst(), getEncryptionKeyAlias(), getEncryptionKeyPassword(), true, FRIENDLYNAME_KEYSTORE); + // set special provider if required + if (keyStore.getSecond() != null) { + log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName()); + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setGeneralProvider(keyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + receiverJwe.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + receiverJwe.setProviderContext(providerCtx); + + } + // validate key from header against key from config final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); @@ -318,7 +261,7 @@ public class JsonSecurityUtils implements IJoseTools { final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]); if (!certFingerPrint.equals(x5t256)) { log.info("X5t256 from JOSE header does NOT match encryption certificate"); - log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); + log.debug("X5t256 from JOSE header: {} Encrytption cert: {}", x5t256, certFingerPrint); throw new SL20Exception("sl20.05", new Object[] { "X5t256 from JOSE header does NOT match encryption certificate" }); @@ -332,7 +275,7 @@ public class JsonSecurityUtils implements IJoseTools { } // set key - receiverJwe.setKey(encryptionCred.getFirst()); + receiverJwe.setKey(JoseUtils.convertToBcKeyIfRequired(encryptionCred.getFirst())); // decrypt payload return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); @@ -377,8 +320,7 @@ public class JsonSecurityUtils implements IJoseTools { config.setFriendlyName(FRIENDLYNAME_KEYSTORE); config.setKeyStoreType(authConfig.getBasicConfiguration( - authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE), - KeyStoreType.JKS.getKeyStoreType())); + Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType())); config.setKeyStoreName( authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME)); config.setSoftKeyStoreFilePath( @@ -398,8 +340,7 @@ public class JsonSecurityUtils implements IJoseTools { config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE); config.setKeyStoreType(authConfig.getBasicConfiguration( - authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE), - KeyStoreType.JKS.getKeyStoreType())); + Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType())); config.setKeyStoreName( authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME)); config.setSoftKeyStoreFilePath( @@ -452,4 +393,26 @@ public class JsonSecurityUtils implements IJoseTools { return null; } + private String getRsaSigningAlgorithm() { + String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_SIG_ALG_RSA, + AlgorithmIdentifiers.RSA_PSS_USING_SHA256); + if (value != null) { + value = value.trim(); + } + + return value; + + } + + private String getEccSigningAlgorithm() { + String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_SIG_ALG_ECC, + AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256); + if (value != null) { + value = value.trim(); + } + + return value; + + } + } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java index edf70cc8..c95bcc45 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java @@ -13,14 +13,15 @@ import org.jose4j.jws.AlgorithmIdentifiers; public class SL20Constants { public static final int CURRENT_SL20_VERSION = 10; - + // http binding parameters public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; public static final String PARAM_SL20_REQ_AUTH_METHOD_PARAM = "authtype"; public static final String PARAM_SL20_REQ_AUTH_VDA_SESSIONID = "session"; - + public static final String PARAM_SL20_REQ_AUTH_VDA_LOCALE = "locale"; + public enum VdaAuthMethod { ANY("any"), MOBILEPHONE("handy"), CARD("card"), SMARTPHONE("smartphone"); @@ -51,7 +52,7 @@ public class SL20Constants { } catch (IllegalArgumentException | NullPointerException e) { return VdaAuthMethod.ANY; - + } } @@ -59,9 +60,9 @@ public class SL20Constants { public String toString() { return getAuthMethod(); - } + } } - + public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl"; public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; @@ -97,7 +98,11 @@ public class SL20Constants { KeyManagementAlgorithmIdentifiers.RSA_OAEP_256; public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Collections - .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_KEY_RSAOAEP, JSON_ALGORITHM_ENC_KEY_RSAOAEP256)); + .unmodifiableList(Arrays.asList( + JSON_ALGORITHM_ENC_KEY_RSAOAEP, + JSON_ALGORITHM_ENC_KEY_RSAOAEP256, + KeyManagementAlgorithmIdentifiers.ECDH_ES_A128KW, + KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW)); public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256; @@ -177,7 +182,7 @@ public class SL20Constants { // error command public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode"; public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage"; - public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID + public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID = "handySignaturSession"; // qualified eID command diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java index 1d7c9646..2b6ddb96 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java @@ -3,23 +3,133 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils; import java.io.IOException; import java.io.StringWriter; import java.net.URISyntaxException; +import java.text.MessageFormat; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.ParseException; +import org.apache.http.StatusLine; +import org.apache.http.client.ResponseHandler; import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.util.EntityUtils; import org.jose4j.base64url.Base64Url; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import com.fasterxml.jackson.databind.JsonNode; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import lombok.Data; +import lombok.Getter; + public class SL20HttpBindingUtils { private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); + private static JsonMapper mapper = new JsonMapper(); + + @Data + @Getter + public static class Sl20ResponseHolder { + private final JsonNode responseBody; + private final StatusLine responseStatus; + private SlCommandoParserException error; + + } + + /** + * Security-Layer 2.0 specific response-handler for Apache HTTP client. + * + * @return {@link Sl20ResponseHolder} + */ + public static ResponseHandler<Sl20ResponseHolder> sl20ResponseHandler() { + return response -> { + try { + final int httpStatusCode = response.getStatusLine().getStatusCode(); + if (httpStatusCode == HttpStatus.OK.value()) { + if (response.getEntity().getContentType() == null) { + throw new SlCommandoParserException("SL20 response contains NO ContentType"); + + } + + final ContentType contentType = ContentType.getOrDefault(response.getEntity()); + if (!ContentType.APPLICATION_JSON.getMimeType().equals(contentType.getMimeType())) { + log.error("SL20 response with statuscode: {} has wrong http ContentType: {}", + response.getStatusLine(), contentType); + throw new SlCommandoParserException( + "SL20 response with a wrong http ContentType: " + contentType); + + } + + //parse OK response from body + return new Sl20ResponseHolder(parseSL20ResultFromResponse(response.getEntity()), + response.getStatusLine()); + + } else if (httpStatusCode == HttpStatus.SEE_OTHER.value() + || httpStatusCode == HttpStatus.TEMPORARY_REDIRECT.value()) { + final Header[] locationHeader = response.getHeaders("Location"); + if (locationHeader == null) { + throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); + + } + + final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); + return new Sl20ResponseHolder(mapper.getMapper().readTree(Base64Url.decode(sl20RespString)), + response.getStatusLine()); + + } else if ( + httpStatusCode == HttpStatus.INTERNAL_SERVER_ERROR.value() + || httpStatusCode == HttpStatus.UNAUTHORIZED.value() + || httpStatusCode == HttpStatus.BAD_REQUEST.value()) { + log.info("SL20 response with http-code: {}. Search for error message", httpStatusCode); + + String bodyMsg = "_EMPTY_"; + try { + //extract JSON body from defined http error-codes + bodyMsg = EntityUtils.toString(response.getEntity()); + log.info("SL20 response with http-code: {0} and errorMsg: {1}", httpStatusCode, bodyMsg); + Sl20ResponseHolder holder = new Sl20ResponseHolder( + mapper.getMapper().readTree(bodyMsg), response.getStatusLine()); + return holder; + + } catch (final IOException | ParseException e) { + log.warn("SL20 response contains no )valid JSON", e); + throw new SlCommandoParserException(MessageFormat.format( + "SL20 response with http-code: {0} with body: {1} and generic response-processing error: {2}", + httpStatusCode, bodyMsg, e.getMessage())); + + } + + } else { + //all other HTTP StatusCodes + throw new SlCommandoParserException(MessageFormat.format( + "SL20 response with http-code: {0} and errorMsg: {1}", + httpStatusCode, EntityUtils.toString(response.getEntity()))); + + } + + } catch (SlCommandoParserException e) { + Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); + holder.setError(e); + return holder; + + } catch (final Exception e) { + Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); + holder.setError( + new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e)); + return holder; + + } + }; + } + /** * Write SL2.0 response into http-response object * @@ -59,6 +169,34 @@ public class SL20HttpBindingUtils { httpResp.setHeader("Location", clientRedirectUri.build().toString()); } + } + + private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { + if (resp != null && resp.getContent() != null) { + final String rawSL20Resp = EntityUtils.toString(resp); + try { + final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); + if (sl20Resp != null) { + return sl20Resp; + + } else { + log.error("SL2.0 can NOT parse to a JSON object from msg: {}", rawSL20Resp); + throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); + } + + } catch (SlCommandoParserException e) { + throw e; + + } catch (Exception e) { + log.error("SL2.0 can NOT parse to a JSON object from msg: {}", rawSL20Resp); + throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); + + } + + } else { + throw new SlCommandoParserException("Can NOT find any content in http response"); + + } } } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java index 40ea0430..bed25c0c 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java @@ -8,12 +8,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.util.EntityUtils; -import org.jose4j.base64url.Base64Url; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -299,84 +293,6 @@ public class SL20JsonExtractorUtils { } - /** - * Extract generic transport container from httpResponse. - * - * @param httpResp Http response object - * @return JSON with SL2.0 response - * @throws SlCommandoParserException In case of an error - */ - public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) throws SlCommandoParserException { - try { - JsonNode sl20Resp = null; - if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { - final Header[] locationHeader = httpResp.getHeaders("Location"); - if (locationHeader == null) { - throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); - } - - final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); - sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); - - } else if (httpResp.getStatusLine().getStatusCode() == 200) { - if (httpResp.getEntity().getContentType() == null) { - throw new SlCommandoParserException("SL20 response contains NO ContentType"); - } - - if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { - throw new SlCommandoParserException( - "SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); - } - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - } else if (httpResp.getStatusLine().getStatusCode() == 500 || httpResp.getStatusLine().getStatusCode() == 401 - || httpResp.getStatusLine().getStatusCode() == 400) { - log.info( - "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + ". Search for error message"); - - try { - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - } catch (final Exception e) { - log.warn("SL20 response contains no valid JSON", e); - throw new SlCommandoParserException("SL20 response with http-code: " - + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e); - - } - - } else { - throw new SlCommandoParserException( - "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); - } - - log.info("Find JSON object in http response"); - return sl20Resp; - - } catch (final Exception e) { - throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); - - } - } - - private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { - if (resp != null && resp.getContent() != null) { - final String rawSL20Resp = EntityUtils.toString(resp); - final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); - - // TODO: check sl20Resp type like && sl20Resp.isJsonObject() - if (sl20Resp != null) { - return sl20Resp; - - } else { - throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); - } - - } else { - throw new SlCommandoParserException("Can NOT find content in http response"); - } - - } - private static JsonNode getAndCheck(final JsonNode input, final String keyID, final boolean isRequired) throws SlCommandoParserException { final JsonNode internal = input.get(keyID); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java index 4bb91634..c3826087 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java @@ -11,17 +11,17 @@ import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; - import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import com.fasterxml.jackson.databind.node.ObjectNode; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -134,7 +134,7 @@ public class SL20ResponseUtils { } else { log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); - log.debug("Client request containts is no native client ... "); + log.debug("Client request is no a native client. SL2.0 anwser will be a http redirect ... "); final URIBuilder clientRedirectUri = new URIBuilder(fullRedirectUrl); response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java new file mode 100644 index 00000000..ae4284d5 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java @@ -0,0 +1,394 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.Security; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; + +import org.apache.commons.lang3.RandomStringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.jose4j.base64url.Base64Url; +import org.jose4j.jca.ProviderContext; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; +import org.jose4j.jwe.JsonWebEncryption; +import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; +import org.jose4j.lang.JoseException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.databind.JsonNode; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import iaik.security.ec.provider.ECCelerate; +import iaik.security.provider.IAIK; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_sl20_hsm.beans.xml") +public abstract class AbstractJsonSecurityUtilsTest { + + @Autowired protected DummyAuthConfigMap config; + @Autowired protected IJoseTools joseTools; + @Autowired protected EaafKeyStoreFactory keyStoreFactory; + + /** + *jUnit test class initializer. + */ + @BeforeClass + public static void classInitializer() { + IAIK.addAsProvider(); + ECCelerate.addAsProvider(); + + Security.addProvider(new BouncyCastleProvider()); + } + + /** + * jUnit test class cleaner. + */ + @AfterClass + public static final void classFinisher() { + Security.removeProvider(IAIK.getInstance().getName()); + Security.removeProvider(ECCelerate.getInstance().getName()); + + } + + protected abstract void setRsaSigningKey(); + + protected abstract void setEcSigningKey(); + + protected abstract void setRsaEncryptionKey(); + + protected abstract void setEcEncryptionKey(); + + protected abstract Pair<KeyStore, Provider> getEncryptionKeyStore() throws EaafException; + + protected abstract String getRsaKeyAlias(); + + protected abstract String getRsaKeyPassword(); + + protected abstract String getEcKeyAlias(); + + protected abstract String getEcKeyPassword(); + + + @Test + public void fullEncryptDecrypt() throws JoseException, EaafException { + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(JoseUtils.convertToBcKeyIfRequired(joseTools.getEncryptionCertificate().getPublicKey())); + jwe.setX509CertSha256ThumbprintHeaderValue(joseTools.getEncryptionCertificate()); + jwe.setPayload(payLoad); + + // set special provider if required + final Pair<KeyStore, Provider> rsaEncKeyStore = getEncryptionKeyStore(); + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + rsaEncKeyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jwe.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jwe.setProviderContext(providerCtx); + + } + + final String encData = jwe.getCompactSerialization(); + Assert.assertNotNull("JWE Encryption", encData); + + + final JsonNode decData = joseTools.decryptPayload(encData); + Assert.assertNotNull("JWE Decryption", decData); + + } + + @Test + public void encryptionRsa() throws JoseException, EaafException { + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + final Pair<KeyStore, Provider> rsaEncKeyStore = getEncryptionKeyStore(); + final Pair<Key, X509Certificate[]> key = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + rsaEncKeyStore.getFirst(), getRsaKeyAlias(), getRsaKeyPassword().toCharArray(), + true, "jUnit RSA JWE"); + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(key.getSecond()[0].getPublicKey()); + jwe.setPayload(payLoad); + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + rsaEncKeyStore.getSecond().getName()); + jwe.setProviderContext(providerCtx); + + } + + final String encData = jwe.getCompactSerialization(); + Assert.assertNotNull("JWE", encData); + + + //decrypt it again + final JsonWebEncryption jweDecrypt = new JsonWebEncryption(); + jweDecrypt.setCompactSerialization(encData); + jweDecrypt.setKey(JoseUtils.convertToBcKeyIfRequired(key.getFirst())); + + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setGeneralProvider(rsaEncKeyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jweDecrypt.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jweDecrypt.setProviderContext(providerCtx); + + } + + String decPayload = jweDecrypt.getPayload(); + Assert.assertNotNull("decrypted Payload", decPayload); + Assert.assertEquals("Decrypted message not match", payLoad, decPayload); + + } + + @Test + public void encryptionEc() throws JoseException, EaafException { + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + final Pair<KeyStore, Provider> rsaEncKeyStore = getEncryptionKeyStore(); + final Pair<Key, X509Certificate[]> key = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + rsaEncKeyStore.getFirst(), getEcKeyAlias(), getEcKeyPassword().toCharArray(), + true, "jUnit RSA JWE"); + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(JoseUtils.convertToBcKeyIfRequired(key.getSecond()[0].getPublicKey())); + jwe.setPayload(payLoad); + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setGeneralProvider(rsaEncKeyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jwe.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jwe.setProviderContext(providerCtx); + + } + + final String encData = jwe.getCompactSerialization(); + + Assert.assertNotNull("JWE", encData); + + + //decrypt it again + final JsonWebEncryption jweDecrypt = new JsonWebEncryption(); + jweDecrypt.setCompactSerialization(encData); + jweDecrypt.setKey(JoseUtils.convertToBcKeyIfRequired(key.getFirst())); + + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setGeneralProvider(rsaEncKeyStore.getSecond().getName()); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jweDecrypt.setProviderContext(providerCtx); + + } else { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); + jweDecrypt.setProviderContext(providerCtx); + + } + + String decPayload = jweDecrypt.getPayload(); + Assert.assertNotNull("decrypted Payload", decPayload); + Assert.assertEquals("Decrypted message not match", payLoad, decPayload); + + } + + + @Test + public void noTrustedCert() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + try { + joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigOnlyEc()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (final JoseException e) { + Assert.assertEquals("Wrong errorCode", + "Can NOT select verification key for JWS. Signature verification FAILED", + e.getMessage()); + + } + } + + @Test + public void invalidSignature() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + final String invalidJws = jws.substring(0, jws.indexOf(".")) + + "." + + Base64Url.encodeUtf8ByteRepresentation("{\"aac\":\"" + RandomStringUtils.randomAlphabetic(25) + "\"}") + + "." + + jws.substring(jws.lastIndexOf(".") + 1); + + + final VerificationResult result = joseTools.validateSignature( + invalidJws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + + Assert.assertFalse("wrong sig. verification state", result.isValidSigned()); + + } + + @Test + public void validSigningRsa() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + final VerificationResult verify = joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.assertTrue("wrong verify state", verify.isValidSigned()); + Assert.assertNotNull("JWS Header", verify.getJoseHeader()); + Assert.assertNotNull("JWS Payload", verify.getPayload()); + Assert.assertNotNull("CertChain", verify.getCertChain()); + + + } + + @Test + public void validSigningRsaPss() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + + // + config.putConfigValue("modules.sl20.security.sigalg.rsa", "PS256"); + + setRsaSigningKey(); + setRsaEncryptionKey(); + + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + final VerificationResult verify = joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.assertTrue("wrong verify state", verify.isValidSigned()); + Assert.assertNotNull("JWS Header", verify.getJoseHeader()); + Assert.assertNotNull("JWS Payload", verify.getPayload()); + Assert.assertNotNull("CertChain", verify.getCertChain()); + + + } + + @Test + public void validSigningEc() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setEcSigningKey(); + setEcEncryptionKey(); + + final String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + final VerificationResult verify = joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.assertTrue("wrong verify state", verify.isValidSigned()); + Assert.assertNotNull("JWS Header", verify.getJoseHeader()); + Assert.assertNotNull("JWS Payload", verify.getPayload()); + Assert.assertNotNull("CertChain", verify.getCertChain()); + + } + + protected KeyStoreConfiguration getSigTrustStoreConfigValid() { + final KeyStoreConfiguration trustConfig = new KeyStoreConfiguration(); + trustConfig.setFriendlyName("jUnit TrustStore"); + trustConfig.setKeyStoreType(KeyStoreType.JKS); + trustConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit.jks"); + trustConfig.setSoftKeyStorePassword("password"); + + return trustConfig; + + } + + protected KeyStoreConfiguration getSigTrustStoreConfigOnlyEc() { + final KeyStoreConfiguration trustConfig = new KeyStoreConfiguration(); + trustConfig.setFriendlyName("jUnit TrustStore"); + trustConfig.setKeyStoreType(KeyStoreType.JKS); + trustConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit_no_rsa.jks"); + trustConfig.setSoftKeyStorePassword("password"); + + return trustConfig; + + } + + private AlgorithmConstraints getDefaultAlgorithmConstrains() { + return new AlgorithmConstraints(ConstraintType.WHITELIST, + SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING + .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); + } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java new file mode 100644 index 00000000..b5a7639e --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java @@ -0,0 +1,83 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.lang.JoseException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JoseUtils.JwsResult; +import iaik.security.ec.provider.ECCelerate; +import iaik.security.provider.IAIK; + +@RunWith(BlockJUnit4ClassRunner.class) +public class JoseUtilsTest { + + private static final List<String> BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList( + Arrays.asList( + AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, + AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512, + AlgorithmIdentifiers.RSA_PSS_USING_SHA256, + AlgorithmIdentifiers.RSA_PSS_USING_SHA512)); + + /** + *jUnit test class initializer. + */ + @BeforeClass + public static final void classInitializer() { + IAIK.addAsProvider(); + ECCelerate.addAsProvider(); + + } + + /** + * jUnit test class cleaner. + */ + @AfterClass + public static final void classFinisher() { + Security.removeProvider(IAIK.getInstance().getName()); + Security.removeProvider(ECCelerate.getInstance().getName()); + + } + + @Test + public void testBindingAuthBlock() throws JoseException, IOException, CertificateException, NoSuchProviderException { + + final String serializedContent = IOUtils.toString(JoseUtils.class.getResourceAsStream( + "/data/bindingAuth1.jws"), "UTF-8"); + + final iaik.x509.X509Certificate trustedCert = new iaik.x509.X509Certificate(JoseUtils.class + .getResourceAsStream("/data/bindingAuth1.crt")); + + final List<X509Certificate> trustedCerts = Arrays.asList(trustedCert); + final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT, + BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING + .toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()])); + + final JwsResult result = JoseUtils.validateSignature(serializedContent, trustedCerts, constraints); + + Assert.assertNotNull("JWS verify result", result); + Assert.assertTrue("JWS not valid", result.isValid()); + Assert.assertNotNull("JWS payload", result.getPayLoad()); + Assert.assertNotNull("JWS Headers", result.getFullJoseHeader()); + Assert.assertNotNull("JWS Signercerts", result.getX5cCerts()); + Assert.assertEquals("Signercerts size", 1, result.getX5cCerts().size()); + Assert.assertArrayEquals("Signercerts", trustedCert.getEncoded(), result.getX5cCerts().get(0).getEncoded()); + + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java new file mode 100644 index 00000000..b01330d2 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java @@ -0,0 +1,86 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.security.KeyStore; +import java.security.Provider; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_sl20_hsm.beans.xml") +public class JsonSecurityUtilsHsmKeyTest extends AbstractJsonSecurityUtilsTest { + + /** + * Initialize jUnit test. + */ + @Before + public void initialize() { + config.putConfigValue("modules.sl20.security.sigalg.rsa", "RS256"); + config.putConfigValue("modules.sl20.security.sigalg.ecc", "ES256"); + + } + + @Override + protected void setRsaSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "rsa-key-1"); + + } + + @Override + protected void setEcSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "ec-key-1"); + + } + + @Override + protected void setRsaEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "rsa-key-1"); + + } + + @Override + protected void setEcEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "ec-key-1"); + + } + + @Override + protected Pair<KeyStore, Provider> getEncryptionKeyStore() throws EaafException { + final KeyStoreConfiguration keyConfig = new KeyStoreConfiguration(); + keyConfig.setFriendlyName("Junit Enc Key Rsa"); + keyConfig.setKeyStoreType(KeyStoreType.HSMFACADE); + keyConfig.setKeyStoreName("eid-junit"); + + return keyStoreFactory.buildNewKeyStore(keyConfig); + } + + @Override + protected String getRsaKeyAlias() { + return "rsa-key-1"; + } + + @Override + protected String getRsaKeyPassword() { + return StringUtils.EMPTY; + } + + @Override + protected String getEcKeyAlias() { + return "ec-key-1"; + } + + @Override + protected String getEcKeyPassword() { + return StringUtils.EMPTY; + } + + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java new file mode 100644 index 00000000..d78bdbd7 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java @@ -0,0 +1,110 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.security.KeyStore; +import java.security.Provider; + +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 org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_sl20.beans.xml") +public class JsonSecurityUtilsSoftwareKeyTest extends AbstractJsonSecurityUtilsTest { + + @Test + public void invalidSignatureRandomString() { + try { + joseTools.validateSignature(RandomStringUtils.randomAlphabetic(10)); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (SL20Exception e) { + Assert.assertEquals("Wrong errorCode", "sl20.05", e.getErrorId()); + } + + } + + @Test + public void invalidSignatureRandomBase64UrlEncoded() { + String testValue = Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()) + + "." + + Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()) + + "." + + Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()); + + try { + joseTools.validateSignature(testValue); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (SL20Exception e) { + Assert.assertEquals("Wrong errorCode", "sl20.05", e.getErrorId()); + } + + } + + @Override + protected void setRsaSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "meta"); + + } + + @Override + protected void setEcSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "sig"); + + } + + @Override + protected void setRsaEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "meta"); + + } + + @Override + protected void setEcEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "sig"); + + } + + @Override + protected Pair<KeyStore, Provider> getEncryptionKeyStore() throws EaafException { + KeyStoreConfiguration keyConfig = new KeyStoreConfiguration(); + keyConfig.setFriendlyName("Junit Enc Key Rsa"); + keyConfig.setKeyStoreType(KeyStoreType.JKS); + keyConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit.jks"); + keyConfig.setSoftKeyStorePassword("password"); + + return keyStoreFactory.buildNewKeyStore(keyConfig); + } + + @Override + protected String getRsaKeyAlias() { + return "meta"; + } + + @Override + protected String getRsaKeyPassword() { + return "password"; + } + + @Override + protected String getEcKeyAlias() { + return "sig"; + } + + @Override + protected String getEcKeyPassword() { + return "password"; + } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt new file mode 100644 index 00000000..11c17e71 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBXzCCAQWgAwIBAgIIPuBGtvo16nUwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwPRHVtbXlQa2lTZXJ2aWNlMB4XDTIwMTAwNzEyMTAyMVoXDTIxMTAwNzEyMTAyMVowUTEpMCcGA1UEAwwgNWMzM2Q3MjdlY2YzZTAyYTE2NmYzYWI2NWZiYTEzOGExFDASBgNVBAoMC0VJRC1ERVYtUEtJMQ4wDAYDVQQLDAVULUVudjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABACA6RBPYIX3i0+TqYq2gb3XAD0B1/tee3/lP8sPc+tt6GFDN0Vsos77VojhRQnGRndmoWi9OW7KS5uQe+5++W8wCgYIKoZIzj0EAwIDSAAwRQIhAO7NlM4YfnapZ9Vam/LF/5ASPGbN4SK0fK4bhGHQw8yIAiB77JHkZIaDtgCcv7CSPf/mvldSf5ViPelhuZBPSLRUsQ== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws new file mode 100644 index 00000000..6ba84d97 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws @@ -0,0 +1 @@ +eyJ4NWMiOlsiTUlJQlh6Q0NBUVdnQXdJQkFnSUlQdUJHdHZvMTZuVXdDZ1lJS29aSXpqMEVBd0l3R2pFWU1CWUdBMVVFQXd3UFJIVnRiWGxRYTJsVFpYSjJhV05sTUI0WERUSXdNVEF3TnpFeU1UQXlNVm9YRFRJeE1UQXdOekV5TVRBeU1Wb3dVVEVwTUNjR0ExVUVBd3dnTldNek0yUTNNamRsWTJZelpUQXlZVEUyTm1ZellXSTJOV1ppWVRFek9HRXhGREFTQmdOVkJBb01DMFZKUkMxRVJWWXRVRXRKTVE0d0RBWURWUVFMREFWVUxVVnVkakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQUNBNlJCUFlJWDNpMCtUcVlxMmdiM1hBRDBCMVwvdGVlM1wvbFA4c1BjK3R0NkdGRE4wVnNvczc3Vm9qaFJRbkdSbmRtb1dpOU9XN0tTNXVRZSs1KytXOHdDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTzdObE00WWZuYXBaOVZhbVwvTEZcLzVBU1BHYk40U0swZks0YmhHSFF3OHlJQWlCNzdKSGtaSWFEdGdDY3Y3Q1NQZlwvbXZsZFNmNVZpUGVsaHVaQlBTTFJVc1E9PSJdLCJ0eXAiOiJiaW5kaW5nQXV0aCIsImFsZyI6IkVTMjU2In0.MzIxZmVmYTQtODVkOC00YmE5LWE0MmUtYWY4MzM3YTEyNTA1.diiXXegwv3Gu6ezJRxf7F5BnRxNhTnBXJ0D5RX4OqDxs2QvfzSPA4mOkUed18_56aILMBLVL-XIMszNILfp7OA
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config1.properties b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config1.properties new file mode 100644 index 00000000..f58e3da9 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config1.properties @@ -0,0 +1,19 @@ +security.hsmfacade.host=eid.a-sit.at +security.hsmfacade.port=9050 +security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt +security.hsmfacade.username=authhandler-junit +security.hsmfacade.password=supersecret123 + +modules.sl20.security.keystore.type=jks +modules.sl20.security.keystore.path=src/test/resources/data/junit.jks +modules.sl20.security.keystore.password=password +modules.sl20.security.keystore.name= +modules.sl20.security.sign.alias=sig +modules.sl20.security.sign.password=password +modules.sl20.security.encryption.alias=meta +modules.sl20.security.encryption.password=password + +modules.sl20.security.truststore.type=jks +modules.sl20.security.truststore.path=src/test/resources/data/junit.jks +modules.sl20.security.truststore.password=password +modules.sl20.security.truststore.name=
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config2.properties b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config2.properties new file mode 100644 index 00000000..ff99dcef --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/config2.properties @@ -0,0 +1,19 @@ +security.hsmfacade.host=eid.a-sit.at +security.hsmfacade.port=9050 +security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt +security.hsmfacade.username=authhandler-junit +security.hsmfacade.password=supersecret123 + +modules.sl20.security.keystore.type=hsmfacade +modules.sl20.security.keystore.path= +modules.sl20.security.keystore.password= +modules.sl20.security.keystore.name=eid-junit +modules.sl20.security.sign.alias=rsa-key-1 +modules.sl20.security.sign.password= +modules.sl20.security.encryption.alias=ec-key-1 +modules.sl20.security.encryption.password= + +modules.sl20.security.truststore.type=hsmfacade +modules.sl20.security.truststore.path=src/test/resources/data/junit.jks +modules.sl20.security.truststore.password= +modules.sl20.security.truststore.name=eid-junit
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_ec.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_ec.crt new file mode 100644 index 00000000..ad780a21 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_ec.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBQTCB56ADAgECAghqWvzGZbotTjAKBggqhkjOPQQDAjASMRAwDgYDVQQDDAdFQy1Sb290MB4XDTIwMDYxODA3MzYwOVoXDTI1MDYxODA3MzYwOVowOzEaMBgGA1UEAwwRaW50LWVjLWtleS0xLTAwMDExETAPBgNVBAoMCHNvZnR3YXJlMQowCAYDVQQFEwExMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMYva5n1ISLX4bZdG9ecGVNVId7OEY4Yjeu+4kk+nbppxNMj6JX5tO2iCCpgHlKC5WWTSJyxSQh3CoLzc8XLUmjAKBggqhkjOPQQDAgNJADBGAiEAiegmUzDThtinnuUwsHXwdr4Y/XUednOyIy7RBeClvyYCIQC/v5NZzg+H6FUrQ2nds2hlB6sD7z5cZPJcqm8+S0wYCw== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_facade_trust_root.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_facade_trust_root.crt new file mode 100644 index 00000000..204ddccf --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_facade_trust_root.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIByzCCAXGgAwIBAgIEYC5cIjAKBggqhkjOPQQDAjA7MRMwEQYDVQQKDApBLVNJ +VCBQbHVzMRIwEAYDVQQLDAlIc21GYWNhZGUxEDAOBgNVBAMMB0VDIFJvb3QwHhcN +MjEwMjE4MTIyMjU4WhcNMzEwMjE4MTIyMjU4WjA7MRMwEQYDVQQKDApBLVNJVCBQ +bHVzMRIwEAYDVQQLDAlIc21GYWNhZGUxEDAOBgNVBAMMB0VDIFJvb3QwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAARK1UAE+T3xYsoI0VkRcP20jPwTd2MePMkXRsSR +lpqPMQ6dPMlxPmAzWK33DWPFAFMY8+ecF0J8t2D+5RiJSSB+o2MwYTAPBgNVHRMB +Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT1v6FCAwJIM8kv +JD7gVjdGXqhcYjAdBgNVHQ4EFgQU9b+hQgMCSDPJLyQ+4FY3Rl6oXGIwCgYIKoZI +zj0EAwIDSAAwRQIhAI+5lHyNCQfyj8c0pdBDVWY3fkCOj9ZTJ/hqgW+6TIQBAiBS +jn7uIj7tGm+f0RgXMbhcgtQhYgVwf0x8OnRwmDOwaw== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_rsa.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_rsa.crt new file mode 100644 index 00000000..aa83c8d9 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/hsm_rsa.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIICDTCCAbOgAwIBAgIIVLxIFI8kRpkwCgYIKoZIzj0EAwIwEjEQMA4GA1UEAwwHRUMtUm9vdDAeFw0yMDA2MTgwNzM2MTBaFw0yNTA2MTgwNzM2MTBaMDwxGzAZBgNVBAMMEmludC1yc2Eta2V5LTEtMDAwMTERMA8GA1UECgwIc29mdHdhcmUxCjAIBgNVBAUTATEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrM1ocQqtch95Dm21JHi0V35nlWZibsjLqR+g8ERdD1qFgun/X0I/Rbft+KxB8QsDX7UmIjXGdavNcEjY/XcbiJxUcpv7vn/2+x3JxZO6Iye/ut001okICt3OGIqP93ZEnIaTTNhDsK7OnvD/eUjlmuHiTaFq1dZLKYDQlz9jl/9F4axfrz1V7oo60iqFIW+7tlUeh8VGDUPjQpHghzjHXTJv/OIAt752K31Tn8KR3kvkn6WTPo8eOWVaPQ480Dik0e2afTPPJNZJ7BW111IwqBAOKp586yVsQ4XVEF8H64Cq+s+b4/HBboo9TDJKTJvo2yQmcTsahbH+Rlm20ifUTAgMBAAEwCgYIKoZIzj0EAwIDSAAwRQIhANKN/N2Atb5fbeHSB2Myv/JcNf9JonxFe92AOu4f62NNAiBjOEeg4OyJZKPiDl6aqYVtz1Qroo6xzUC9UVA4qNe4LA== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit.jks Binary files differnew file mode 100644 index 00000000..a18df332 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit.jks diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit_no_rsa.jks b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit_no_rsa.jks Binary files differnew file mode 100644 index 00000000..370cf19e --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/junit_no_rsa.jks diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_ec.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_ec.crt new file mode 100644 index 00000000..5311f3f1 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_ec.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcwHhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwCLZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqGSM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIhANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_rsa.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_rsa.crt new file mode 100644 index 00000000..c70f5031 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/software_rsa.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJBVDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFkYXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRhZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYAO5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6Hrp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONbf+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3lPIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NXzh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWSYI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZipurO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/test.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/test.crt new file mode 100644 index 00000000..76c18361 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/test.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEY4Qn3zANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCQVQxSDBGBgNVBAoMP0EtVHJ1c3QgR2VzLiBmLiBTaWNoZXJoZWl0c3N5c3RlbWUgaW0gZWxla3RyLiBEYXRlbnZlcmtlaHIgR21iSDEmMCQGA1UECwwdYS1zaWduLVRlc3QtUHJlbWl1bS1Nb2JpbGUtMDUxJjAkBgNVBAMMHWEtc2lnbi1UZXN0LVByZW1pdW0tTW9iaWxlLTA1MB4XDTE5MTIxMzEzNDg0N1oXDTI0MTIxMzEzNDg0N1owYDELMAkGA1UEBhMCQVQxFzAVBgNVBAMMDk1heCBNdXN0ZXJtYW5uMRMwEQYDVQQEDApNdXN0ZXJtYW5uMQwwCgYDVQQqDANNYXgxFTATBgNVBAUTDDgxNjkyMjY1ODM0ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAUAVvbow4O/DMA5ZZoPHQXe0rtf86lvH8GLM/Crz1vvRYyQ5D4ESYRFy+s3zHdLqhE4l8I95i9jz2qTvof46mqjggGfMIIBmzCBggYIKwYBBQUHAQEEdjB0MEkGCCsGAQUFBzAChj1odHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLXRlc3QtcHJlbWl1bS1tb2JpbGUtMDUuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRydXN0LmF0L29jc3AwEwYDVR0jBAwwCoAITuhoD/7N29AwEQYDVR0OBAoECEyqhgBwLul2MA4GA1UdDwEB/wQEAwIGwDAJBgNVHRMEAjAAMIGGBgNVHSAEfzB9MHsGBiooABEBBDBxMDgGCCsGAQUFBwICMCwaKkRpZXNlcyBaZXJ0aWZpa2F0IGRpZW50IG51ciB6dSBUZXN0endlY2tlbjA1BggrBgEFBQcCARYpaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVRFU1QwSAYDVR0fBEEwPzA9oDugOYY3aHR0cDovL2NybC5hLXRydXN0LmF0L2NybC9hLXNpZ24tdGVzdC1wcmVtaXVtLW1vYmlsZS0wNTANBgkqhkiG9w0BAQsFAAOCAQEATD4ZnrEV+xeT7PFI/idqHdElLZ1BVUO9G9qfQQn4oKNCWWHxMo/ZXSlvsOtTjFezCQFkcFO1eJtXNHCyqfr69jorzhZcicscNRMrDlJoB/sJr0l/Ekjlt/dgRaTuZ7NzWE/oTefI3M3xkkLd0ydAMrhrZx+9f82VE3k63I1fmT90kQ8PfDzAMMRmlwbZDA+2TB8iF7SQkOOL6H1j2L9qrhjlG2ekU4cyx6KMkRjLLbr1JVgS07qOzUkeQPR2KTJcWWR+/NQZWDKdOz97eVOulxeI+Y3y96arraGM7lIbV9ZrpkbUn/IxQ9TQTE5X02EipgnZdR7bZrwJ7hJ27vwnfQ== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20.beans.xml b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20.beans.xml new file mode 100644 index 00000000..e4002a8f --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20.beans.xml @@ -0,0 +1,24 @@ +<?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" + default-lazy-init="true"> + + <bean id="dummyAuthConfigMap" + class="at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap"> + <constructor-arg value="/data/config1.properties" /> + </bean> + + <bean id="jwsJweUtils" + class="at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonSecurityUtils"/> + + <import resource="classpath:/spring/eaaf_utils.beans.xml"/> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20_hsm.beans.xml b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20_hsm.beans.xml new file mode 100644 index 00000000..a9f5dc80 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/spring/test_eaaf_sl20_hsm.beans.xml @@ -0,0 +1,24 @@ +<?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" + default-lazy-init="true"> + + <bean id="dummyAuthConfigMap" + class="at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap"> + <constructor-arg value="/data/config2.properties" /> + </bean> + + <bean id="jwsJweUtils" + class="at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonSecurityUtils"/> + + <import resource="classpath:/spring/eaaf_utils.beans.xml"/> + +</beans>
\ No newline at end of file |