aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2016-03-24 17:03:22 +0100
committerThomas Lenz <tlenz@iaik.tugraz.at>2016-03-24 17:03:22 +0100
commit5848cd0057ad9f607e8c117c18481f5caebfd357 (patch)
treecec2b71ea17bfe89e8e0f188b9bdd8794dd0b25c
parent5b1f6e34fa4c9fd6c992efd347127db863fb1031 (diff)
downloadmoa-id-spss-5848cd0057ad9f607e8c117c18481f5caebfd357.tar.gz
moa-id-spss-5848cd0057ad9f607e8c117c18481f5caebfd357.tar.bz2
moa-id-spss-5848cd0057ad9f607e8c117c18481f5caebfd357.zip
update Session-Transfer-Module to restore session
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngineSP.java14
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java7
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java2
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java117
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java25
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java17
6 files changed, 134 insertions, 48 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngineSP.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngineSP.java
index d9bc7daaf..385fe90fb 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngineSP.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngineSP.java
@@ -62,7 +62,7 @@ import at.gv.egovernment.moa.logging.Logger;
public class SAMLVerificationEngineSP extends SAMLVerificationEngine {
@Autowired AuthConfiguration authConfig;
-
+
/**
* Validate a PVP response and all included assertions
*
@@ -74,6 +74,13 @@ public class SAMLVerificationEngineSP extends SAMLVerificationEngine {
* @throws AssertionValidationExeption
*/
public void validateAssertion(Response samlResp, boolean validateDestination, Credential assertionDecryption, String spEntityID, String loggerSPName) throws AssertionValidationExeption {
+ validateAssertion(samlResp, validateDestination, assertionDecryption, spEntityID, loggerSPName, true);
+
+ }
+
+
+ public void validateAssertion(Response samlResp, boolean validateDestination, Credential assertionDecryption, String spEntityID, String loggerSPName,
+ boolean validateDateTime) throws AssertionValidationExeption {
try {
if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
List<org.opensaml.saml2.core.Assertion> saml2assertions = new ArrayList<org.opensaml.saml2.core.Assertion>();
@@ -102,7 +109,7 @@ public class SAMLVerificationEngineSP extends SAMLVerificationEngine {
throw new AssertionValidationExeption("sp.pvp2.07", new Object[]{loggerSPName, "'IssueInstant' attribute is not included"});
}
- if (issueInstant.minusMinutes(MOAIDAuthConstants.TIME_JITTER).isAfterNow()) {
+ if (validateDateTime && issueInstant.minusMinutes(MOAIDAuthConstants.TIME_JITTER).isAfterNow()) {
Logger.warn("PVP response: IssueInstant DateTime is not valid anymore.");
throw new AssertionValidationExeption("sp.pvp2.07", new Object[]{loggerSPName, "'IssueInstant' Time is not valid any more"});
@@ -150,7 +157,8 @@ public class SAMLVerificationEngineSP extends SAMLVerificationEngine {
if (conditions != null) {
DateTime notbefore = conditions.getNotBefore().minusMinutes(5);
DateTime notafter = conditions.getNotOnOrAfter();
- if ( notbefore.isAfterNow() || notafter.isBeforeNow() ) {
+ if (validateDateTime &&
+ (notbefore.isAfterNow() || notafter.isBeforeNow()) ) {
isAssertionValid = false;
Logger.info("Assertion:" + saml2assertion.getID()
+ " is out of Date. "
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java
index 1ee715afa..1a4356653 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java
@@ -59,11 +59,18 @@ public class SSOTransferConstants {
public static final String SSOCONTAINER_KEY_SESSION = "session";
public static final String SSOCONTAINER_KEY_RESULTENDPOINT = "resultEndPoint";
public static final String SSOCONTAINER_KEY_NONCE = "nonce";
+ public static final String SSOCONTAINER_KEY_BLOB = "blob";
+ public static final String SSOCONTAINER_KEY_SIGNATURE = "signature";
+ public static final String SSOCONTAINER_KEY_UNIQUEUSERID = "bPK";
+
+ public static final String SSOCONTAINER_KEY_STATUS = "status";
public static final String FLAG_SSO_SESSION_RESTORED = "ssoRestoredFlag";
public static final long CERT_VALIDITY = 700; //2 years
public static final String PENDINGREQ_DH = "dhparams";
public static final String PENDINGREQ_NONCE = "nonce";
+
+
}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java
index 7cf7c914a..b18425839 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java
@@ -278,7 +278,7 @@ public class SSOTransferServlet{
@RequestMapping(value = { "/TransmitSSOSession"
},
- method = {RequestMethod.GET})
+ method = {RequestMethod.GET, RequestMethod.POST})
public void transferToPhone(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Logger.debug("Receive " + this.getClass().getName() + " request");
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
index 6d9b43e5b..dd133e4fb 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
@@ -24,6 +24,7 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.task;
import java.io.BufferedReader;
import java.io.IOException;
+import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.MessageDigest;
@@ -96,48 +97,57 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
Logger.warn("Received POST-message produce an ERROR.", e);
}
-
- //session is valid --> load MOASession object
- try {
- defaultTaskInitialization(request, executionContext);
-
- } catch (MOAIDException | MOADatabaseException e1) {
- Logger.error("Database Error! MOASession is not stored!");
- throw new TaskExecutionException(pendingReq, "Load MOASession FAILED.", e1);
-
- }
-
+
String nonce = pendingReq.getGenericData(SSOTransferConstants.PENDINGREQ_NONCE, String.class);
SSOTransferContainer container = pendingReq.getGenericData(
SSOTransferConstants.PENDINGREQ_DH, SSOTransferContainer.class);
if (container == null) {
- throw new TaskExecutionException(pendingReq, "NO DH-Params in pending-request", null);
+ throw new TaskExecutionException(pendingReq, "NO DH-Params in pending-request",
+ new MOAIDException("NO DH-Params in pending-request", null));
}
if (MiscUtil.isNotEmpty(receivedPostMessage)) {
Logger.debug("Receive POST-Message data. Start data-validation process ... ");
+ JsonObject responseMsg = new JsonObject();
try {
+ Logger.debug("Unformated Msg:" + receivedPostMessage);
+
JsonParser parser = new JsonParser();
- JsonObject reveivedData = (JsonObject) parser.parse(sb.toString());
- JsonObject reveivedSession = reveivedData.get("session").getAsJsonObject();
- String validTo = reveivedSession.get("validTo").getAsString();
- String entityID = reveivedSession.get("entityID").getAsString();
- //String sessionBlob = reveivedSession.get("sessionBlob").getAsString();
-
-// Logger.trace("Blob:" + sessionBlob +
-// " | validTo:" + validTo +
-// " | entityIS:" + entityID);
-
-
- //TODO!!!!
- String mobilePubKeyBase64 = reveivedSession.get(
+ JsonObject receivedData = (JsonObject) parser.parse(sb.toString());
+
+ JsonObject receivedSession = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_SESSION).getAsJsonObject();
+
+ Logger.debug("Received Session-Object:"+ receivedSession.toString());
+
+ String signature = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_SIGNATURE).getAsString();
+ String mobilePubKeyBase64 = receivedData.get(
SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();
- String encSessionBlobBase64 = new String();
+
+ String respNonce = receivedSession.get(
+ SSOTransferConstants.PENDINGREQ_NONCE).getAsString();
+ String encSessionBlobBase64 = receivedSession.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_BLOB).getAsString();
- Logger.debug("Receive PubKey:" +mobilePubKeyBase64 + " | SessionBlob:" + encSessionBlobBase64);
+ Logger.debug("Receive PubKey:" +mobilePubKeyBase64
+ + " | SessionBlob:" + encSessionBlobBase64
+ + " | Nonce:" + respNonce
+ + " | Signature:" + signature
+ + " | SignedData:" + receivedSession.toString());
+ if (MiscUtil.isEmpty(respNonce) || !respNonce.equals(nonce)) {
+ Logger.warn("Received 'nonce':" + respNonce
+ + " does not match to stored 'nonce':" + nonce);
+ throw new TaskExecutionException(pendingReq, "Received 'nonce':" + respNonce
+ + " does not match to stored 'nonce':" + nonce,
+ new MOAIDException("Received 'nonce':" + respNonce + " does not match to stored 'nonce':" + nonce, null));
+
+ }
+
+
//finish DH key agreement
BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, true));
DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,
@@ -175,6 +185,16 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
Logger.debug("MobileDevice is valid. --> Starting session reconstruction ...");
+ //session is valid --> load MOASession object
+ try {
+ defaultTaskInitialization(request, executionContext);
+
+ } catch (MOAIDException | MOADatabaseException e1) {
+ Logger.error("Database Error! MOASession is not stored!");
+ throw new TaskExecutionException(pendingReq, "Load MOASession FAILED.", e1);
+
+ }
+
//transfer SSO Assertion into MOA-Session
ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, attributeExtractor);
@@ -190,8 +210,18 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
executionContext.put(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED, true);
executionContext.put("sessionRestoreFinished", false);
-
+
+
+ responseMsg.addProperty(
+ SSOTransferConstants.SSOCONTAINER_KEY_STATUS,
+ "OK");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+ out.print(responseMsg.toString());
+ out.flush();
+
// Logger.info("Received SSO session-data is from IDP: " + entityID
// + ". Start inderfederation process to restore SSO session ... ");
// //change to inderfederated session reconstruction
@@ -202,8 +232,20 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
} catch (Exception e) {
Logger.error("Parse reveived JSON data-object " + sb.toString() + " FAILED!", e);
- throw new TaskExecutionException(pendingReq, "JSON data is not parseable.", e);
-
+ //throw new TaskExecutionException(pendingReq, "JSON data is not parseable.", e);
+ try {
+ responseMsg.addProperty(
+ SSOTransferConstants.SSOCONTAINER_KEY_STATUS,
+ "FAILED");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+ out.print(responseMsg.toString());
+ out.flush();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+
+ }
}
} else {
@@ -218,10 +260,21 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
executionContext.put("sessionRestoreFinished", true);
} else {
+ //session is valid --> load MOASession object
+ try {
+ defaultTaskInitialization(request, executionContext);
+
+ } catch (MOAIDException | MOADatabaseException e1) {
+ Logger.error("Database Error! MOASession is not stored!");
+ throw new TaskExecutionException(pendingReq, "Load MOASession FAILED.", e1);
+
+ }
+
DateTime moaSessionCreated = new DateTime(moasession.getSessionCreated().getTime());
- if (moaSessionCreated.plusMinutes(3).isBeforeNow()) {
+ if (moaSessionCreated.plusMinutes(1).isBeforeNow()) {
Logger.warn("No SSO session-container received. Stop authentication process after time-out.");
- throw new TaskExecutionException(pendingReq, "No SSO container received from smartphone app.", null);
+ throw new TaskExecutionException(pendingReq, "No SSO container received from smartphone app.",
+ new MOAIDException("No SSO container received from smartphone app.", null));
} else {
Logger.debug("No restored SSO session found --> Wait a few minutes and check again.");
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java
index 753da96de..0785f767b 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java
@@ -129,6 +129,7 @@ import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.MiscUtil;
+import at.gv.util.BpkUtil;
import iaik.x509.X509Certificate;
/**
@@ -269,16 +270,14 @@ public class SSOContainerUtils {
}
- public Response validateReceivedSSOContainer(String signedEncryptedContainer) throws IOException, XMLParserException, UnmarshallingException, MOAIDException {
- byte[] base64decodedContainer = Base64Utils.decode(signedEncryptedContainer, false);
-
+ public Response validateReceivedSSOContainer(String signedEncryptedContainer) throws IOException, XMLParserException, UnmarshallingException, MOAIDException {
final BasicParserPool ppMgr = new BasicParserPool();
final HashMap<String, Boolean> features = new HashMap<String, Boolean>();
features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
ppMgr.setBuilderFeatures(features);
ppMgr.setNamespaceAware(true);
- Document document = ppMgr.parse(new ByteArrayInputStream(base64decodedContainer));
+ Document document = ppMgr.parse(new ByteArrayInputStream(signedEncryptedContainer.getBytes()));
Element domElement = document.getDocumentElement();
UnmarshallerFactory saml2UnmarshallerFactory = Configuration.getUnmarshallerFactory();
@@ -317,8 +316,8 @@ public class SSOContainerUtils {
samlVerificationEngine.validateAssertion(ssoContainer, false,
credentials.getIDPAssertionEncryptionCredential(),
ssoContainer.getIssuer().getValue(),
- "SSO-Session Transfer module"
- );
+ "SSO-Session Transfer module",
+ false);
return ssoContainer;
} else {
@@ -369,7 +368,7 @@ public class SSOContainerUtils {
IAuthData authData = new SSOTransferAuthenticationData(authConfig, authSession);
Assertion assertion = PVP2AssertionBuilder.buildGenericAssertion(
- authURL,
+ entityID,
entityID,
new DateTime(date.getTime()),
authnContextClassRef,
@@ -380,7 +379,7 @@ public class SSOContainerUtils {
subjectConfirmationData.getNotOnOrAfter());
//build blob with signed session information
- String ssoDataBlob = buildSSOContainerObject(authURL, assertion, new DateTime(date.getTime()));
+ String ssoDataBlob = buildSSOContainerObject(entityID, assertion, new DateTime(date.getTime()));
Logger.debug("Unencrypted SessionBlob:" + ssoDataBlob);
//encrypt session information with ephemeral key
@@ -394,8 +393,10 @@ public class SSOContainerUtils {
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_VALIDTO, subjectConfirmationData.getNotOnOrAfter().toString());
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_ENTITYID, entityID);
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_USERID, authData.getGivenName() + " " + authData.getFamilyName());
-
+
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_SESSION, encAndEncodedPersonalData);
+ container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_UNIQUEUSERID,
+ BpkUtil.calcBPK(authData.getIdentificationValue(), "AB"));
//TODO
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_RESULTENDPOINT, "https://demo.egiz.gv.at");
@@ -447,13 +448,13 @@ public class SSOContainerUtils {
}
- private String buildSSOContainerObject(String authURL, Assertion assertion, DateTime date) throws ConfigurationException, EncryptionException, CredentialsNotAvailableException, SecurityException, ParserConfigurationException, MarshallingException, SignatureException, TransformerFactoryConfigurationError, TransformerException, IOException {
+ private String buildSSOContainerObject(String entityID, Assertion assertion, DateTime date) throws ConfigurationException, EncryptionException, CredentialsNotAvailableException, SecurityException, ParserConfigurationException, MarshallingException, SignatureException, TransformerFactoryConfigurationError, TransformerException, IOException {
Response authResponse = SAML2Utils.createSAMLObject(Response.class);
Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
//change to entity value from entity name to IDP EntityID (URL)
- nissuer.setValue(authURL);
+ nissuer.setValue(entityID);
nissuer.setFormat(NameID.ENTITY);
authResponse.setIssuer(nissuer);
@@ -541,7 +542,7 @@ public class SSOContainerUtils {
Logger.info("SSO-Transfer attribute " + el + " is empty!");
} catch (Exception e) {
- Logger.warn("Build SSO-Transfer attribute " + el + " FAILED.", e);
+ Logger.info("Build SSO-Transfer attribute " + el + " FAILED:" + e.getMessage());
}
}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java b/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java
index 57f4d11ad..0eb71ec92 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java
@@ -22,6 +22,10 @@
*/
package at.gv.egiz.tests;
+import com.google.gson.JsonObject;
+
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants;
+
/**
* @author tlenz
*
@@ -53,6 +57,19 @@ public class Tests {
+ JsonObject responseMsg = new JsonObject();
+ responseMsg.addProperty(
+ SSOTransferConstants.SSOCONTAINER_KEY_STATUS,
+ "OK");
+
+
+ JsonObject levelTwo = new JsonObject();
+ levelTwo.addProperty("test", "12345");
+
+ responseMsg.add("levelTwo", levelTwo );
+
+
+ System.out.println(responseMsg.toString());
// } catch (IOException e) {
// // TODO Auto-generated catch block