aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2016-03-01 10:13:50 +0100
committerThomas Lenz <tlenz@iaik.tugraz.at>2016-03-01 10:13:50 +0100
commite9d885d2dbcfa2234bfa3b1db701c3956278624d (patch)
treee3e7a512633346f6c74bc267f721f052e5bd5245 /id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment
parent116263de6a4043fd217ea12f73f0b08db90f1935 (diff)
downloadmoa-id-spss-e9d885d2dbcfa2234bfa3b1db701c3956278624d.tar.gz
moa-id-spss-e9d885d2dbcfa2234bfa3b1db701c3956278624d.tar.bz2
moa-id-spss-e9d885d2dbcfa2234bfa3b1db701c3956278624d.zip
update SSO-transfer-modul for new mobile app
Diffstat (limited to 'id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment')
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java12
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/Pair.java21
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java5
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferContainer.java107
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java537
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java60
6 files changed, 651 insertions, 91 deletions
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 03f3fcdab..cc60bbd20 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
@@ -28,6 +28,11 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer;
*/
public class SSOTransferConstants {
+ public static final String MOASESSION_DATA_HOLDEROFKEY_CERTIFICATE = "holderofkey_cert";
+
+ public static final String DH_PRIME_BASE64 = "AO672PgS9gv0vLTDDISxnZ61aroRrvj53F4CX1ffNNdU+PYPv6ff3pkmuaw3av41tpD/Y0ypcCEPLh39GemNDUnehwBfi6PocHdDGPhTvhan5kYgDoWPWebA9P3Qy3eUdslwU+Eusr0SBhN+Cssw7XZ0nue5IiOjBxdzdijJiojH";
+ public static final String DH_GENERATOR_BASE64 = "NuuDqMxQa7T3XP4H6OFR30imozmM0Eho0na9gXak+Qs+J9uE/3xgHspz9PYO/6Lk2wgeOk42Pk4MHamKVPCLdqztlmEFgKPwHiAwNdNr4PklonLWk5zPSEYDVUt/8IFmK+cu0cPomACo0AfSCSZqdexq0FnFey/5mBjOGPimOJQ=";
+
public static final String SERVLET_SSOTRANSFER_GUI = "/TransferSSOSession";
public static final String SERVLET_SSOTRANSFER_TO_SMARTPHONE = "/TransmitSSOSession";
public static final String SERVLET_SSOTRANSFER_FROM_SMARTPHONE = "/SSOTransferSignalEndpoint";
@@ -41,6 +46,12 @@ public class SSOTransferConstants {
public static final String SSOCONTAINER_KEY_URL = "url";
+ public static final String SSOCONTAINER_KEY_DH_PUBKEY = "pubKey";
+ public static final String SSOCONTAINER_KEY_DH_PRIME = "prime";
+ public static final String SSOCONTAINER_KEY_DH_GENERATOR = "generator";
+
+ public static final String SSOCONTAINER_KEY_CSR = "csr";
+
public static final String SSOCONTAINER_KEY_VALIDTO = "validTo";
public static final String SSOCONTAINER_KEY_ENTITYID = "entityID";
public static final String SSOCONTAINER_KEY_USERID = "userID";
@@ -48,5 +59,6 @@ public class SSOTransferConstants {
public static final String SSOCONTAINER_KEY_RESULTENDPOINT = "resultEndPoint";
public static final String FLAG_SSO_SESSION_RESTORED = "ssoRestoredFlag";
+ public static final long CERT_VALIDITY = 700; //2 years
}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/Pair.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/Pair.java
new file mode 100644
index 000000000..47351b2bd
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/Pair.java
@@ -0,0 +1,21 @@
+package at.gv.egovernment.moa.id.auth.modules.ssotransfer.data;
+
+import java.io.Serializable;
+
+public class Pair<F,S> implements Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1677989418252218345L;
+
+ private F l;
+ private S r;
+ public Pair(F l, S r){
+ this.l = l;
+ this.r = r;
+ }
+ public F getF(){ return l; }
+ public S getS(){ return r; }
+ public void setF(F l){ this.l = l; }
+ public void setS(S r){ this.r = r; }
+}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java
index b9ab4f307..17e88e381 100644
--- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java
@@ -375,9 +375,8 @@ public class SSOTransferAuthenticationData implements IAuthData {
* @see at.gv.egovernment.moa.id.data.IAuthData#getGenericData(java.lang.String, java.lang.Class)
*/
@Override
- public <T> T getGenericData(String key, Class<T> clazz) {
- // TODO Auto-generated method stub
- return null;
+ public <T> T getGenericData(String key, Class<T> clazz) {
+ return this.authSession.getGenericDataFromSession(key, clazz);
}
}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferContainer.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferContainer.java
new file mode 100644
index 000000000..eecf03b71
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferContainer.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014 Federal Chancellery Austria
+ * MOA-ID has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egovernment.moa.id.auth.modules.ssotransfer.data;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+import javax.crypto.spec.DHPublicKeySpec;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SSOTransferContainer implements Serializable {
+
+ private static final long serialVersionUID = 3762458954168085854L;
+
+ private String authURL = null;
+ private String tokkenID = null;
+ private String moaSessionID = null;
+
+ //DH parameters
+ private PrivateKey dh_privKey;
+ private BigInteger dh_pubKey;
+ private BigInteger dh_prime;
+ private BigInteger dh_generator;
+
+
+ /**
+ * @return the authURL
+ */
+ public String getAuthURL() {
+ return authURL;
+ }
+ /**
+ * @param authURL the authURL to set
+ */
+ public void setAuthURL(String authURL) {
+ this.authURL = authURL;
+ }
+ /**
+ * @return the tokkenID
+ */
+ public String getTokkenID() {
+ return tokkenID;
+ }
+ /**
+ * @param tokkenID the tokkenID to set
+ */
+ public void setTokkenID(String tokkenID) {
+ this.tokkenID = tokkenID;
+ }
+ /**
+ * @return the moaSessionID
+ */
+ public String getMoaSessionID() {
+ return moaSessionID;
+ }
+ /**
+ * @param moaSessionID the moaSessionID to set
+ */
+ public void setMoaSessionID(String moaSessionID) {
+ this.moaSessionID = moaSessionID;
+ }
+ /**
+ * @return the dhParams
+ */
+ public Pair<DHPublicKeySpec, PrivateKey> getDhParams() {
+ return new Pair<DHPublicKeySpec, PrivateKey>(new DHPublicKeySpec(this.dh_pubKey,
+ this.dh_prime,
+ this.dh_generator), this.dh_privKey);
+ }
+ /**
+ * @param dhParams the dhParams to set
+ */
+ public void setDhParams(Pair<DHPublicKeySpec, PrivateKey> dhParams) {
+ this.dh_privKey = dhParams.getS();
+
+ this.dh_pubKey = dhParams.getF().getY();
+ this.dh_prime = dhParams.getF().getP();
+ this.dh_generator = dhParams.getF().getG();
+ }
+
+
+
+}
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 d33b157e0..80c2663fb 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
@@ -22,37 +22,80 @@
*/
package at.gv.egovernment.moa.id.auth.modules.ssotransfer.servlet;
+import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
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.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
import java.util.Date;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.security.cert.CertificateException;
+import javax.security.cert.X509Certificate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.VelocityContext;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.pkcs.PKCSException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.ParseException;
+import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException;
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.auth.parser.IdentityLinkAssertionParser;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import at.gv.egovernment.moa.id.moduls.SSOManager;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider;
import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.storage.ITransactionStorage;
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;
+import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.MiscUtil;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
@@ -73,28 +116,181 @@ public class SSOTransferServlet{
@Autowired IAuthenticationSessionStoreage authenticationSessionStorage;
@Autowired SSOContainerUtils ssoTransferUtils;
@Autowired ITransactionStorage transactionStorage;
+ @Autowired IDPCredentialProvider idpCredentials;
+ @Autowired AuthConfiguration authConfig;
public SSOTransferServlet() {
super();
Logger.debug("Registering servlet " + getClass().getName()
- + " with mapping {'/TransferSSOSession','/TransmitSSOSession'}.");
+ + " with mapping {'/TransferSSOSession','/TransmitSSOSession'}"
+ + " Development-EndPoints: {'/TestTransferSSOSession','/TestTransmitSSOSession'}.");
}
+ /**
+ * Only for development and debugging
+ * This methode create template QR and for the template service
+ *
+ * @param req
+ * @param resp
+ * @throws IOException
+ */
+ @RequestMapping(value = { "/TestTransferSSOSession"
+ },
+ method = {RequestMethod.GET})
+ public void testTransferSSOSessionGUIWithoutAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ try {
+ VelocityContext context = new VelocityContext();
+
+ //create first step of SSO Transfer GUI
+ String authURL = HTTPUtils.extractAuthURLFromRequest(req);
+ if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().contains(authURL)) {
+ Logger.warn("Requested URL is not allowed.");;
+ resp.sendError(500, "Requested URL is not allowed.");
+
+ }
+
+ internalCreateQRCodeForTransfer(resp, authURL,
+ "123456", "/TestTransmitSSOSession", context);
+
+ } catch (MOAIDException | MOADatabaseException e) {
+ e.printStackTrace();
+ resp.sendError(500, e.getMessage());
+
+ } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
+ e.printStackTrace();
+ resp.sendError(500, e.getMessage());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ resp.sendError(500, e.getMessage());
+ }
+ }
+
+ /**
+ * Only for development and debugging
+ * This methode transfer personal information to smartphone
+ *
+ * @param req
+ * @param resp
+ * @throws IOException
+ */
+ @RequestMapping(value = { "/TestTransmitSSOSession"
+ },
+ method = {RequestMethod.GET, RequestMethod.POST})
+ public void testTransferToPhone(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ Logger.debug("Receive " + this.getClass().getName() + " request");
+ Object tokenObj = req.getParameter(SSOTransferConstants.REQ_PARAM_TOKEN);
+ if (tokenObj != null && tokenObj instanceof String) {
+ String token = (String)tokenObj;
+ try {
+ SSOTransferContainer container = transactionStorage.get(token, SSOTransferContainer.class, transmisionTimeOut * 1000);
+ if (container != null) {
+ AuthenticationSession moaSession = new AuthenticationSession("123456", new Date());
+
+ URL idlURL = new URL(FileUtils.makeAbsoluteURL(
+ authConfig.getMonitoringTestIdentityLinkURL(),
+ authConfig.getRootConfigFileDir()));
+ InputStream idlstream = idlURL.openStream();
+ moaSession.setIdentityLink(new IdentityLinkAssertionParser(idlstream).parseIdentityLink());
+ internalTransferPersonalInformation(req, resp, container, moaSession, true);
+
+ } else {
+ Logger.info("Servlet " + getClass().getName() + " receive a token:" +
+ token + ", which references an empty data object.");
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Empty data object.");
+
+ }
+
+ } catch (MOADatabaseException e) {
+ Logger.info("Servlet " + getClass().getName() + " receive a token:" +
+ token + ", which is UNKNOWN.");
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Transfer token is UNKOWN:");
+
+
+ } catch (AuthenticationException e) {
+ Logger.info("Servlet " + getClass().getName() + " receive a token:" +
+ token + ", which has a timeout.");
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Single Sign-On session transfer token is not valid any more.");
+
+ } catch (OperatorCreationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CredentialsNotAvailableException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (PKCSException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeyException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeySpecException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (SessionDataStorageException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ } catch (ParseException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+
+ } else {
+ Logger.info("Servlet " + getClass().getName() + " receive a NOT valid request.");
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Request not valid.");
+
+ }
+
+ }
+
+
@RequestMapping(value = { "/TransmitSSOSession"
},
method = {RequestMethod.GET})
public void transferToPhone(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ Logger.debug("Receive " + this.getClass().getName() + " request");
+
Object tokenObj = req.getParameter(SSOTransferConstants.REQ_PARAM_TOKEN);
if (tokenObj != null && tokenObj instanceof String) {
String token = (String)tokenObj;
- try {
- String signedEncSession = transactionStorage.get(token, String.class, transmisionTimeOut);
- if (MiscUtil.isNotEmpty(signedEncSession)) {
- resp.setContentType("text/html;charset=UTF-8");
- PrintWriter out = new PrintWriter(resp.getOutputStream());
- out.print(signedEncSession);
- out.flush();
-
+ try {
+ SSOTransferContainer container = transactionStorage.get(token, SSOTransferContainer.class, transmisionTimeOut);
+ if (container != null) {
+ AuthenticationSession moaSession = authenticationSessionStorage.getSession(container.getMoaSessionID());
+ if (moaSession != null) {
+ internalTransferPersonalInformation(req, resp, container, moaSession, false);
+
+
+ } else {
+ Logger.info("Servlet " + getClass().getName() + " receive a token:" +
+ token + ", but the corresponding MOASession is empty");
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No MOASession.");
+
+ }
+
} else {
Logger.info("Servlet " + getClass().getName() + " receive a token:" +
token + ", which references an empty data object.");
@@ -113,7 +309,47 @@ public class SSOTransferServlet{
token + ", which has a timeout.");
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Single Sign-On session transfer token is not valid any more.");
+ } catch (OperatorCreationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CredentialsNotAvailableException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (PKCSException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeyException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeySpecException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (SessionDataStorageException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
+
+
} else {
Logger.info("Servlet " + getClass().getName() + " receive a NOT valid request.");
@@ -127,7 +363,7 @@ public class SSOTransferServlet{
@RequestMapping(value = { "/TransferSSOSession"
},
- method = {RequestMethod.GET})
+ method = {RequestMethod.GET, RequestMethod.POST})
public void transferSSOSessionGUI(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//search SSO session
String ssoid = ssomanager.getSSOSessionID(req);
@@ -136,65 +372,254 @@ public class SSOTransferServlet{
try {
if (ssomanager.isValidSSOSession(ssoid, null)) {
- Object createQRObj = req.getParameter(SSOTransferConstants.REQ_PARAM_GENERATE_QR);
- if (createQRObj != null && createQRObj instanceof Integer) {
-
-
+ //Object createQRObj = req.getParameter(SSOTransferConstants.REQ_PARAM_GENERATE_QR);
+
+ //create first step of SSO Transfer GUI
+ String authURL = HTTPUtils.extractAuthURLFromRequest(req);
+ if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().
+ contains(authURL)) {
+ Logger.warn("Requested URL is not allowed.");;
+ resp.sendError(500, "Requested URL is not allowed.");
- } else {
- //create first step of SSO Transfer GUI
- String authURL = HTTPUtils.extractAuthURLFromRequest(req);
- if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().
- contains(authURL)) {
- Logger.warn("Requested URL is not allowed.");;
- resp.sendError(500, "Requested URL is not allowed.");
+ }
+
+ String moaSessionID = authenticationSessionStorage.getMOASessionSSOID(ssoid);
+ if (MiscUtil.isNotEmpty(moaSessionID)) {
+ AuthenticationSession authSession = authenticationSessionStorage.getSession(moaSessionID);
+ if(authSession != null) {
+ internalCreateQRCodeForTransfer(resp, authURL,
+ authSession.getSessionID(),
+ SSOTransferConstants.SERVLET_SSOTRANSFER_TO_SMARTPHONE, context);
- }
-
- String moaSessionID = authenticationSessionStorage.getMOASessionSSOID(ssoid);
- if (MiscUtil.isNotEmpty(moaSessionID)) {
- AuthenticationSession authSession = authenticationSessionStorage.getSession(moaSessionID);
- if(authSession != null) {
- Date now = new Date();
- String encodedSSOContainer = ssoTransferUtils.generateSignedAndEncryptedSSOContainer(authURL, authSession, now);
-
- String token = Random.nextRandom();
- transactionStorage.put(token, encodedSSOContainer);
-
- String containerURL = authURL
- + SSOTransferConstants.SERVLET_SSOTRANSFER_TO_SMARTPHONE
- + "?"+ SSOTransferConstants.REQ_PARAM_TOKEN + "=" + token;
-
- JsonObject qrResult = new JsonObject();
- qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE,
- SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_PERSIST);
- qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_URL, containerURL);
-
- ByteArrayOutputStream qrStream =
- QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(300, 300).stream();
- String base64EncodedImage = Base64Utils.encode(qrStream.toByteArray());
- context.put("QRImage", base64EncodedImage);
-
- context.put("successMsg", "Scan the QR-Code with your <i>SSO-Transfer App</i> to start the transfer operation.");
-
- GUIUtils.printSSOTransferGUI(context, resp);
-
- }
+ return;
}
}
- } else {
- context.put("errorMsg",
- "No active Single Sign-On session found! SSO Session transfer is not possible.");
- GUIUtils.printSSOTransferGUI(context, resp);
}
+ context.put("errorMsg",
+ "No active Single Sign-On session found! SSO Session transfer is not possible.");
+ GUIUtils.printSSOTransferGUI(context, resp);
+
} catch (MOAIDException | MOADatabaseException e) {
e.printStackTrace();
resp.sendError(500, e.getMessage());
+ } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
+ e.printStackTrace();
+ resp.sendError(500, e.getMessage());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ resp.sendError(500, e.getMessage());
+ }
+ }
+
+ private void internalTransferPersonalInformation(HttpServletRequest req, HttpServletResponse resp,
+ SSOTransferContainer container, AuthenticationSession moaSession, boolean developmentMode) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, OperatorCreationException, CredentialsNotAvailableException, PKCSException, CertificateException, SessionDataStorageException {
+ JsonObject receivedData = getJSONObjectFromPostMessage(req, developmentMode);
+
+ if (receivedData == null) {
+ Logger.warn("No data received");
+ throw new IOException("No data received");
+
}
+
+ //TODO: check if needed
+ //JsonObject reveivedSession = receivedData.get("session").getAsJsonObject();
+
+ String mobilePubKeyBase64 = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();
+ String mobileCSRBase64 = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_CSR).getAsString();
+
+ Logger.trace("Receive PubKey:" +mobilePubKeyBase64 +
+ " | CSR:" + mobileCSRBase64);
+
+ //finish DH key agreement
+ BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, false));
+ DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,
+ container.getDhParams().getF().getP(),
+ container.getDhParams().getF().getG());
+ byte[] sharedSecret = getSecret(mobilePubKeySpec, container.getDhParams().getS());
+
+ Logger.debug("Finished Diffie-Hellman key exchange. --> Starting CSR decryption ...");
+ //TODO decrypt CSR
+ byte[] decryptedCSR = Base64Utils.decode(mobileCSRBase64, true);
+
+
+ //generate certificate from CSR
+ X509Certificate mobileCert = signCSRWithMOAKey(decryptedCSR);
+
+ moaSession.setGenericDataToSession(
+ SSOTransferConstants.MOASESSION_DATA_HOLDEROFKEY_CERTIFICATE,
+ mobileCert.getEncoded());
+
+ //generate assertion
+ Date now = new Date();
+ String personInformationToTransfer =
+ ssoTransferUtils.generateSignedAndEncryptedSSOContainer(
+ container.getAuthURL(), moaSession, now);
+
+ resp.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.print(personInformationToTransfer);
+ out.flush();
+ return;
+
+ }
+
+ private void internalCreateQRCodeForTransfer(HttpServletResponse resp, String authURL,
+ String moaSessionID, String servletEndPoint, VelocityContext context) throws Exception {
+ SSOTransferContainer container = new SSOTransferContainer();
+ String token = Random.nextRandom();
+
+ container.setAuthURL(authURL);
+ container.setTokkenID(token);
+ container.setMoaSessionID(moaSessionID);
+
+ //build Diffie-Hellman parameter for Data transfer
+ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+
+ //TODO: implement worker-thread to generate new parameters every day
+ //generate new DH parameters
+ //SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG-SP80090", "IAIK");
+ //AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DiffieHellman", "BC");
+ //paramGen.init(1024, secureRandom ); // number of bits
+ //AlgorithmParameters params = paramGen.generateParameters();
+ //DHParameterSpec dhSpec = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
+ //DHParameterSpec dhSpec = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
+
+ //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 = createSpecificKey(dhSpec.getP(), dhSpec.getG());
+ container.setDhParams(dhKeyIDP);
+
+ //store container
+ transactionStorage.put(token, container);
+
+ //build QR code
+ String containerURL = authURL
+ + servletEndPoint
+ + "?"+ SSOTransferConstants.REQ_PARAM_TOKEN + "=" + token;
+
+ JsonObject qrResult = new JsonObject();
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE,
+ SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_PERSIST);
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_URL,
+ containerURL);
+
+ //add DH parameters
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY,
+ Base64Utils.encode(dhKeyIDP.getF().getY().toByteArray()));
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PRIME,
+ Base64Utils.encode(dhKeyIDP.getF().getP().toByteArray()));
+ qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_GENERATOR,
+ Base64Utils.encode(dhKeyIDP.getF().getG().toByteArray()));
+
+ ByteArrayOutputStream qrStream =
+ QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(350, 350).stream();
+ String base64EncodedImage = Base64Utils.encode(qrStream.toByteArray());
+ context.put("QRImage", base64EncodedImage);
+
+ context.put("successMsg", "Scan the QR-Code with your <i>SSO-Transfer App</i> to start the transfer operation.");
+
+ GUIUtils.printSSOTransferGUI(context, resp);
+
+
+ }
+
+ private X509Certificate signCSRWithMOAKey(byte[] inputCSR) throws IOException, OperatorCreationException, PKCSException, CredentialsNotAvailableException, CertificateException {
+ PKCS10CertificationRequest csr = new PKCS10CertificationRequest(inputCSR);
+
+ //validate CSR request
+ ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(
+ new BouncyCastleProvider()).build(csr.getSubjectPublicKeyInfo());
+ csr.isSignatureValid(verifier);
+
+ //build certificate with CSR
+ X500Name issuer = new X500Name("CN=IDP");
+ BigInteger serial = new BigInteger(32, new SecureRandom());
+ Date from = new Date();
+ Date to = new Date(System.currentTimeMillis() + (SSOTransferConstants.CERT_VALIDITY * 86400000L));
+ X509v3CertificateBuilder certgen = new X509v3CertificateBuilder(issuer, serial, from, to, csr.getSubject(), csr.getSubjectPublicKeyInfo());
+ certgen.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));
+ //certgen.addExtension(Extension.subjectKeyIdentifier, false, SubjectKeyIdentifier.getInstance(csr.getSubjectPublicKeyInfo()));
+
+ //build signer
+ ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA").build(idpCredentials.getIDPAssertionSigningCredential().getPrivateKey());
+
+ //sign certificate
+ X509CertificateHolder x509CertificateHolder = certgen.build(sigGen);
+
+ return X509Certificate.getInstance(x509CertificateHolder.getEncoded());
+
+
+ }
+
+ 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();
+ String receivedPostMessage = null;
+
+ try {
+ BufferedReader reader = req.getReader();
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+
+ receivedPostMessage = sb.toString();
+
+ } catch (IOException e) {
+ Logger.warn("Received POST-message produce an ERROR.", e);
+ Logger.info("Msg: " + receivedPostMessage);
+
+ }
+
+ JsonParser parser = new JsonParser();
+ JsonObject receivedData = null;
+ if (MiscUtil.isNotEmpty(receivedPostMessage))
+ receivedData = (JsonObject) parser.parse(sb.toString());
+
+ else if (developmentMode && MiscUtil.isNotEmpty(req.getParameter("blob"))) {
+ receivedData = (JsonObject) parser.parse(req.getParameter("blob"));
+
+ }
+
+ return receivedData;
+
+ }
+
+ 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/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 7c8a86f73..4d41ff652 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
@@ -49,19 +49,14 @@ import org.opensaml.Configuration;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.SubjectConfirmationData;
-import org.opensaml.saml2.encryption.Encrypter;
-import org.opensaml.saml2.encryption.Encrypter.KeyPlacement;
import org.opensaml.security.SAMLSignatureProfileValidator;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.EncryptionException;
-import org.opensaml.xml.encryption.EncryptionParameters;
-import org.opensaml.xml.encryption.KeyEncryptionParameters;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.io.Unmarshaller;
@@ -72,8 +67,6 @@ import org.opensaml.xml.parse.XMLParserException;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.security.SecurityHelper;
import org.opensaml.xml.security.credential.Credential;
-import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
-import org.opensaml.xml.security.x509.X509Credential;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureException;
import org.opensaml.xml.signature.SignatureValidator;
@@ -140,6 +133,7 @@ public class SSOContainerUtils {
tmp.add(PVPConstants.MANDATE_PROF_REP_OID_NAME);
tmp.add(PVPConstants.MANDATE_PROF_REP_DESC_NAME);
tmp.add(PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME);
+ tmp.add(PVPConstants.PVP_HOLDEROFKEY_NAME);
REQUIRED_ATTRIBUTES = Collections.unmodifiableList(tmp);
}
@@ -398,31 +392,33 @@ public class SSOContainerUtils {
authResponse.setStatus(SAML2Utils.getSuccessStatus());
//encrypt container
- X509Credential encryptionCredentials = credentials.getIDPAssertionEncryptionCredential();
- EncryptionParameters dataEncParams = new EncryptionParameters();
- dataEncParams.setAlgorithm(PVPConstants.DEFAULT_SYM_ENCRYPTION_METHODE);
-
- List<KeyEncryptionParameters> keyEncParamList = new ArrayList<KeyEncryptionParameters>();
- KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters();
-
- keyEncParam.setEncryptionCredential(encryptionCredentials);
- keyEncParam.setAlgorithm(PVPConstants.DEFAULT_ASYM_ENCRYPTION_METHODE);
- KeyInfoGeneratorFactory kigf = Configuration.getGlobalSecurityConfiguration()
- .getKeyInfoGeneratorManager().getDefaultManager()
- .getFactory(encryptionCredentials);
- keyEncParam.setKeyInfoGenerator(kigf.newInstance());
- keyEncParamList.add(keyEncParam);
-
- Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList);
- //samlEncrypter.setKeyPlacement(KeyPlacement.INLINE);
- samlEncrypter.setKeyPlacement(KeyPlacement.PEER);
-
- EncryptedAssertion encryptAssertion = null;
-
- encryptAssertion = samlEncrypter.encrypt(assertion);
- authResponse.getEncryptedAssertions().add(encryptAssertion);
-
-
+// X509Credential encryptionCredentials = credentials.getIDPAssertionEncryptionCredential();
+// EncryptionParameters dataEncParams = new EncryptionParameters();
+// dataEncParams.setAlgorithm(PVPConstants.DEFAULT_SYM_ENCRYPTION_METHODE);
+//
+// List<KeyEncryptionParameters> keyEncParamList = new ArrayList<KeyEncryptionParameters>();
+// KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters();
+//
+// keyEncParam.setEncryptionCredential(encryptionCredentials);
+// keyEncParam.setAlgorithm(PVPConstants.DEFAULT_ASYM_ENCRYPTION_METHODE);
+// KeyInfoGeneratorFactory kigf = Configuration.getGlobalSecurityConfiguration()
+// .getKeyInfoGeneratorManager().getDefaultManager()
+// .getFactory(encryptionCredentials);
+// keyEncParam.setKeyInfoGenerator(kigf.newInstance());
+// keyEncParamList.add(keyEncParam);
+//
+// Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList);
+// //samlEncrypter.setKeyPlacement(KeyPlacement.INLINE);
+// samlEncrypter.setKeyPlacement(KeyPlacement.PEER);
+//
+// EncryptedAssertion encryptAssertion = null;
+//
+// encryptAssertion = samlEncrypter.encrypt(assertion);
+// authResponse.getEncryptedAssertions().add(encryptAssertion);
+
+ //add unencrypted assertion
+ authResponse.getAssertions().add(assertion);
+
//sign container
Credential signingCredential = credentials.getIDPAssertionSigningCredential();
Signature signature = AbstractCredentialProvider.getIDPSignature(signingCredential);