aboutsummaryrefslogtreecommitdiff
path: root/id/server
diff options
context:
space:
mode:
Diffstat (limited to 'id/server')
-rw-r--r--id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html18
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java4
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java61
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java36
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java125
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java42
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java75
7 files changed, 258 insertions, 103 deletions
diff --git a/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html b/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html
index e9c2fae76..c76e75d64 100644
--- a/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html
+++ b/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html
@@ -3,17 +3,33 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<!-- MOA-ID 2.x BKUSelection Layout CSS -->
- <link rel="stylesheet" href="#CONTEXTPATH#/css/buildCSS" />
+ <link rel="stylesheet" href="$contextPath/css/buildCSS" />
+
+ #if($timeoutURL)
+ <script type="text/javascript">
+ function sloTimeOut() {
+ window.location.href="$timeoutURL";
+
+ }
+
+ </script>
+ #end
<title>Single Sign-On Session Transfer</title>
</head>
+#if($timeoutURL)
+ <body onload='setTimeout(sloTimeOut, $timeout);'>
+#else
<body>
+#end
<noscript>
<p>
<strong>Note:</strong> Since your browser does not support
JavaScript, you must press the Continue button once to proceed.
</p>
+
+ <a href="$timeoutURL">Press this link to resume</a>
</noscript>
<div id="page">
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 ce3a7856b..1ee715afa 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
@@ -58,8 +58,12 @@ public class SSOTransferConstants {
public static final String SSOCONTAINER_KEY_USERID = "userID";
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 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 2bb31f700..7cf7c914a 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
@@ -30,13 +30,9 @@ import java.io.PrintWriter;
import java.math.BigInteger;
import java.net.URL;
import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
@@ -46,11 +42,9 @@ import java.util.Date;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
-import javax.crypto.spec.SecretKeySpec;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
import javax.servlet.http.HttpServletRequest;
@@ -467,7 +461,7 @@ public class SSOTransferServlet{
DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,
container.getDhParams().getF().getP(),
container.getDhParams().getF().getG());
- byte[] sharedSecret = getSecret(mobilePubKeySpec, container.getDhParams().getS());
+ byte[] sharedSecret = ssoTransferUtils.getSecret(mobilePubKeySpec, container.getDhParams().getS());
//build ASE256 key
MessageDigest digest = MessageDigest.getInstance("SHA-256");
@@ -479,7 +473,7 @@ public class SSOTransferServlet{
byte[] encryptedCSR = Base64Utils.decode(mobileCSRBase64, true);
Logger.debug("EncCSR:" + Base64Utils.encode(encryptedCSR) + " | Key:" + Base64Utils.encode(hashedSecret));
- byte[] decryptedCSR = enOrDeCryptCSR(encryptedCSR, hashedSecret, Cipher.DECRYPT_MODE);
+ byte[] decryptedCSR = ssoTransferUtils.enOrDeCryptCSR(encryptedCSR, hashedSecret, Cipher.DECRYPT_MODE);
Logger.debug("DecCSR:" + Base64Utils.encode(decryptedCSR));
Logger.debug("CSR decryption finished. --> Starting CSR validation and signing ...");
@@ -496,18 +490,16 @@ public class SSOTransferServlet{
Date now = new Date();
String personInformationToTransfer =
ssoTransferUtils.generateSignedAndEncryptedSSOContainer(
- container.getAuthURL(), moaSession, now);
+ container.getAuthURL(), moaSession, now, hashedSecret);
Logger.debug("PersonData:" + personInformationToTransfer);
//encrypt personal information
Logger.debug("PersonData generation finished. --> Starting personData encryption ... ");
- byte[] encPersonData = enOrDeCryptCSR(personInformationToTransfer.getBytes(), hashedSecret, Cipher.ENCRYPT_MODE);
- String encAndEncodedPersonalData = Base64Utils.encode(encPersonData);
Logger.debug("Encrypt personData finished. --> Send token to device.");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = new PrintWriter(resp.getOutputStream());
- out.print(encAndEncodedPersonalData);
+ out.print(personInformationToTransfer);
out.flush();
return;
@@ -539,7 +531,7 @@ public class SSOTransferServlet{
BigInteger generator = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_GENERATOR_BASE64, false));
DHParameterSpec dhSpec = new DHParameterSpec(prime, generator, 1024);
- Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = createSpecificKey(dhSpec.getP(), dhSpec.getG());
+ Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = ssoTransferUtils.createSpecificKey(dhSpec.getP(), dhSpec.getG());
container.setDhParams(dhKeyIDP);
//store container
@@ -575,17 +567,7 @@ public class SSOTransferServlet{
guiBuilder.build(resp, config, "SSO-Session Transfer-Module");
}
-
- public byte[] enOrDeCryptCSR(byte[] binBlob, byte[] binSecret, int mode) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
- byte[] decrypted = null;
- SecretKeySpec skeySpec = new SecretKeySpec(binSecret, "AES");
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(mode, skeySpec);
- decrypted = cipher.doFinal(binBlob);
-
- return decrypted;
- }
-
+
private X509Certificate signCSRWithMOAKey(byte[] inputCSR) throws IOException, OperatorCreationException, PKCSException, CredentialsNotAvailableException, CertificateException {
PKCS10CertificationRequest csr = new PKCS10CertificationRequest(inputCSR);
@@ -613,20 +595,7 @@ public class SSOTransferServlet{
}
-
- private static byte[] getSecret(DHPublicKeySpec kspectrans, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
- KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman");
- aKeyAgree.init(privateKey);
-
- KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");
- PublicKey pub = kfactory.generatePublic(kspectrans);
- aKeyAgree.doPhase(pub, true);
-
- byte[] secretKey = aKeyAgree.generateSecret();
- return secretKey;
-
- }
-
+
private JsonObject getJSONObjectFromPostMessage(HttpServletRequest req, boolean developmentMode) {
//read POST request
StringBuffer sb = new StringBuffer();
@@ -662,20 +631,4 @@ public class SSOTransferServlet{
}
- private Pair<DHPublicKeySpec, PrivateKey> createSpecificKey(BigInteger p, BigInteger g) throws Exception {
- KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman");
-
- DHParameterSpec param = new DHParameterSpec(p, g);
- kpg.initialize(param);
- KeyPair kp = kpg.generateKeyPair();
-
- KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");
-
- Pair<DHPublicKeySpec, PrivateKey> pair = new Pair<DHPublicKeySpec, PrivateKey>(
- (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class), kp.getPrivate());
- return pair;
-
- }
-
-
}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java
index e3c8efb50..be27de9a1 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java
@@ -22,6 +22,11 @@
*/
package at.gv.egovernment.moa.id.auth.modules.ssotransfer.task;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -31,12 +36,18 @@ import org.springframework.stereotype.Component;
import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;
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.ssotransfer.SSOTransferConstants;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.Pair;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferContainer;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.GUIUtils;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.SSOContainerUtils;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.id.util.HTTPUtils;
+import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Base64Utils;
/**
* @author tlenz
@@ -46,6 +57,7 @@ import at.gv.egovernment.moa.logging.Logger;
public class InitializeRestoreSSOSessionTask extends AbstractAuthServletTask {
@Autowired IGUIFormBuilder guiBuilder;
+ @Autowired SSOContainerUtils ssoTransferUtils;
/* (non-Javadoc)
* @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
@@ -64,10 +76,30 @@ public class InitializeRestoreSSOSessionTask extends AbstractAuthServletTask {
response.sendError(500, "Requested URL is not allowed.");
}
-
- GUIUtils.buildSSOTransferGUI(guiBuilder, response, authURL, pendingReq.getRequestID());
+
+ //use predefined parameters
+ BigInteger prime = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_PRIME_BASE64, false));
+ BigInteger generator = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_GENERATOR_BASE64, false));
+ DHParameterSpec dhSpec = new DHParameterSpec(prime, generator, 1024);
+
+ Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = ssoTransferUtils.createSpecificKey(dhSpec.getP(), dhSpec.getG());
+ String nonce = Random.nextLongRandom();
+ GUIUtils.buildSSOTransferGUI(guiBuilder, response, authURL,
+ pendingReq.getRequestID(), nonce, dhKeyIDP.getF());
+ //store DH params and nonce to pending-request
+ SSOTransferContainer container = new SSOTransferContainer();
+ container.setDhParams(dhKeyIDP);
+ pendingReq.setGenericDataToSession(SSOTransferConstants.PENDINGREQ_DH, container);
+ pendingReq.setGenericDataToSession(SSOTransferConstants.PENDINGREQ_NONCE, nonce);
+
+ //store pending-request
+ requestStoreage.storePendingRequest(pendingReq);
+
+ //set flag
+ executionContext.put("sessionRestoreFinished", false);
+
} catch (MOAIDException e) {
throw new TaskExecutionException(pendingReq, e.getMessage(), e);
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 526f45be3..6d9b43e5b 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,12 +24,15 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.task;
import java.io.BufferedReader;
import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import javax.crypto.Cipher;
+import javax.crypto.spec.DHPublicKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.BooleanUtils;
-import org.apache.velocity.VelocityContext;
import org.joda.time.DateTime;
import org.opensaml.saml2.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
@@ -42,16 +45,20 @@ import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;
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.ssotransfer.SSOTransferConstants;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferContainer;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.GUIUtils;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.SSOContainerUtils;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
-import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;
import at.gv.egovernment.moa.id.util.HTTPUtils;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.MiscUtil;
+import iaik.x509.X509Certificate;
/**
* @author tlenz
@@ -100,6 +107,14 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
}
+ 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);
+
+ }
+
if (MiscUtil.isNotEmpty(receivedPostMessage)) {
Logger.debug("Receive POST-Message data. Start data-validation process ... ");
@@ -109,40 +124,81 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
JsonObject reveivedSession = reveivedData.get("session").getAsJsonObject();
String validTo = reveivedSession.get("validTo").getAsString();
String entityID = reveivedSession.get("entityID").getAsString();
- String sessionBlob = reveivedSession.get("sessionBlob").getAsString();
+ //String sessionBlob = reveivedSession.get("sessionBlob").getAsString();
+
+// Logger.trace("Blob:" + sessionBlob +
+// " | validTo:" + validTo +
+// " | entityIS:" + entityID);
+
+
+ //TODO!!!!
+ String mobilePubKeyBase64 = reveivedSession.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();
+ String encSessionBlobBase64 = new String();
- Logger.trace("Blob:" + sessionBlob +
- " | validTo:" + validTo +
- " | entityIS:" + entityID);
+ Logger.debug("Receive PubKey:" +mobilePubKeyBase64 + " | SessionBlob:" + encSessionBlobBase64);
+
+ //finish DH key agreement
+ BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, true));
+ DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,
+ container.getDhParams().getF().getP(),
+ container.getDhParams().getF().getG());
+ byte[] sharedSecret = ssoTransferUtils.getSecret(mobilePubKeySpec, container.getDhParams().getS());
+
+ //build ASE256 key
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ digest.reset();
+ byte[] hashedSecret = digest.digest(sharedSecret);
+
+ //decrypt CSR
+ Logger.debug("Finished Diffie-Hellman key exchange. --> Starting SessionBlob decryption ...");
+ byte[] encryptedSessionBlob = Base64Utils.decode(encSessionBlobBase64, true);
+ Logger.debug("EncSessionBlob:" + Base64Utils.encode(encryptedSessionBlob) + " | Key:" + Base64Utils.encode(hashedSecret));
+
+ byte[] sessionBlobArray = ssoTransferUtils.enOrDeCryptCSR(encryptedSessionBlob, hashedSecret, Cipher.DECRYPT_MODE);
+ String sessionBlob = new String(sessionBlobArray, "UTF-8");
+ Logger.debug("DecSessionBlob:" + sessionBlob);
- if (PVPConfiguration.getInstance().getIDPPublicPath().contains(entityID)) {
- // stored SSO session data is from this IDP - start local session reconstruction
- Response ssoInformation = ssoTransferUtils.validateReceivedSSOContainer(sessionBlob, entityID);
-
- //transfer SSO Assertion into MOA-Session
- ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, ssoInformation);
-
- // store MOASession into database
- try {
- authenticatedSessionStorage.storeSession(moasession);
-
- } catch (MOADatabaseException e) {
- Logger.error("Database Error! MOASession is not stored!");
- throw new MOAIDException("init.04", new Object[] {
- moasession.getSessionID()});
- }
-
- executionContext.put(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED, true);
- executionContext.put("sessionRestoreFinished", false);
-
- } else {
- Logger.info("Received SSO session-data is from IDP: " + entityID
- + ". Start inderfederation process to restore SSO session ... ");
- //change to inderfederated session reconstruction
-
- Logger.warn("Device Session Transfer with interfederation is not implemented, yet!!!!");
+ //parse SAML2 assertion
+ Response ssoInformation = ssoTransferUtils.validateReceivedSSOContainer(sessionBlob);
+
+ //validate signature
+ AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation);
+ String holderOfKeyCertBase64 = attributeExtractor.getSingleAttributeValue(PVPConstants.PVP_HOLDEROFKEY_NAME);
+ byte[] holderOfKeyCertEncoded = Base64Utils.decode(holderOfKeyCertBase64, false);
+ X509Certificate holderOfKeyCert = new X509Certificate(holderOfKeyCertEncoded);
+ Logger.debug("Found HolderOfKey Certificate:" + holderOfKeyCert.getSubjectDN().toString());
+
+
+ //TODO: implement Signature validation
+
+ Logger.debug("MobileDevice is valid. --> Starting session reconstruction ...");
+
+
+ //transfer SSO Assertion into MOA-Session
+ ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, attributeExtractor);
+
+ // store MOASession into database
+ try {
+ authenticatedSessionStorage.storeSession(moasession);
+
+ } catch (MOADatabaseException e) {
+ Logger.error("Database Error! MOASession is not stored!");
+ throw new MOAIDException("init.04", new Object[] {
+ moasession.getSessionID()});
+ }
+
+ executionContext.put(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED, true);
+ executionContext.put("sessionRestoreFinished", false);
+
+
+// Logger.info("Received SSO session-data is from IDP: " + entityID
+// + ". Start inderfederation process to restore SSO session ... ");
+// //change to inderfederated session reconstruction
+//
+// Logger.warn("Device Session Transfer with interfederation is not implemented, yet!!!!");
- }
+
} catch (Exception e) {
Logger.error("Parse reveived JSON data-object " + sb.toString() + " FAILED!", e);
@@ -171,7 +227,6 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
Logger.debug("No restored SSO session found --> Wait a few minutes and check again.");
executionContext.put("sessionRestoreFinished", false);
- VelocityContext context;
try {
//create first step of SSO Transfer GUI
authURL = HTTPUtils.extractAuthURLFromRequest(request);
@@ -183,7 +238,7 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {
}
GUIUtils.buildSSOTransferGUI(guiBuilder, response,
- authURL, pendingReq.getRequestID());
+ authURL, pendingReq.getRequestID(), nonce, container.getDhParams().getF());
} catch (IOException | MOAIDException e) {
throw new TaskExecutionException(pendingReq, e.getMessage(), e);
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java
index b1446c4d2..13a278d1d 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java
@@ -25,6 +25,7 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import javax.crypto.spec.DHPublicKeySpec;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.JsonObject;
@@ -37,6 +38,7 @@ import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Base64Utils;
+import at.gv.egovernment.moa.util.MiscUtil;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
@@ -50,18 +52,50 @@ public class GUIUtils {
public static void buildSSOTransferGUI(
IGUIFormBuilder guiBuilder, HttpServletResponse httpResp,
String authURL, String pendingReqID) throws ConfigurationException, IOException {
+ buildSSOTransferGUI(guiBuilder, httpResp, authURL, pendingReqID, null, null);
+
+ }
+
+ /**
+ * @param guiBuilder
+ * @param response
+ * @param authURL
+ * @param requestID
+ * @param nonce
+ * @param dhKeyIDP
+ * @throws ConfigurationException
+ * @throws IOException
+ */
+ public static void buildSSOTransferGUI(IGUIFormBuilder guiBuilder, HttpServletResponse response, String authURL,
+ String requestID, String nonce, DHPublicKeySpec dhKeyIDP) throws ConfigurationException, IOException {
try {
String containerURL = authURL
+ SSOTransferConstants.SERVLET_SSOTRANSFER_FROM_SMARTPHONE
- + "?" + MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingReqID;
+ + "?" + MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID + "=" + requestID;
+
+
+
JsonObject qrResult = new JsonObject();
qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE,
SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_TRANSER);
qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_URL, containerURL);
+
+ if (MiscUtil.isNotEmpty(nonce))
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_NONCE, nonce);
+ if (dhKeyIDP != null) {
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY,
+ Base64Utils.encode(dhKeyIDP.getY().toByteArray()));
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PRIME,
+ Base64Utils.encode(dhKeyIDP.getP().toByteArray()));
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_GENERATOR,
+ Base64Utils.encode(dhKeyIDP.getG().toByteArray()));
+
+ }
+
ByteArrayOutputStream qrStream =
- QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(300, 300).stream();
+ QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(350, 350).stream();
String base64EncodedImage = Base64Utils.encode(qrStream.toByteArray());
DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration(
@@ -74,13 +108,13 @@ public class GUIUtils {
config.putCustomParameter("timeoutURL", containerURL);
config.putCustomParameter("timeout", REFESH_TIMEOUT);
- guiBuilder.build(httpResp, config, "SSO-Transfer-Module");
+ guiBuilder.build(response, config, "SSO-Transfer-Module");
} catch (GUIBuildException e) {
Logger.warn("Can not build GUI:'BKU-Selection'. Msg:" + e.getMessage(), e);
throw new ConfigurationException("builder.09", new Object[]{e.getMessage()}, e);
}
-
+
}
}
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 9683d5cb7..ab0aba6a7 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
@@ -25,14 +25,31 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.cert.CertificateException;
+import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyAgreement;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.crypto.spec.SecretKeySpec;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -83,6 +100,7 @@ import com.google.gson.JsonObject;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.exception.ParseException;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.Pair;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferAuthenticationData;
import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferOnlineApplication;
import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
@@ -149,8 +167,8 @@ public class SSOContainerUtils {
@Autowired SAMLVerificationEngineSP samlVerificationEngine;
@Autowired AuthConfiguration authConfig;
- public void parseSSOContainerToMOASessionDataObject(IRequest pendingReq, AuthenticationSession moasession, Response ssoInformation) throws AssertionAttributeExtractorExeption, ConfigurationException {
- AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation);
+ public void parseSSOContainerToMOASessionDataObject(IRequest pendingReq, AuthenticationSession moasession, AssertionAttributeExtractor attributeExtractor) throws AssertionAttributeExtractorExeption, ConfigurationException {
+// AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation);
//TODO: maybe change to correct URL
//set dummy BKU URLx
@@ -251,7 +269,7 @@ public class SSOContainerUtils {
}
- public Response validateReceivedSSOContainer(String signedEncryptedContainer, String entityID) throws IOException, XMLParserException, UnmarshallingException, MOAIDException {
+ public Response validateReceivedSSOContainer(String signedEncryptedContainer) throws IOException, XMLParserException, UnmarshallingException, MOAIDException {
byte[] base64decodedContainer = Base64Utils.decode(signedEncryptedContainer, false);
final BasicParserPool ppMgr = new BasicParserPool();
@@ -298,7 +316,7 @@ public class SSOContainerUtils {
//validate PVP 2.1 assertion
samlVerificationEngine.validateAssertion(ssoContainer, false,
credentials.getIDPAssertionEncryptionCredential(),
- entityID,
+ ssoContainer.getIssuer().getValue(),
"SSO-Session Transfer module"
);
return ssoContainer;
@@ -319,7 +337,7 @@ public class SSOContainerUtils {
public String generateSignedAndEncryptedSSOContainer(String authURL,
- AuthenticationSession authSession, Date date) {
+ AuthenticationSession authSession, Date date, byte[] hashedSecret) {
try {
String entityID = PVPConfiguration.getInstance().getIDPSSOMetadataService(authURL);
AuthnContextClassRef authnContextClassRef = SAML2Utils
@@ -363,25 +381,68 @@ public class SSOContainerUtils {
String ssoDataBlob = buildSSOContainerObject(authURL, assertion, new DateTime(date.getTime()));
+ byte[] encPersonData = enOrDeCryptCSR(ssoDataBlob.getBytes(), hashedSecret, Cipher.ENCRYPT_MODE);
+ String encAndEncodedPersonalData = Base64Utils.encode(encPersonData);
+
+
JsonObject container = new JsonObject();
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE, SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_SSO);
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, ssoDataBlob);
+
+ container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_SESSION, encAndEncodedPersonalData);
//TODO
container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_RESULTENDPOINT, "https://demo.egiz.gv.at");
return container.toString();
- } catch (ConfigurationException | EncryptionException | CredentialsNotAvailableException | SecurityException | ParserConfigurationException | MarshallingException | SignatureException | TransformerFactoryConfigurationError | TransformerException | IOException e) {
+ } catch (ConfigurationException | EncryptionException | CredentialsNotAvailableException | SecurityException | ParserConfigurationException | MarshallingException | SignatureException | TransformerFactoryConfigurationError | TransformerException | IOException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchPaddingException e) {
Logger.warn("SSO container generation FAILED.", e);
}
return null;
}
+ public byte[] enOrDeCryptCSR(byte[] binBlob, byte[] binSecret, int mode) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
+ byte[] decrypted = null;
+ SecretKeySpec skeySpec = new SecretKeySpec(binSecret, "AES");
+ Cipher cipher = Cipher.getInstance("AES");
+ cipher.init(mode, skeySpec);
+ decrypted = cipher.doFinal(binBlob);
+
+ return decrypted;
+ }
+
+ public Pair<DHPublicKeySpec, PrivateKey> createSpecificKey(BigInteger p, BigInteger g) throws Exception {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman");
+
+ DHParameterSpec param = new DHParameterSpec(p, g);
+ kpg.initialize(param);
+ KeyPair kp = kpg.generateKeyPair();
+
+ KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");
+
+ Pair<DHPublicKeySpec, PrivateKey> pair = new Pair<DHPublicKeySpec, PrivateKey>(
+ (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class), kp.getPrivate());
+ return pair;
+
+ }
+
+ public byte[] getSecret(DHPublicKeySpec kspectrans, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
+ KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman");
+ aKeyAgree.init(privateKey);
+
+ KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");
+ PublicKey pub = kfactory.generatePublic(kspectrans);
+ aKeyAgree.doPhase(pub, true);
+
+ byte[] secretKey = aKeyAgree.generateSecret();
+ return secretKey;
+
+ }
+
private String buildSSOContainerObject(String authURL, Assertion assertion, DateTime date) throws ConfigurationException, EncryptionException, CredentialsNotAvailableException, SecurityException, ParserConfigurationException, MarshallingException, SignatureException, TransformerFactoryConfigurationError, TransformerException, IOException {
Response authResponse = SAML2Utils.createSAMLObject(Response.class);