diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-06-28 09:25:09 +0200 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-06-28 09:25:09 +0200 | 
| commit | 514747e925abddcb320a8433908dbae32dc5049b (patch) | |
| tree | 9bdcd47fe8ca13c27321739077d078fad5da43b8 /eaaf_modules/eaaf_module_auth_sl20 | |
| parent | 470ac2c6234a0bac1e973fd3c1f49e1d9da41be4 (diff) | |
| download | EAAF-Components-514747e925abddcb320a8433908dbae32dc5049b.tar.gz EAAF-Components-514747e925abddcb320a8433908dbae32dc5049b.tar.bz2 EAAF-Components-514747e925abddcb320a8433908dbae32dc5049b.zip | |
some small updates
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20')
10 files changed, 321 insertions, 218 deletions
| 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 f6488626..a5bbf03f 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 @@ -70,7 +70,7 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule  			log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier());  			log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE +  ": " + sl20ClientTypeHeader);			  			log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE +  ": " + sl20VDATypeHeader); -			return "SL20Authentication"; +			return getProcessName();  		} else {  			log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier()); @@ -87,6 +87,13 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule  	 */  	public abstract String getConfigPropertyNameEnableModule(); +	/** +	 * Get the name of this specific SL2.0 process +	 *  +	 * @return +	 */ +	public abstract String getProcessName(); +	  	/* (non-Javadoc)  	 * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()  	 */ 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 94322084..72781dc7 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 @@ -13,7 +13,8 @@ public class Constants {  	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX + ".security.encryption.alias";;  	public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX + ".security.encryption.password"; -	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "default"; +	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; +	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT;  	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list";  	public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; @@ -22,10 +23,12 @@ public class Constants {  	public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.required";  	public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX + ".security.eID.signed.result.required"; -	public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".ipc.return.url"; -	 +	public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url"; +	public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code"; +	public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "307";  	public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled"; +	public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints";  	public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_"; 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 9cc574bd..e19ef5fc 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 @@ -11,4 +11,6 @@ public class EventCodes {  	public static final int AUTHPROCESS_SL20_SELECTED = 4111;  	public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112;  	public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; +	 +	public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113;  } 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 dfcaaf5a..8939e61d 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 @@ -69,6 +69,9 @@ public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServl  				}  				log.debug("Use {} as VDA end-point", vdaQualeIDUrl) ; +				pendingReq.setRawDataToTransaction( +						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,  +						vdaQualeIDUrl);  				revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualeIDUrl);  				//create SL2.0 command for qualified eID @@ -129,7 +132,8 @@ public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServl  					//forward SL2.0 command  					//TODO: maybe add SL2ClientType Header from execution context -					SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL); +					SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL, +							Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));  				} else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()  						.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {  @@ -179,11 +183,12 @@ public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServl  	private String extractVDAURLForSpecificOA(ISPConfiguration oaConfig, ExecutionContext executionContext) {		 -		//TODO: fully remove if not required any more -		//String spSpecificVDAEndpoints = oaConfig.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_AUTH_SL20_ENDPOINTS);		 -		final String spSpecificVDAEndpoints = null; +		//load SP specific config for development and testing purposes +		final String spSpecificVDAEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST);		 +		//load general configuration  		final Map<String, String> endPointMap = authConfig.getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST); +		endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT));  		if (StringUtils.isNotEmpty(spSpecificVDAEndpoints)) {  			endPointMap.putAll(KeyValueUtils.convertListToMap(  							KeyValueUtils.getListOfCSVValues( @@ -199,15 +204,15 @@ public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServl  		if (StringUtils.isNotEmpty(sl20VDATypeHeader)) {  			final String vdaURL = endPointMap.get(sl20VDATypeHeader);  			if (StringUtils.isNotEmpty(vdaURL)) -				return vdaURL.trim(); -			 -			else +				return vdaURL.trim();			 +			else   				log.info("Can NOT find VDA with Id: " + sl20VDATypeHeader + ". Use default VDA");  		} -		 -		log.info("NO SP specific VDA endpoint found. Use default VDA"); -		return authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT); + +				 +		log.info("NO specific VDA endpoint requested or found. Use default VDA"); +		return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT);  	} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java index 5abbd543..761c8b24 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 @@ -2,6 +2,7 @@ package at.gv.egiz.eaaf.modules.auth.sl20.tasks;  import java.io.IOException;  import java.io.StringWriter; +import java.net.URISyntaxException;  import java.util.HashMap;  import java.util.Map;  import java.util.UUID; @@ -10,6 +11,7 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.URIBuilder;  import org.apache.http.entity.ContentType;  import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger; @@ -54,7 +56,12 @@ public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask  		try {  			log.debug("Receiving SL2.0 response process .... "); -			JsonNode sl20ReqObj = null;			 +			JsonNode sl20ReqObj = null; +			 +			//A-Trust does not SET http-header 'SL2ClientType' with value 'native' +			//If A-trust sends an error, its maybe FrontChannel on DataURL +			boolean aTrustErrorWorkAround = false; +			  			try {  				//get SL2.0 command or result from HTTP request  				final Map<String, String> reqParams = getParameters(request); @@ -88,41 +95,61 @@ public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask  				} -				//validate reqId with inResponseTo  -				final String sl20ReqId = pendingReq.getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); -				final String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); -				if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { -					log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -					throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -				} -			 -			 -				//validate signature -				final VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad( -						sl20ReqObj, joseTools,  -						authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); +				//check on errorMessage +				final VerificationResult payLoadContainerErrorCheck = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, false); +				if (SL20JSONExtractorUtils.getStringValue( +						payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) +							.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { +					log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... "); +					final JsonNode errorResult = SL20JSONExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(), joseTools, false); +					final String errorCode = SL20JSONExtractorUtils.getStringValue(errorResult,  +							SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); +					final String errorMsg = SL20JSONExtractorUtils.getStringValue(errorResult,  +							SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false); +					 +					log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... "); +					aTrustErrorWorkAround = true; +					throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg}); +									 +				} else { +					//Receive no error - To request validation +					 +					//validate reqId with inResponseTo  +					final String sl20ReqId = pendingReq.getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); +					final String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); +					if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { +						log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +						throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +					} -				if ( (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) { -					if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { -						log.info("SL20 result from VDA was not valid signed"); -						throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); -					} else { -						log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification is DISABLED by configuration!"); -						 +					//validate signature +					final VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad( +							sl20ReqObj, joseTools,  +							authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); +					 +					if ( (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) { +						if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { +							log.info("SL20 result from VDA was not valid signed"); +							throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); +					 +						} else { +							log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification is DISABLED by configuration!"); +							 +						}  					} -				} +					 +					payLoadContainer.getCertChain(); -				payLoadContainer.getCertChain(); -			 -			 -				//extract payloaf -				final JsonNode payLoad = payLoadContainer.getPayload(); -			 -				//handle SL2.0 response payLoad -				handleResponsePayLoad(payLoad); -								 +					//extract payloaf +					final JsonNode payLoad = payLoadContainer.getPayload(); +				 +					 +					//handle SL2.0 response payLoad +					handleResponsePayLoad(payLoad); +					 +				}		  			} catch (final EAAFAuthenticationException  e) {  				log.warn("SL2.0 processing error:", e); @@ -147,7 +174,7 @@ public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask  					//write SL2.0 response  					if (sl20ReqObj != null)				 -						buildResponse(request, response, sl20ReqObj); +						buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround);  					else   						buildErrorResponse(request, response, "2000", "General transport Binding error");					 @@ -197,59 +224,71 @@ public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask  	} -	private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20ReqObj) throws IOException, SL20Exception {		 -				//create response  -				final Map<String, String> reqParameters = new HashMap<String, String>(); -				reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); -				final ObjectNode callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( -						new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), null),  -						SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,  -						false,  -						reqParameters); -				final ObjectNode callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); +	private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20ReqObj, boolean aTrustErrorWorkAround) throws IOException, SL20Exception, URISyntaxException {		 +		//create response  +		final Map<String, String> reqParameters = new HashMap<String, String>(); +		reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); +		final ObjectNode callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( +				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), null),  +				SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,  +				false,  +				reqParameters); +		final ObjectNode callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); -				//build first redirect command for app -				final ObjectNode redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters( -				generateICPRedirectURLForDebugging(),  -				callCommand, null, true); -				final ObjectNode redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); -								 -				//build second redirect command for IDP -				final ObjectNode redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( -						new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()),  -						redirectOneCommand, null, true); -				final ObjectNode redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); -				 -				//build generic SL2.0 response container								 -				final String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); -				final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericRequest( -						UUID.randomUUID().toString(),  -						transactionId,  -						redirectTwoCommand,  -						null);  +		//build first redirect command for app +		final ObjectNode redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters( +		generateICPRedirectURLForDebugging(),  +		callCommand, null, true); +		final ObjectNode redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); +						 +		//build second redirect command for IDP +		final ObjectNode redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( +				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()),  +				redirectOneCommand, null, true); +		final ObjectNode redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); +		 +		//build generic SL2.0 response container								 +		final String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); +		final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericRequest( +				UUID.randomUUID().toString(),  +				transactionId,  +				redirectTwoCommand,  +				null);   		//workaround for A-Trust -				if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  +		if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&   				request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE) -					|| true) {					 +				|| !aTrustErrorWorkAround) {					  			log.debug("Client request containts 'native client' header ... ");  			log.trace("SL20 response to VDA: " + respContainer); -					final StringWriter writer = new StringWriter(); -					writer.write(respContainer.toString());						 -					final byte[] content = writer.toString().getBytes("UTF-8"); -					response.setStatus(HttpServletResponse.SC_OK); -					response.setContentLength(content.length); -					response.setContentType(ContentType.APPLICATION_JSON.toString());						 -					response.getOutputStream().write(content); -					 -					 -				} else { -					log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); -					throw new SL20Exception("sl20.06",  -							new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); -					 -				} -			} +			final StringWriter writer = new StringWriter(); +			writer.write(respContainer.toString());						 +			final byte[] content = writer.toString().getBytes("UTF-8"); +			response.setStatus(HttpServletResponse.SC_OK); +			response.setContentLength(content.length); +			response.setContentType(ContentType.APPLICATION_JSON.toString());						 +			response.getOutputStream().write(content); +			 +			 +		} else {						 +			log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); +			 +			log.debug("Client request containts is no native client ... "); +			final URIBuilder clientRedirectURI = new URIBuilder( +					new DataURLBuilder().buildDataURL( +							pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId())); +			response.setStatus(Integer.parseInt( +					authConfig.getBasicConfiguration( +							Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,  +							Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); +			response.setHeader("Location", clientRedirectURI.build().toString()); +			 +			 +//			throw new SL20Exception("sl20.06",  +//					new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); +			 +		} +	}  	/**  	 * Generates a IPC redirect URL that is configured on IDP side diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java index 959a696a..043a39bc 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java @@ -1,10 +1,5 @@  package at.gv.egiz.eaaf.modules.auth.sl20.utils; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -  import java.io.IOException;  import org.slf4j.Logger; @@ -12,17 +7,22 @@ import org.slf4j.LoggerFactory;  import org.springframework.lang.NonNull;  import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference;  import com.fasterxml.jackson.databind.DeserializationFeature;  import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonMappingException;  import com.fasterxml.jackson.databind.ObjectMapper;  import com.fasterxml.jackson.databind.SerializationFeature;  import com.fasterxml.jackson.databind.type.TypeFactory; -public class JsonMapper { +import at.gv.egiz.eaaf.core.api.utils.IJsonMapper; +import at.gv.egiz.eaaf.core.exceptions.EAAFJsonMapperException; + +public class JsonMapper implements IJsonMapper {  	private static final Logger log = LoggerFactory.getLogger(JsonMapper.class); -	private ObjectMapper mapper = new ObjectMapper(); +	private final ObjectMapper mapper = new ObjectMapper();  	/**  	 * The default constructor where the default pretty printer is disabled. @@ -53,10 +53,8 @@ public class JsonMapper {  	} -	/** -	 * Get the internal mapper implemenation -	 *  -	 * @return +	/* (non-Javadoc) +	 * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper()  	 */  	public ObjectMapper getMapper() {  		return mapper; @@ -64,44 +62,47 @@ public class JsonMapper {  	} -	/** -	 * Serialize an object to a JSON string. -	 * @param value the object to serialize -	 * @return a JSON string -	 * @throws JsonProcessingException thrown when an error occurs during serialization +	/* (non-Javadoc) +	 * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object)  	 */ -	public String serialize(Object value) throws JsonProcessingException { -		return mapper.writeValueAsString(value); +	@Override +	public String serialize(Object value) throws EAAFJsonMapperException { +		try { +			return mapper.writeValueAsString(value); +			 +		} catch (final JsonProcessingException e) { +			log.warn("JSON mapping FAILED with error: {}", e.getMessage()); +			throw new EAAFJsonMapperException(e.getMessage(), e); +			 +		}  	} -	/** -	 * Deserialize a JSON string. -	 *  -	 * @param value the JSON string to deserialize -	 * @param clazz optional parameter that determines the type of the returned object. If not set, an {@link Object} is returned. -	 * @return the deserialized JSON string as an object of type {@code clazz} or {@link Object} -	 * @throws JsonParseException if the JSON string contains invalid content. -	 * @throws JsonMappingException if the input JSON structure does not match structure expected for result type -	 * @throws IOException if an I/O problem occurs (e.g. unexpected end-of-input) +	/* (non-Javadoc) +	 * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, java.lang.Class)  	 */ -	public <T> Object deserialize(String value, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException{ - -		ObjectMapper mapper = new ObjectMapper(); -		if (clazz != null) { -			JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); -			return mapper.readValue(value, javaType); +	@Override +	public <T> Object deserialize(String value, Class<T> clazz) throws EAAFJsonMapperException { +		try {					 +			if (clazz != null) { +				if (clazz.isAssignableFrom(TypeReference.class)) +					return mapper.readValue(value, clazz); +					 +				else {				 +					final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); +					return mapper.readValue(value, javaType); +					 +				} -		} else -			return mapper.readValue(value, Object.class); +			} else +				return mapper.readValue(value, Object.class); +			 +		} catch (final IOException e) { +			log.warn("JSON mapping FAILED with error: {}", e.getMessage()); +			throw new EAAFJsonMapperException(e.getMessage(), e); +			 +		}  	} -	 -	 -	 -	public <T> Object deserialize(String value, TypeReference<T> clazz) throws JsonParseException, JsonMappingException, IOException {		 -		return mapper.readValue(value, clazz); -						 -	} -	 +							  } 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 5eda95cc..33873f43 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 @@ -57,7 +57,7 @@ public class JsonSecurityUtils implements IJOSETools{  	private Key encPrivKey = null;  	private X509Certificate[] encCertChain = null; -	private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>(); +	private final List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>();  	private static JsonMapper mapper = new JsonMapper(); @@ -66,12 +66,12 @@ public class JsonSecurityUtils implements IJOSETools{  		log.info("Initialize SL2.0 authentication security constrains ... ");  		try {  			if (getKeyStoreFilePath() != null) { 			 -				KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),  +				final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),   						getKeyStorePassword());  				//load signing key  				signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray()); -				Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias()); +				final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias());  				signCertChain = new X509Certificate[certChainSigning.length];  				for (int i=0; i<certChainSigning.length; i++) {  					if (certChainSigning[i] instanceof X509Certificate) { @@ -85,7 +85,7 @@ public class JsonSecurityUtils implements IJOSETools{  				try {  					encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray());  					if (encPrivKey != null) { -						Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias()); +						final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias());  						encCertChain = new X509Certificate[certChainEncryption.length];  						for (int i=0; i<certChainEncryption.length; i++) {  							if (certChainEncryption[i] instanceof X509Certificate) { @@ -96,18 +96,18 @@ public class JsonSecurityUtils implements IJOSETools{  					} else  						log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); -				} catch (Exception e) { +				} catch (final Exception e) {  					log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), e);  				}  				//load trusted certificates -				Enumeration<String> aliases = keyStore.aliases(); +				final Enumeration<String> aliases = keyStore.aliases();  				while(aliases.hasMoreElements()) { -					String el = aliases.nextElement(); +					final String el = aliases.nextElement();  					log.trace("Process TrustStoreEntry: " + el);  					if (keyStore.isCertificateEntry(el)) { -						Certificate cert = keyStore.getCertificate(el);  +						final Certificate cert = keyStore.getCertificate(el);   						if (cert != null && cert instanceof X509Certificate)  							trustedCerts.add((X509Certificate) cert);  						else @@ -134,7 +134,7 @@ public class JsonSecurityUtils implements IJOSETools{  			} else  				log.info("NO SL2.0 authentication security configuration. Initialization was skipped"); -		} catch ( Exception e) { +		} catch ( final Exception e) {  			log.error("SL2.0 security constrains initialization FAILED.", e);  		} @@ -145,7 +145,7 @@ public class JsonSecurityUtils implements IJOSETools{  	@Override  	public String createSignature(String payLoad) throws SLCommandoBuildException {  		try { -			JsonWebSignature jws = new JsonWebSignature(); +			final JsonWebSignature jws = new JsonWebSignature();  			//set payload  			jws.setPayload(payLoad); @@ -163,7 +163,7 @@ public class JsonSecurityUtils implements IJOSETools{  			return jws.getCompactSerialization(); -		} catch (JoseException e) { +		} catch (final JoseException e) {  			log.warn("Can NOT sign SL2.0 command.", e);  			throw new SLCommandoBuildException("Can NOT sign SL2.0 command.", e); @@ -174,7 +174,7 @@ public class JsonSecurityUtils implements IJOSETools{  	@Override  	public VerificationResult validateSignature(String serializedContent) throws SL20Exception {  		try { -			JsonWebSignature jws = new JsonWebSignature(); +			final JsonWebSignature jws = new JsonWebSignature();  			//set payload  			jws.setCompactSerialization(serializedContent); @@ -184,12 +184,12 @@ public class JsonSecurityUtils implements IJOSETools{  			//load signinc certs  			Key selectedKey = null; -			List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); -			String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +			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 ... "); -				List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); +				final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts);  				if (trustedCerts.contains(sortedX5cCerts.get(0))) {  					selectedKey = sortedX5cCerts.get(0).getPublicKey(); @@ -199,7 +199,7 @@ public class JsonSecurityUtils implements IJOSETools{  					log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString());  					try {  						log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); -					} catch (CertificateEncodingException e) { +					} catch (final CertificateEncodingException e) {  						e.printStackTrace();  					} @@ -207,7 +207,7 @@ public class JsonSecurityUtils implements IJOSETools{  			} else if (StringUtils.isNotEmpty(x5t256)) {  				log.debug("Found x5t256 fingerprint in JOSE header .... "); -				X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); +				final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts);  				selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList());  			} else { @@ -226,7 +226,7 @@ public class JsonSecurityUtils implements IJOSETools{  			jws.setKey(selectedKey);  			//validate signature -			boolean valid = jws.verifySignature(); +			final boolean valid = jws.verifySignature();  			if (!valid) {  				log.info("JWS signature invalide. Stopping authentication process ...");  				log.debug("Received JWS msg: " + serializedContent); @@ -237,7 +237,7 @@ public class JsonSecurityUtils implements IJOSETools{  			//load payLoad  			log.debug("SL2.0 commando signature validation sucessfull"); -			JsonNode sl20Req = mapper.getMapper().readTree(jws.getPayload()); +			final JsonNode sl20Req = mapper.getMapper().readTree(jws.getPayload());  			return new VerificationResult(sl20Req, null, valid) ; @@ -245,7 +245,7 @@ public class JsonSecurityUtils implements IJOSETools{  			log.warn("SL2.0 commando signature validation FAILED", e);  			throw new SL20SecurityException(new Object[]{e.getMessage()}, e); -		} catch (IOException e) { +		} catch (final IOException e) {  			log.warn("Decrypted SL2.0 result can not be parsed.", e);  			throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e); @@ -257,7 +257,7 @@ public class JsonSecurityUtils implements IJOSETools{  	@Override  	public JsonNode decryptPayload(String compactSerialization) throws SL20Exception {  		try {			 -			JsonWebEncryption receiverJwe = new JsonWebEncryption(); +			final JsonWebEncryption receiverJwe = new JsonWebEncryption();  			//set security constrains  			receiverJwe.setAlgorithmConstraints( @@ -272,12 +272,12 @@ public class JsonSecurityUtils implements IJOSETools{  			//validate key from header against key from config -			List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); -			String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); +			final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); +			final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue();  			if (x5cCerts != null) {  				log.debug("Found x509 certificate in JOSE header ... ");  				log.trace("Sorting received X509 certificates ... "); -				List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); +				final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts);  				if (!sortedX5cCerts.get(0).equals(encCertChain[0])) {  					log.info("Certificate from JOSE header does NOT match encryption certificate"); @@ -285,7 +285,7 @@ public class JsonSecurityUtils implements IJOSETools{  					try {  						log.debug("Cert: " + Base64Utils.encode(sortedX5cCerts.get(0).getEncoded())); -					} catch (CertificateEncodingException e) { +					} catch (final CertificateEncodingException e) {  						e.printStackTrace();  					}  					throw new SL20Exception("sl20.05", new Object[]{"Certificate from JOSE header does NOT match encryption certificate"}); @@ -293,7 +293,7 @@ public class JsonSecurityUtils implements IJOSETools{  			} else if (StringUtils.isNotEmpty(x5t256)) {  				log.debug("Found x5t256 fingerprint in JOSE header .... "); -				String certFingerPrint = X509Util.x5tS256(encCertChain[0]); +				final String certFingerPrint = X509Util.x5tS256(encCertChain[0]);  				if (!certFingerPrint.equals(x5t256)) {  					log.info("X5t256 from JOSE header does NOT match encryption certificate");  					log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); @@ -314,15 +314,15 @@ public class JsonSecurityUtils implements IJOSETools{  			//decrypt payload			  			return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); -		} catch (JoseException e) { +		} catch (final JoseException e) {  			log.warn("SL2.0 result decryption FAILED", e);  			throw new SL20SecurityException(new Object[]{e.getMessage()}, e); -		} catch ( JsonParseException e) { +		} catch ( final JsonParseException e) {  			log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e);  			throw new SLCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e); -		} catch (IOException e) { +		} catch (final IOException e) {  			log.warn("Decrypted SL2.0 result can not be parsed.", e);  			throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e);  		} 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 416c16b6..06c36cff 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 @@ -92,7 +92,8 @@ public class SL20Constants {  	public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect";  	public static final String SL20_COMMAND_IDENTIFIER_CALL = "call";  	public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error"; -	public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; +	@Deprecated public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; +	public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent";  	//public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig";  	public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate"; @@ -133,19 +134,25 @@ public class SL20Constants {  	public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage";  	//qualified eID command -	public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID";  	public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;  -	public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; -	public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE"; -	public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; -	public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; -	public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE";  	public static final String SL20_COMMAND_PARAM_EID_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;  	public static final String SL20_COMMAND_PARAM_EID_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; -	public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; -	public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK";  	public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL"; -	public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; +	@Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; +	 +	public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID"; +	public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent"; +	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS"; +	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ"; +	public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent";  	//qualified Signature comamnd  //	public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; 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 e1cca5ef..39f2515d 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 @@ -4,6 +4,8 @@ import java.io.IOException;  import java.io.StringWriter;  import java.net.URISyntaxException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -18,20 +20,33 @@ import com.fasterxml.jackson.databind.JsonNode;  public class SL20HttpBindingUtils {  	private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); -	public static void writeIntoResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20Forward, String redirectURL) throws IOException, URISyntaxException { +	/** +	 * Write SL2.0 response into http-response object  +	 *  +	 * @param httpReq Current http request +	 * @param httpResp Current http response +	 * @param sl20Forward SL2.0 command that should be written to response +	 * @param redirectURL SL2.0 redirect URL in case of SL2.0 redirect command and no native client (see SL2.0 specification) +	 * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command and no native client (see SL2.0 specification) +	 * @throws IOException +	 * @throws URISyntaxException +	 */ +	public static void writeIntoResponse(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp,  +			@Nonnull JsonNode sl20Forward, @Nullable String redirectURL, +			@Nonnull int httpCodeRedirect) throws IOException, URISyntaxException {  		//forward SL2.0 command -		response.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); +		httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); -		if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  -				request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { +		if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  +				httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {  			log.debug("Client request containts 'native client' header ... ");												  			final StringWriter writer = new StringWriter();  			writer.write(sl20Forward.toString());						  			final byte[] content = writer.toString().getBytes("UTF-8"); -			response.setStatus(HttpServletResponse.SC_OK); -			response.setContentLength(content.length); -			response.setContentType(ContentType.APPLICATION_JSON.toString());						 -			response.getOutputStream().write(content); +			httpResp.setStatus(HttpServletResponse.SC_OK); +			httpResp.setContentLength(content.length); +			httpResp.setContentType(ContentType.APPLICATION_JSON.toString());						 +			httpResp.getOutputStream().write(content);  		} else {  			log.debug("Client request containts is no native client ... "); @@ -39,8 +54,8 @@ public class SL20HttpBindingUtils {  			clientRedirectURI.addParameter(  					SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,   					Base64Url.encode(sl20Forward.toString().getBytes())); -			response.setStatus(307); -			response.setHeader("Location", clientRedirectURI.build().toString()); +			httpResp.setStatus(httpCodeRedirect); +			httpResp.setHeader("Location", clientRedirectURI.build().toString());  		} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java index 611bb339..84e02887 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java @@ -27,7 +27,7 @@ public class SL20JSONBuilderUtils {  	 */  	public static ObjectNode createCommand(String name, ObjectNode params) throws SLCommandoBuildException { -		ObjectNode command = mapper.getMapper().createObjectNode(); +		final ObjectNode command = mapper.getMapper().createObjectNode();  		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);  		addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);				  		return command; @@ -44,7 +44,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static String createSignedCommand(String name, ObjectNode params, IJOSETools signer) throws SLCommandoBuildException { -		ObjectNode command = mapper.getMapper().createObjectNode();	 +		final ObjectNode command = mapper.getMapper().createObjectNode();	  		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);  		addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);		  		return signer.createSignature(command.toString()); @@ -63,9 +63,9 @@ public class SL20JSONBuilderUtils {  	public static String createEncryptedCommandoResult(ObjectNode result, JsonSecurityUtils encrypter) throws SLCommandoBuildException {  		//TODO: add real implementation  		//create header and footer -		String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); -		String payLoad = result.toString(); -		String dummyFooter = createJsonSignedFooter(encrypter); +		final String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); +		final String payLoad = result.toString(); +		final String dummyFooter = createJsonSignedFooter(encrypter);  		return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "."  			+ Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "." @@ -84,7 +84,7 @@ public class SL20JSONBuilderUtils {  	 * @return  	 */  	public static ObjectNode createCommandResponse(String name, ObjectNode result, String encryptedResult) throws SLCommandoBuildException { -		ObjectNode command = mapper.getMapper().createObjectNode(); +		final ObjectNode command = mapper.getMapper().createObjectNode();  		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);		  		addOnlyOnceOfTwo(command,   				SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,  @@ -103,17 +103,17 @@ public class SL20JSONBuilderUtils {  	 * @return  	 */  	public static String createSignedCommandResponse(String name, ObjectNode result, String encryptedResult, JsonSecurityUtils signer) throws SLCommandoBuildException { -		ObjectNode command = mapper.getMapper().createObjectNode(); +		final ObjectNode command = mapper.getMapper().createObjectNode();  		addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);		  		addOnlyOnceOfTwo(command,   				SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,   				result, encryptedResult);	 -		String encodedCommand = command.toString();  +		final String encodedCommand = command.toString();   		//TODO: add real implementation  		//create header and footer -		String dummyHeader = createJsonSignedHeader(signer).toString(); -		String dummyFooter = createJsonSignedFooter(signer); +		final String dummyHeader = createJsonSignedHeader(signer).toString(); +		final String dummyFooter = createJsonSignedFooter(signer);  		return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "."  				+ Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "." @@ -132,7 +132,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createRedirectCommandParameters(String url, ObjectNode command, ObjectNode signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{ -		ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); +		final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode();  		addOnlyOnceOfTwo(redirectReqParams,   				SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND,   				command, signedCommand);		 @@ -153,7 +153,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map<String, String> reqParameters) throws SLCommandoBuildException { -		ObjectNode callReqParams = mapper.getMapper().createObjectNode(); +		final ObjectNode callReqParams = mapper.getMapper().createObjectNode();  		addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true);  		addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true);  		addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false); @@ -171,13 +171,36 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true);  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true);  		return result;  	} +	/** +	 * Create parameters for qualifiedeID command +	 *  +	 * @param consentTemplateId Identifier of the template that is used for consent visualization +	 * @param consent Consent that has to be signed by user +	 * @param dataUrl +	 * @param additionalReqParameters +	 * @param x5cEnc +	 * @return +	 * @throws CertificateEncodingException +	 * @throws SLCommandoBuildException +	 */ +	public static ObjectNode createQualifiedeEIDConsent(String consentTemplateId, byte[] consent,  String dataUrl,  +			X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { +		final ObjectNode params = mapper.getMapper().createObjectNode(); +		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true); +		addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true);		 +		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); +		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);		 +		return params; + +	} +	  	/**  	 * Create parameters for qualifiedeID command @@ -190,9 +213,10 @@ public class SL20JSONBuilderUtils {  	 * @throws CertificateEncodingException  	 * @throws SLCommandoBuildException  	 */ +	@Deprecated  	public static ObjectNode createQualifiedeIDCommandParameters(String authBlockId,  String dataUrl,   			Map<String, String> additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { -		ObjectNode params = mapper.getMapper().createObjectNode(); +		final ObjectNode params = mapper.getMapper().createObjectNode();  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true);  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);  		addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters); @@ -212,7 +236,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true);  		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true);  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true); @@ -240,7 +264,7 @@ public class SL20JSONBuilderUtils {  	 */  	public static ObjectNode createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg,   			Map<String, String> policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { -		ObjectNode params = mapper.getMapper().createObjectNode(); +		final ObjectNode params = mapper.getMapper().createObjectNode();  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true);  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true);  		addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true); @@ -266,7 +290,7 @@ public class SL20JSONBuilderUtils {  	 * @throws CertificateEncodingException  	 */  	public static ObjectNode createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true);  		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true);  		addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false); @@ -285,7 +309,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException { -		ObjectNode params = mapper.getMapper().createObjectNode(); +		final ObjectNode params = mapper.getMapper().createObjectNode();  		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true);  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true);		  		return params; @@ -299,7 +323,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS,   				SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true);  		return result; @@ -318,7 +342,7 @@ public class SL20JSONBuilderUtils {  	 * @throws CertificateEncodingException  	 */  	public static ObjectNode createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { -		ObjectNode params = mapper.getMapper().createObjectNode();		 +		final ObjectNode params = mapper.getMapper().createObjectNode();		  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true);  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true);  		addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false); @@ -335,7 +359,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true);  		addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true);		  		return result; @@ -353,7 +377,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createJwsTokenAuthCommandParams(String nonce, String dataUrl, List<String> displayData, List<String> displayUrl) throws SLCommandoBuildException { -		ObjectNode params = mapper.getMapper().createObjectNode(); +		final ObjectNode params = mapper.getMapper().createObjectNode();  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true);  		addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true);  		addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData); @@ -370,7 +394,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException { -		ObjectNode result = mapper.getMapper().createObjectNode(); +		final ObjectNode result = mapper.getMapper().createObjectNode();  		addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true);		  		return result; @@ -388,7 +412,7 @@ public class SL20JSONBuilderUtils {  	 * @throws SLCommandoBuildException  	 */  	public static ObjectNode createGenericRequest(String reqId, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { -		ObjectNode req = mapper.getMapper().createObjectNode(); +		final ObjectNode req = mapper.getMapper().createObjectNode();  		addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);  		addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true);  		addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);		 @@ -411,7 +435,7 @@ public class SL20JSONBuilderUtils {  	 */  	public static final ObjectNode createGenericResponse(String respId, String inResponseTo, String transactionId,   			ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException {		 -		ObjectNode req = mapper.getMapper().createObjectNode(); +		final ObjectNode req = mapper.getMapper().createObjectNode();  		addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);  		addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true);  		addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, true); @@ -454,7 +478,7 @@ public class SL20JSONBuilderUtils {  	//TODO!!!!  	private static ObjectNode createJsonSignedHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { -		ObjectNode header = mapper.getMapper().createObjectNode(); +		final ObjectNode header = mapper.getMapper().createObjectNode();  		addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true);  		addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true);		  		addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT)); @@ -464,7 +488,7 @@ public class SL20JSONBuilderUtils {  	//TODO!!!!  	private static ObjectNode createJsonEncryptionHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { -		ObjectNode header = mapper.getMapper().createObjectNode(); +		final ObjectNode header = mapper.getMapper().createObjectNode();  		addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true);  		addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true);  		addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true);		 @@ -488,9 +512,9 @@ public class SL20JSONBuilderUtils {  	private static void addArrayOfStrings(ObjectNode parent, String keyId, List<String> values) throws SLCommandoBuildException {  		validateParentAndKey(parent, keyId);		  		if (values != null) { -			ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); +			final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();  			parent.set(keyId, callReqParamsArray  ); -			for(String el : values) +			for(final String el : values)  				callReqParamsArray.add(el);  		} @@ -500,11 +524,11 @@ public class SL20JSONBuilderUtils {  	private static void addArrayOfStringElements(ObjectNode parent, String keyId, Map<String, String> keyValuePairs) throws SLCommandoBuildException {  		validateParentAndKey(parent, keyId);		  		if (keyValuePairs != null) {			 -			ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); +			final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();  			parent.set(keyId, callReqParamsArray); -			for(Entry<String, String> el : keyValuePairs.entrySet()) { -				ObjectNode callReqParams = mapper.getMapper().createObjectNode(); +			for(final Entry<String, String> el : keyValuePairs.entrySet()) { +				final ObjectNode callReqParams = mapper.getMapper().createObjectNode();  				callReqParams.put(el.getKey(), el.getValue());  				callReqParamsArray.add(callReqParams); | 
