aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-sl20_authentication/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/modules/moa-id-module-sl20_authentication/src/main')
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java4
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java7
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java16
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java2
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java2
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java61
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java99
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java29
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java327
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java180
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/resources/moaid_sl20_auth.beans.xml4
-rw-r--r--id/server/modules/moa-id-module-sl20_authentication/src/main/resources/sl20.Authentication.process.xml14
12 files changed, 539 insertions, 206 deletions
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java
index 920187bfb..a3648220d 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java
@@ -3,6 +3,7 @@ package at.gv.egovernment.moa.id.auth.modules.sl20_auth;
public class Constants {
public static final String HTTP_ENDPOINT_DATAURL = "/sl20/dataUrl";
+ public static final String HTTP_ENDPOINT_RESUME = "/sl20/resume";
public static final String CONFIG_PROP_PREFIX = "modules.sl20";
public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_PREFIX + ".vda.urls.qualeID.endpoint";
@@ -17,6 +18,9 @@ public class Constants {
public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ".";
public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds.";
+ public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + ".security.eID.validation.disable";
+ public static final String CONFIG_PROP_DISABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled";
+
public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_";
/**
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java
index 87d306822..4f8ef0a76 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java
@@ -44,11 +44,14 @@ public class SL20SignalServlet extends AbstractProcessEngineSignalController {
public SL20SignalServlet() {
super();
Logger.debug("Registering servlet " + getClass().getName() +
- " with mappings '"+ Constants.HTTP_ENDPOINT_DATAURL + "'.");
+ " with mappings '"+ Constants.HTTP_ENDPOINT_DATAURL +
+ " and " + Constants.HTTP_ENDPOINT_RESUME +
+ "'.");
}
- @RequestMapping(value = { Constants.HTTP_ENDPOINT_DATAURL
+ @RequestMapping(value = { Constants.HTTP_ENDPOINT_DATAURL,
+ Constants.HTTP_ENDPOINT_RESUME
},
method = {RequestMethod.POST, RequestMethod.GET})
public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException {
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java
new file mode 100644
index 000000000..957ace0fb
--- /dev/null
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java
@@ -0,0 +1,16 @@
+package at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions;
+
+public class SL20eIDDataValidationException extends SL20Exception {
+ private static final long serialVersionUID = 1L;
+
+ public SL20eIDDataValidationException(Object[] parameters) {
+ super("sl20.07", parameters);
+
+ }
+
+ public SL20eIDDataValidationException(Object[] parameters, Throwable e) {
+ super("sl20.07", parameters, e);
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java
index d00ef8a04..2563c7f7d 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java
@@ -105,7 +105,7 @@ public class JsonSecurityUtils implements IJOSETools{
}
}
-
+
//some short validation
if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {
Logger.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath());
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java
index b855c3cac..33bb4fe36 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java
@@ -12,6 +12,8 @@ public class SL20Constants {
//http binding parameters
public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand";
+ public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command";
+
public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";
public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID";
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java
index e01945df0..6949b7a18 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java
@@ -9,6 +9,7 @@ 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.log4j.Logger;
@@ -163,19 +164,23 @@ public class SL20JSONExtractorUtils {
return result;
else if (encryptedResult != null && encryptedResult.isJsonPrimitive()) {
- /*TODO:
- *
- * Remove dummy code and test real decryption!!!!!
- *
- */
-
- //return decrypter.decryptPayload(encryptedResult.getAsString());
+ try {
+ return decrypter.decryptPayload(encryptedResult.getAsString());
+
+ } catch (Exception e) {
+ log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage());
+ if (!mustBeEncrypted) {
+ log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible");
- //dummy code
- String[] signedPayload = encryptedResult.toString().split("\\.");
- JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode(signedPayload[1])));
- return payLoad;
-
+ //dummy code
+ String[] signedPayload = encryptedResult.toString().split("\\.");
+ JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode(signedPayload[1])));
+ return payLoad;
+
+ } else
+ throw e;
+
+ }
} else
throw new SLCommandoParserException("Internal build error");
@@ -241,13 +246,21 @@ public class SL20JSONExtractorUtils {
} else if (httpResp.getStatusLine().getStatusCode() == 200) {
if (!httpResp.getEntity().getContentType().getValue().equals("application/json;charset=UTF-8"))
- throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());
-
- sl20Resp = new JsonParser().parse(new InputStreamReader(httpResp.getEntity().getContent())).getAsJsonObject();
+ 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");
+ sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
+
+
} else
throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode());
-
+
+ log.info("Find JSON object in http response");
return sl20Resp;
} catch (Exception e) {
@@ -256,6 +269,22 @@ public class SL20JSONExtractorUtils {
}
}
+ private static JsonObject parseSL20ResultFromResponse(HttpEntity resp) throws Exception {
+ if (resp != null && resp.getContent() != null) {
+ JsonElement sl20Resp = new JsonParser().parse(new InputStreamReader(resp.getContent()));
+ if (sl20Resp != null && sl20Resp.isJsonObject()) {
+ return sl20Resp.getAsJsonObject();
+
+ } 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 JsonElement getAndCheck(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
JsonElement internal = input.get(keyID);
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java
index 7d03a43ac..d07d7a78a 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java
@@ -1,24 +1,17 @@
package at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier;
import java.io.IOException;
-import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.List;
-import javax.xml.bind.DatatypeConverter;
-import javax.xml.transform.TransformerException;
-
import org.jaxen.SimpleNamespaceContext;
import org.w3c.dom.Element;
import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils;
-import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
-import at.gv.egovernment.moa.id.auth.exception.BuildException;
-import at.gv.egovernment.moa.id.auth.exception.ParseException;
-import at.gv.egovernment.moa.id.auth.exception.ServiceException;
import at.gv.egovernment.moa.id.auth.exception.ValidateException;
import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20eIDDataValidationException;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;
import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;
import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;
import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureRequestBuilder;
@@ -27,13 +20,12 @@ import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;
import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse;
-import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;
import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.spss.api.impl.VerifyXMLSignatureRequestImpl;
+import at.gv.egovernment.moa.sig.tsl.utils.MiscUtil;
+import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.Constants;
-import at.gv.egovernment.moa.util.DOMUtils;
-import at.gv.egovernment.moa.util.XPathUtils;
public class QualifiedeIDVerifier {
@@ -57,7 +49,7 @@ public class QualifiedeIDVerifier {
NS_CONTEXT.addNamespace(Constants.XADES_1_4_1_NS_PREFIX, Constants.XADES_1_4_1_NS_URI);
}
- public static boolean verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {
+ public static void verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {
// validates the identity link
IdentityLinkValidator.getInstance().validate(idl);
@@ -79,17 +71,15 @@ public class QualifiedeIDVerifier {
VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK,
oaParam);
-
- return false;
-
+
}
- public static IVerifiyXMLSignatureResponse verifyAuthBlock(byte[] authblock, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {
+ public static IVerifiyXMLSignatureResponse verifyAuthBlock(String authBlockB64, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException, IOException {
String trustProfileId = authConfig.getMoaSpAuthBlockTrustProfileID(oaParam.isUseAuthBlockTestTestStore());
List<String> verifyTransformsInfoProfileID = null;
SignatureVerificationUtils sigVerify = new SignatureVerificationUtils();
- IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(authblock, trustProfileId , verifyTransformsInfoProfileID);
+ IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(Base64Utils.decode(authBlockB64, false), trustProfileId , verifyTransformsInfoProfileID);
// validates the <VerifyXMLSignatureResponse>
VerifyXMLSignatureResponseValidator.getInstance().validate(sigVerifyResult,
@@ -99,20 +89,43 @@ public class QualifiedeIDVerifier {
}
- public static boolean checkIDLAgainstAuthblock(IVerifiyXMLSignatureResponse sigVerifyResult, IIdentityLink idl, byte[] authBlock) throws ValidateException {
+ public static boolean checkConsistencyOfeIDData(String sl20ReqId, IIdentityLink idl, AssertionAttributeExtractor authBlockExtractor, IVerifiyXMLSignatureResponse sigVerifyResult) throws SL20eIDDataValidationException {
try {
// compares the public keys from the identityLink with the AuthBlock
VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(sigVerifyResult, idl);
+ //compare requestId from SL20 qualifiedeID command to ID from SAML2 assertion
+ String authBlockId = authBlockExtractor.getAssertionID();
+ if (MiscUtil.isEmpty(authBlockId)) {
+ Logger.info("AuthBlock containts no ID, but ID MUST be included");
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "AuthBlock containts no ID, but ID MUST be included"
+ });
+ }
+ if (!authBlockId.equals(sl20ReqId)) {
+ Logger.info("SL20 'requestId' does NOT match to AuthBlock Id."
+ + " Expected : " + sl20ReqId
+ + " Authblock: " + authBlockId);
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "SL20 'requestId' does NOT match to AuthBlock Id."
+ });
+ }
+
+
// Compare AuthBlock Data with information stored in session, especially
// date and time
- validateSigningDateTime(sigVerifyResult);
+ validateSigningDateTime(sigVerifyResult, authBlockExtractor);
} catch ( ValidateException e) {
- Logger.error("Signature verification error. ", e);
- throw e;
+ Logger.warn("Validation of eID information FAILED. ", e);
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL,
+ e.getMessage()
+ });
}
@@ -121,12 +134,46 @@ public class QualifiedeIDVerifier {
}
- private static boolean validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult) throws ValidateException {
+ private static void validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult, AssertionAttributeExtractor authBlockExtractor) throws SL20eIDDataValidationException {
Date signingDate = sigVerifyResult.getSigningDateTime();
+ Date notBefore = authBlockExtractor.getAssertionNotBefore();
+ Date notOrNotAfter = authBlockExtractor.getAssertionNotOnOrAfter();
+ if (signingDate == null) {
+ Logger.info("AuthBlock signature contains NO signing data");
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "AuthBlock signature contains NO signing data"
+ });
+
+ }
-
- return false;
+ Logger.debug("AuthBlock signing data: " + signingDate.toString());
+
+ if (notBefore == null || notOrNotAfter == null) {
+ Logger.info("AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates");
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates"
+ });
+
+ }
+
+ Logger.debug("AuthBlock valid period."
+ + " NotBefore:" + notBefore.toString()
+ + " NotOrNotAfter:" + notOrNotAfter.toString());
+
+ if (signingDate.after(notBefore) || signingDate.before(notOrNotAfter))
+ Logger.debug("Signing date validation successfull");
+
+ else {
+ Logger.info("AuthBlock signing date does NOT match to AuthBlock constrains");
+ throw new SL20eIDDataValidationException(new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "AuthBlock signing date does NOT match to AuthBlock constrains"
+ });
+
+ }
}
}
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java
index d9ff9d93c..763454639 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java
@@ -5,7 +5,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.UUID;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.http.HttpServletRequest;
@@ -30,6 +29,7 @@ import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.Constants;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.data.VerificationResult;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20Exception;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SLCommandoParserException;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.IJOSETools;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20HttpBindingUtils;
@@ -41,6 +41,7 @@ import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;
import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import at.gv.egovernment.moa.id.util.SSLUtils;
import at.gv.egovernment.moa.util.MiscUtil;
import at.gv.egovernment.moaspss.logging.Logger;
@@ -91,7 +92,8 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {
qualifiedeIDParams,
joseTools.getEncryptionCertificate());
- String qualeIDReqId = UUID.randomUUID().toString();
+ //String qualeIDReqId = UUID.randomUUID().toString();
+ String qualeIDReqId = SAML2Utils.getSecureIdentifier();
String signedQualeIDCommand = SL20JSONBuilderUtils.createSignedCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID, qualeIDCommandParams, joseTools);
JsonObject sl20Req = SL20JSONBuilderUtils.createGenericRequest(qualeIDReqId, null, null, signedQualeIDCommand);
@@ -107,9 +109,16 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {
HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualeIDUrl).build());
httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE);
List<NameValuePair> parameters = new ArrayList<NameValuePair>();;
- parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, sl20Req.toString()));
+
+ //correct one
+ //parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes())));
+
+ //A-Trust current version
+ parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM_OLD, sl20Req.toString()));
httpReq.setEntity(new UrlEncodedFormEntity(parameters ));
+
+
//request VDA
HttpResponse httpResp = httpClient.execute(httpReq);
@@ -147,10 +156,22 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {
//TODO: maybe add SL2ClientType Header from execution context
SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL);
+ } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()
+ .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {
+ JsonObject result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false);
+ if (result == null)
+ result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false);
+
+ String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true);
+ String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true);
+
+ Logger.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg);
+ throw new SL20Exception("sl20.08", new Object[]{errorCode, errorMsg});
+
} else {
//TODO: update to add error handling
Logger.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString());
-
+ throw new SLCommandoParserException("Received an unrecognized command: \" + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()");
}
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java
index 90e19326e..b7fe579a3 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java
@@ -1,9 +1,8 @@
package at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks;
-import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.StringWriter;
import java.security.cert.X509Certificate;
-import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -13,7 +12,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.entity.ContentType;
-import org.jose4j.keys.X509Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -35,18 +33,12 @@ import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.IJOSETools;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONBuilderUtils;
import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONExtractorUtils;
-import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
-import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
-import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController;
-import at.gv.egovernment.moa.util.Base64Utils;
-import at.gv.egovernment.moa.util.DateTimeUtils;
import at.gv.egovernment.moa.util.MiscUtil;
import at.gv.egovernment.moaspss.logging.Logger;
-import iaik.esi.sva.util.X509Utils;
-import iaik.utils.Util;
+
@Component("ReceiveQualeIDTask")
public class ReceiveQualeIDTask extends AbstractAuthServletTask {
@@ -57,173 +49,210 @@ public class ReceiveQualeIDTask extends AbstractAuthServletTask {
public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
throws TaskExecutionException {
- Logger.debug("Receiving SL2.0 response process .... ");
try {
- //get SL2.0 command or result from HTTP request
- Map<String, String> reqParams = getParameters(request);
- String sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM);
- if (MiscUtil.isEmpty(sl20Result)) {
- Logger.info("NO SL2.0 commando or result FOUND.");
- throw new SL20Exception("sl20.04", null);
-
- }
-
-
- //parse SL2.0 command/result into JSON
+ Logger.debug("Receiving SL2.0 response process .... ");
JsonObject sl20ReqObj = null;
try {
- JsonParser jsonParser = new JsonParser();
- JsonElement sl20Req = jsonParser.parse(sl20Result);
- sl20ReqObj = sl20Req.getAsJsonObject();
+ //get SL2.0 command or result from HTTP request
+ Map<String, String> reqParams = getParameters(request);
+ String sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM);
+ if (MiscUtil.isEmpty(sl20Result)) {
+ Logger.info("NO SL2.0 commando or result FOUND.");
+ throw new SL20Exception("sl20.04", null);
+
+ }
+
+ //parse SL2.0 command/result into JSON
+ try {
+ JsonParser jsonParser = new JsonParser();
+ JsonElement sl20Req = jsonParser.parse(sl20Result);
+ sl20ReqObj = sl20Req.getAsJsonObject();
+
+ } catch (JsonSyntaxException e) {
+ Logger.warn("SL2.0 command or result is NOT valid JSON.", e);
+ Logger.debug("SL2.0 msg: " + sl20Result);
+ throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e);
+
+ }
- } catch (JsonSyntaxException e) {
- Logger.warn("SL2.0 command or result is NOT valid JSON.", e);
- Logger.debug("SL2.0 msg: " + sl20Result);
- throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e);
+ //validate reqId with inResponseTo
+ String sl20ReqId = pendingReq.getGenericData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class);
+ String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true);
+ if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) {
+ Logger.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
+ throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
+ }
- }
-
- //validate reqId with inResponseTo
- String sl20ReqId = pendingReq.getGenericData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class);
- String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true);
- if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) {
- Logger.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
- throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
- }
-
-
- //validate signature
- VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, true);
- if (payLoadContainer.isValidSigned() == null ||
- !payLoadContainer.isValidSigned()) {
- Logger.info("SL20 result from VDA was not valid signed");
- throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."});
- }
-
- //TODO validate certificate
- List<X509Certificate> sigCertChain = payLoadContainer.getCertChain();
-
-
- //extract payloaf
- JsonObject payLoad = payLoadContainer.getPayload();
-
- //check response type
- if (SL20JSONExtractorUtils.getStringValue(
- payLoad, SL20Constants.SL20_COMMAND_CONTAINER_NAME, true)
- .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID)) {
- Logger.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result .... ");
-
- //TODO: activate decryption in 'SL20JSONExtractorUtils.extractSL20Result'
- JsonElement qualeIDResult = SL20JSONExtractorUtils.extractSL20Result(payLoad, joseTools, false);
-
- //extract attributes from result
- String idlB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
- SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, true);
- String authBlockB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
- SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, true);
- String ccsURL = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
- SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, true);
- String LoA = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
- SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, true);
+ //validate signature
+ VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, true);
+ if (payLoadContainer.isValidSigned() == null ||
+ !payLoadContainer.isValidSigned()) {
+ Logger.info("SL20 result from VDA was not valid signed");
+ throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."});
+
+ }
+ /*TODO validate certificate by using MOA-SPSS
+ * currently, the certificate is validated in IJOSETools by using a pkcs12 or jks keystore
+ */
+ List<X509Certificate> sigCertChain = payLoadContainer.getCertChain();
- //TODO: validate results
- IIdentityLink idl = new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink();
+ //extract payloaf
+ JsonObject payLoad = payLoadContainer.getPayload();
+ //check response type
+ if (SL20JSONExtractorUtils.getStringValue(
+ payLoad, SL20Constants.SL20_COMMAND_CONTAINER_NAME, true)
+ .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID)) {
+ Logger.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result .... ");
+
+ JsonElement qualeIDResult = SL20JSONExtractorUtils.extractSL20Result(
+ payLoad, joseTools,
+ authConfig.getBasicMOAIDConfigurationBoolean(Constants.CONFIG_PROP_DISABLE_EID_ENCRYPTION, true));
+
+ //extract attributes from result
+ String idlB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, true);
+ String authBlockB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, true);
+ String ccsURL = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, true);
+ String LoA = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, true);
+
+ //cache qualified eID data into pending request
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL,
+ idlB64);
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ authBlockB64);
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,
+ ccsURL);
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA,
+ LoA);
+
+ } else {
+ Logger.info("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result");
+ throw new SLCommandoParserException("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result");
+ }
- //add into session
- defaultTaskInitialization(request, executionContext);
- moasession.setIdentityLink(idl);
- moasession.setBkuURL(ccsURL);
- //TODO: from AuthBlock
- moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(Calendar.getInstance()));
- moasession.setQAALevel(LoA);
- //mark as authenticated
- moasession.setAuthenticated(true);
- pendingReq.setAuthenticated(true);
-
- //store pending request
- requestStoreage.storePendingRequest(pendingReq);
-
- //create response
- Map<String, String> reqParameters = new HashMap<String, String>();
- reqParameters.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID());
- JsonObject callReqParams = SL20JSONBuilderUtils.createCallCommandParameters(
- new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, null),
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,
- false,
- reqParameters);
- JsonObject callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams);
+ } catch (MOAIDException e) {
+ Logger.warn("SL2.0 processing error:", e);
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
+ new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e));
- //build first redirect command for app
- JsonObject redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters("", callCommand, null, true);
- JsonObject redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
-
- //build second redirect command for IDP
- JsonObject redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters(
- new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, null),
- redirectOneCommand, null, true);
- JsonObject redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
+ } catch (Exception e) {
+ Logger.warn("ERROR:", e);
+ Logger.warn("SL2.0 Authentication FAILED with a generic error.", e);
+ pendingReq.setGenericDataToSession(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
+ new TaskExecutionException(pendingReq, e.getMessage(), e));
- //build generic SL2.0 response container
- String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false);
- JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest(
- UUID.randomUUID().toString(),
- transactionId,
- redirectTwoCommand,
- null);
+ } finally {
+ //store pending request
+ requestStoreage.storePendingRequest(pendingReq);
- if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&
- request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
- Logger.debug("Client request containts 'native client' header ... ");
- 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);
+ //write SL2.0 response
+ if (sl20ReqObj != null)
+ buildResponse(request, response, sl20ReqObj);
+ else
+ buildErrorResponse(request, response, "2000", "General transport Binding error");
-
- } else {
- Logger.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 + "'"});
-
- }
-
- } else {
- Logger.info("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result");
- throw new SLCommandoParserException("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result");
}
-
-
- } catch (MOAIDException e) {
- Logger.warn("ERROR:", e);
- throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e);
-
+
} catch (Exception e) {
- Logger.warn("ERROR:", e);
- Logger.warn("SL2.0 Authentication FAILED with a generic error.", e);
- throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+ //write internal server errror 500 according to SL2.0 specification, chapter https transport binding
+ Logger.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e);
+ try {
+ response.sendError(500, "Internal Server Error.");
+
+ } catch (IOException e1) {
+ Logger.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e);
+
+ }
- } finally {
+ } finally {
TransactionIDUtils.removeTransactionId();
TransactionIDUtils.removeSessionId();
}
}
-
- private JsonObject createRedirectCommand() {
-
+ private void buildErrorResponse(HttpServletRequest request, HttpServletResponse response, String errorCode, String errorMsg) throws Exception {
+ JsonObject error = SL20JSONBuilderUtils.createErrorCommandResult(errorCode, errorMsg);
+ JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest(
+ UUID.randomUUID().toString(),
+ null,
+ error ,
+ null);
+
+ Logger.debug("Client request containts 'native client' header ... ");
+ StringWriter writer = new StringWriter();
+ writer.write(respContainer.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentLength(content.length);
+ response.setContentType(ContentType.APPLICATION_JSON.toString());
+ response.getOutputStream().write(content);
+
+ }
+
+ private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonObject sl20ReqObj) throws IOException, SL20Exception {
+ //create response
+ Map<String, String> reqParameters = new HashMap<String, String>();
+ reqParameters.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID());
+ JsonObject callReqParams = SL20JSONBuilderUtils.createCallCommandParameters(
+ new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), Constants.HTTP_ENDPOINT_RESUME, null),
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,
+ false,
+ reqParameters);
+ JsonObject callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams);
- return null;
+ //build first redirect command for app
+ JsonObject redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters("", callCommand, null, true);
+ JsonObject redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
+
+ //build second redirect command for IDP
+ JsonObject redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters(
+ new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), Constants.HTTP_ENDPOINT_RESUME, null),
+ redirectOneCommand, null, true);
+ JsonObject redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
+ //build generic SL2.0 response container
+ String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false);
+ JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest(
+ UUID.randomUUID().toString(),
+ transactionId,
+ redirectTwoCommand,
+ null);
+ if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&
+ request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
+ Logger.debug("Client request containts 'native client' header ... ");
+ 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 {
+ Logger.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 + "'"});
+
+ }
}
+
+
}
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java
new file mode 100644
index 000000000..b5c84d315
--- /dev/null
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java
@@ -0,0 +1,180 @@
+package at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks;
+
+import java.io.ByteArrayInputStream;
+import java.util.Calendar;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.Configuration;
+import org.opensaml.saml2.core.Assertion;
+import org.opensaml.xml.XMLObject;
+import org.opensaml.xml.io.Unmarshaller;
+import org.opensaml.xml.io.UnmarshallerFactory;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.Constants;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20eIDDataValidationException;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;
+import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier.QualifiedeIDVerifier;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;
+import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.util.Base64Utils;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.DateTimeUtils;
+import at.gv.egovernment.moaspss.logging.Logger;
+
+
+@Component("VerifyQualifiedeIDTask")
+public class VerifyQualifiedeIDTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+
+ Logger.debug("Verify qualified eID data from SL20 response .... ");
+ try {
+ //check if there was an error
+ TaskExecutionException sl20Error = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
+ TaskExecutionException.class);
+ if (sl20Error != null) {
+ Logger.info("Found SL2.0 error after redirect ... ");
+ throw sl20Error;
+
+ }
+
+ //get data from pending request
+ String sl20ReqId = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,
+ String.class);
+ String idlB64 = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL,
+ String.class);
+ String authBlockB64 = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ String.class);
+ String ccsURL = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,
+ String.class);
+ String LoA = pendingReq.getGenericData(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA,
+ String.class);
+
+ //parse eID data
+ IIdentityLink idl = new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink();
+ IVerifiyXMLSignatureResponse authBlockVerificationResult = null;
+ try {
+ Assertion authBlock = parseAuthBlockToSaml2Assertion(authBlockB64);
+ AssertionAttributeExtractor authBlockExtractor = new AssertionAttributeExtractor(authBlock);
+
+
+ //validate eID data
+ QualifiedeIDVerifier.verifyIdentityLink(idl, pendingReq.getOnlineApplicationConfiguration(), authConfig);
+ authBlockVerificationResult = QualifiedeIDVerifier.verifyAuthBlock(
+ authBlockB64, pendingReq.getOnlineApplicationConfiguration(), authConfig);
+ QualifiedeIDVerifier.checkConsistencyOfeIDData(sl20ReqId, idl, authBlockExtractor, authBlockVerificationResult);
+
+ //TODO: add LoA verification
+
+ } catch (SL20eIDDataValidationException e) {
+ if (authConfig.getBasicMOAIDConfigurationBoolean(Constants.CONFIG_PROP_DISABLE_EID_VALIDATION, false)) {
+ Logger.warn("SL20 eID data validation IS DISABLED!!");
+ Logger.warn("SL20 eID data IS NOT VALID!!! Reason: " + e.getMessage(), e);
+
+ } else
+ throw e;
+
+ }
+
+ //add into session
+ defaultTaskInitialization(request, executionContext);
+ moasession.setIdentityLink(idl);
+ moasession.setBkuURL(ccsURL);
+ //TODO: from AuthBlock
+ if (authBlockVerificationResult != null)
+ moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(authBlockVerificationResult.getSigningDateTime()));
+ else
+ moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(Calendar.getInstance()));
+
+ moasession.setQAALevel(LoA);
+
+ //store pending request
+ requestStoreage.storePendingRequest(pendingReq);
+
+ } catch (MOAIDException e) {
+ Logger.warn("ERROR:", e);
+ throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e);
+
+ } catch (Exception e) {
+ Logger.warn("ERROR:", e);
+ Logger.warn("SL2.0 Authentication FAILED with a generic error.", e);
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ } finally {
+ TransactionIDUtils.removeTransactionId();
+ TransactionIDUtils.removeSessionId();
+
+ }
+ }
+
+ private Assertion parseAuthBlockToSaml2Assertion(String authblockB64) throws SL20eIDDataValidationException {
+ try {
+ //parse authBlock into SAML2 Assertion
+ byte[] authBlockBytes = Base64Utils.decode(authblockB64, false);
+ Element authBlockDOM = DOMUtils.parseXmlValidating(new ByteArrayInputStream(authBlockBytes));
+ UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
+ Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(authBlockDOM);
+ XMLObject samlAssertion = unmarshaller.unmarshall(authBlockDOM);
+
+ //validate SAML2 Assertion
+ SAML2Utils.schemeValidation(samlAssertion);
+
+ if (samlAssertion instanceof Assertion)
+ return (Assertion) samlAssertion;
+ else
+ throw new SL20eIDDataValidationException(
+ new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ "AuthBlock is NOT of type SAML2 Assertion"
+ });
+
+ } catch (SL20eIDDataValidationException e) {
+ throw e;
+
+ } catch (SAXException e) {
+ Logger.info("Scheme validation of SAML2 AuthBlock FAILED. Reason: " + e.getMessage());
+ throw new SL20eIDDataValidationException(
+ new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ e.getMessage()
+ },
+ e);
+
+ } catch (Exception e) {
+ Logger.info("Can not parse AuthBlock. Reason: " + e.getMessage());
+ Logger.trace("FullAuthBlock: " + authblockB64);
+ throw new SL20eIDDataValidationException(
+ new Object[] {
+ SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,
+ e.getMessage()
+ },
+ e);
+
+ }
+
+ }
+
+
+
+}
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/moaid_sl20_auth.beans.xml b/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/moaid_sl20_auth.beans.xml
index 37551b3f5..a9c9bac8e 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/moaid_sl20_auth.beans.xml
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/moaid_sl20_auth.beans.xml
@@ -29,5 +29,9 @@
<bean id="ReceiveQualeIDResponseTask"
class="at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks.ReceiveQualeIDTask"
scope="prototype"/>
+
+ <bean id="VerifyQualifiedeIDTask"
+ class="at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks.VerifyQualifiedeIDTask"
+ scope="prototype"/>
</beans> \ No newline at end of file
diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/sl20.Authentication.process.xml b/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/sl20.Authentication.process.xml
index bcd74f84c..4975dc2d7 100644
--- a/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/sl20.Authentication.process.xml
+++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/resources/sl20.Authentication.process.xml
@@ -3,17 +3,15 @@
<pd:Task id="createQualifiedeIDRequest" class="CreateQualeIDRequestTask" />
<pd:Task id="receiveQualifiedeID" class="ReceiveQualeIDResponseTask" async="true"/>
-
- <!-- <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" /> -->
+ <pd:Task id="verifyQualifiedeIDTask" class="VerifyQualifiedeIDTask" async="true"/>
+ <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" />
<pd:StartEvent id="start" />
<pd:Transition from="start" to="createQualifiedeIDRequest" />
- <pd:Transition from="createQualifiedeIDRequest" to="receiveQualifiedeID" />
- <pd:Transition from="receiveQualifiedeID" to="end" />
-
- <!-- It's only required if we can not use the finalize redirect on SL20 redirect command -->
- <!-- <pd:Transition from="receiveQualifiedeID" to="finalizeAuthentication" />
- <pd:Transition from="finalizeAuthentication" to="end" /> -->
+ <pd:Transition from="createQualifiedeIDRequest" to="receiveQualifiedeID" />
+ <pd:Transition from="receiveQualifiedeID" to="verifyQualifiedeIDTask" />
+ <pd:Transition from="verifyQualifiedeIDTask" to="finalizeAuthentication" />
+ <pd:Transition from="finalizeAuthentication" to="end" />
<pd:EndEvent id="end" />