aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-ssoTransfer/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/modules/moa-id-module-ssoTransfer/src/main')
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthModuleImpl.java76
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java76
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferSpringResourceProvider.java62
-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.java365
-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/data/SSOTransferOnlineApplication.java444
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java634
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferSignalServlet.java101
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java115
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java306
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java120
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java553
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransfer.authmodule.beans.xml14
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthentication.process.xml24
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/resources/moaid_ssotransfer_auth.beans.xml34
-rw-r--r--id/server/modules/moa-id-module-ssoTransfer/src/main/resources/sso_transfer_template.html447
18 files changed, 3500 insertions, 0 deletions
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthModuleImpl.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthModuleImpl.java
new file mode 100644
index 000000000..2a2b7bf80
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthModuleImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import at.gv.egovernment.moa.id.auth.modules.AuthModule;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SSOTransferAuthModuleImpl implements AuthModule{
+
+ private int priority = 1;
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Sets the priority of this module. Default value is {@code 0}.
+ * @param priority The priority.
+ */
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext)
+ */
+ @Override
+ public String selectProcess(ExecutionContext context) {
+ Object restoreSSOSessionObj = context.get("restoreSSOSession");
+ if (restoreSSOSessionObj != null && restoreSSOSessionObj instanceof String) {
+ boolean restoreSSOSession = (boolean) Boolean.parseBoolean((String)restoreSSOSessionObj);
+ if (restoreSSOSession)
+ return "SSOTransferAuthentication";
+
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
+ */
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthentication.process.xml" };
+ }
+
+}
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
new file mode 100644
index 000000000..1a4356653
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+/**
+ * @author tlenz
+ *
+ */
+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";
+
+ public static final String REQ_PARAM_GENERATE_QR = "createQR";
+ public static final String REQ_PARAM_TOKEN = "token";
+
+ public static final String SSOCONTAINER_KEY_TYPE = "type";
+ public static final String SSOCONTAINER_VALUE_TYPE_TRANSER = "TRANSFER";
+ public static final String SSOCONTAINER_VALUE_TYPE_PERSIST = "PERSIST";
+ public static final String SSOCONTAINER_VALUE_TYPE_SSO = "SSO";
+
+ 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 = "certificate";
+
+ public static final String SSOCONTAINER_KEY_VALIDTO = "validTo";
+ public static final String SSOCONTAINER_KEY_ENTITYID = "entityID";
+ 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 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/SSOTransferSpringResourceProvider.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferSpringResourceProvider.java
new file mode 100644
index 000000000..1c7a9f124
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferSpringResourceProvider.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SSOTransferSpringResourceProvider implements SpringResourceProvider {
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getResourcesToLoad()
+ */
+ @Override
+ public Resource[] getResourcesToLoad() {
+ ClassPathResource ssoTransferAuthConfig = new ClassPathResource("/moaid_ssotransfer_auth.beans.xml", SSOTransferSpringResourceProvider.class);
+ return new Resource[] {ssoTransferAuthConfig};
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getPackagesToScan()
+ */
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getName()
+ */
+ @Override
+ public String getName() {
+ return "SSO Transfer Module";
+ }
+
+}
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
new file mode 100644
index 000000000..78cbd788d
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferAuthenticationData.java
@@ -0,0 +1,365 @@
+/*
+ * 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.security.cert.CertificateEncodingException;
+import java.util.Date;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
+import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;
+import at.gv.egovernment.moa.id.data.AuthenticationRole;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.MISMandate;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SSOTransferAuthenticationData implements IAuthData {
+
+ private AuthenticationSession authSession = null;
+ boolean isIDPPrivateService = true;
+
+ public SSOTransferAuthenticationData(AuthConfiguration authConfig, AuthenticationSession authSession) throws ConfigurationException {
+ this.authSession = authSession;
+ String domainIdentifier = authConfig.getSSOTagetIdentifier();
+ if (domainIdentifier != null)
+ isIDPPrivateService = domainIdentifier.startsWith(MOAIDAuthConstants.PREFIX_WPBK);
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getIssueInstant()
+ */
+ @Override
+ public Date getIssueInstant() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getIssuer()
+ */
+ @Override
+ public String getIssuer() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isBusinessService()
+ */
+ @Override
+ public boolean isBusinessService() {
+ return this.isIDPPrivateService;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isSsoSession()
+ */
+ @Override
+ public boolean isSsoSession() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isUseMandate()
+ */
+ @Override
+ public boolean isUseMandate() {
+ return this.authSession.isMandateUsed();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getFamilyName()
+ */
+ @Override
+ public String getFamilyName() {
+ return this.authSession.getIdentityLink().getFamilyName();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getGivenName()
+ */
+ @Override
+ public String getGivenName() {
+ return this.authSession.getIdentityLink().getGivenName();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getDateOfBirth()
+ */
+ @Override
+ public Date getDateOfBirth() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getFormatedDateOfBirth()
+ */
+ @Override
+ public String getFormatedDateOfBirth() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getBPK()
+ */
+ @Override
+ public String getBPK() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getBPKType()
+ */
+ @Override
+ public String getBPKType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getSsoSessionValidTo()
+ */
+ @Override
+ public Date getSsoSessionValidTo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getIdentificationValue()
+ */
+ @Override
+ public String getIdentificationValue() {
+ return this.authSession.getIdentityLink().getIdentificationValue();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getIdentificationType()
+ */
+ @Override
+ public String getIdentificationType() {
+ return this.authSession.getIdentityLink().getIdentificationType();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getBkuURL()
+ */
+ @Override
+ public String getBkuURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getEncbPKList()
+ */
+ @Override
+ public List<String> getEncbPKList() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getIdentityLink()
+ */
+ @Override
+ public IdentityLink getIdentityLink() {
+ return this.authSession.getIdentityLink();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getSignerCertificate()
+ */
+ @Override
+ public byte[] getSignerCertificate() {
+ try {
+ return this.authSession.getSignerCertificate().getEncoded();
+
+ } catch (CertificateEncodingException e) {
+ Logger.error("SSO-Transfer: SignerCertificate encoding FAILED.", e);
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getAuthBlock()
+ */
+ @Override
+ public String getAuthBlock() {
+ return this.authSession.getAuthBlock();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getPvpAttribute_OU()
+ */
+ @Override
+ public String getPvpAttribute_OU() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getAuthenticationRoles()
+ */
+ @Override
+ public List<AuthenticationRole> getAuthenticationRoles() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isPublicAuthority()
+ */
+ @Override
+ public boolean isPublicAuthority() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getPublicAuthorityCode()
+ */
+ @Override
+ public String getPublicAuthorityCode() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isQualifiedCertificate()
+ */
+ @Override
+ public boolean isQualifiedCertificate() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getMISMandate()
+ */
+ @Override
+ public MISMandate getMISMandate() {
+ return this.authSession.getMISMandate();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getMandate()
+ */
+ @Override
+ public Element getMandate() {
+ return this.authSession.getMISMandate().getMandateDOM();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getMandateReferenceValue()
+ */
+ @Override
+ public String getMandateReferenceValue() {
+ return this.authSession.getMandateReferenceValue();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getQAALevel()
+ */
+ @Override
+ public String getQAALevel() {
+ return this.authSession.getQAALevel();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getSessionIndex()
+ */
+ @Override
+ public String getSessionIndex() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getNameID()
+ */
+ @Override
+ public String getNameID() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getNameIDFormat()
+ */
+ @Override
+ public String getNameIDFormat() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#isForeigner()
+ */
+ @Override
+ public boolean isForeigner() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getCcc()
+ */
+ @Override
+ public String getCcc() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.data.IAuthData#getEIDASQAALevel()
+ */
+ @Override
+ public String getEIDASQAALevel() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ /* (non-Javadoc)
+ * @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) {
+ 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/data/SSOTransferOnlineApplication.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferOnlineApplication.java
new file mode 100644
index 000000000..af180ff10
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/data/SSOTransferOnlineApplication.java
@@ -0,0 +1,444 @@
+/*
+ * 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.security.PrivateKey;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.commons.api.data.CPEPS;
+import at.gv.egovernment.moa.id.commons.api.data.SAML1ConfigurationParameters;
+import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute;
+import at.gv.egovernment.moa.id.commons.api.data.StorkAttributeProviderPlugin;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SSOTransferOnlineApplication implements IOAAuthParameters {
+
+ public SSOTransferOnlineApplication() {
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getBusinessService()
+ */
+ @Override
+ public boolean getBusinessService() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#useSSO()
+ */
+ @Override
+ public boolean useSSO() {
+ return true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getBKUURL()
+ */
+ @Override
+ public List<String> getBKUURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getFullConfiguration()
+ */
+ @Override
+ public Map<String, String> getFullConfiguration() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getConfigurationValue(java.lang.String)
+ */
+ @Override
+ public String getConfigurationValue(String key) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getFriendlyName()
+ */
+ @Override
+ public String getFriendlyName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getPublicURLPrefix()
+ */
+ @Override
+ public String getPublicURLPrefix() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getOaType()
+ */
+ @Override
+ public String getOaType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getTarget()
+ */
+ @Override
+ public String getTarget() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getTargetFriendlyName()
+ */
+ @Override
+ public String getTargetFriendlyName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isInderfederationIDP()
+ */
+ @Override
+ public boolean isInderfederationIDP() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isSTORKPVPGateway()
+ */
+ @Override
+ public boolean isSTORKPVPGateway() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getIdentityLinkDomainIdentifier()
+ */
+ @Override
+ public String getIdentityLinkDomainIdentifier() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getKeyBoxIdentifier()
+ */
+ @Override
+ public String getKeyBoxIdentifier() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getSAML1Parameter()
+ */
+ @Override
+ public SAML1ConfigurationParameters getSAML1Parameter() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getTemplateURL()
+ */
+ @Override
+ public List<String> getTemplateURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getAditionalAuthBlockText()
+ */
+ @Override
+ public String getAditionalAuthBlockText() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getBKUURL(java.lang.String)
+ */
+ @Override
+ public String getBKUURL(String bkutype) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#useSSOQuestion()
+ */
+ @Override
+ public boolean useSSOQuestion() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getMandateProfiles()
+ */
+ @Override
+ public List<String> getMandateProfiles() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getIdentityLinkDomainIdentifierType()
+ */
+ @Override
+ public String getIdentityLinkDomainIdentifierType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isShowMandateCheckBox()
+ */
+ @Override
+ public boolean isShowMandateCheckBox() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isOnlyMandateAllowed()
+ */
+ @Override
+ public boolean isOnlyMandateAllowed() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isShowStorkLogin()
+ */
+ @Override
+ public boolean isShowStorkLogin() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getQaaLevel()
+ */
+ @Override
+ public Integer getQaaLevel() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isRequireConsentForStorkAttributes()
+ */
+ @Override
+ public boolean isRequireConsentForStorkAttributes() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getRequestedSTORKAttributes()
+ */
+ @Override
+ public Collection<StorkAttribute> getRequestedSTORKAttributes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getBKUSelectionTemplate()
+ */
+ @Override
+ public byte[] getBKUSelectionTemplate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getSendAssertionTemplate()
+ */
+ @Override
+ public byte[] getSendAssertionTemplate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getPepsList()
+ */
+ @Override
+ public Collection<CPEPS> getPepsList() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getIDPAttributQueryServiceURL()
+ */
+ @Override
+ public String getIDPAttributQueryServiceURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isInboundSSOInterfederationAllowed()
+ */
+ @Override
+ public boolean isInboundSSOInterfederationAllowed() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isInterfederationSSOStorageAllowed()
+ */
+ @Override
+ public boolean isInterfederationSSOStorageAllowed() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isOutboundSSOInterfederationAllowed()
+ */
+ @Override
+ public boolean isOutboundSSOInterfederationAllowed() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isTestCredentialEnabled()
+ */
+ @Override
+ public boolean isTestCredentialEnabled() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getTestCredentialOIDs()
+ */
+ @Override
+ public List<String> getTestCredentialOIDs() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isUseIDLTestTrustStore()
+ */
+ @Override
+ public boolean isUseIDLTestTrustStore() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isUseAuthBlockTestTestStore()
+ */
+ @Override
+ public boolean isUseAuthBlockTestTestStore() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getBPKDecBpkDecryptionKey()
+ */
+ @Override
+ public PrivateKey getBPKDecBpkDecryptionKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isPassivRequestUsedForInterfederation()
+ */
+ @Override
+ public boolean isPassivRequestUsedForInterfederation() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isPerformLocalAuthenticationOnInterfederationError()
+ */
+ @Override
+ public boolean isPerformLocalAuthenticationOnInterfederationError() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getStorkAPs()
+ */
+ @Override
+ public Collection<StorkAttributeProviderPlugin> getStorkAPs() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#getReversionsLoggingEventCodes()
+ */
+ @Override
+ public List<Integer> getReversionsLoggingEventCodes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isRemovePBKFromAuthBlock()
+ */
+ @Override
+ public boolean isRemovePBKFromAuthBlock() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
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
new file mode 100644
index 000000000..b18425839
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java
@@ -0,0 +1,634 @@
+/*
+ * 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.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.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+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.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+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.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.ParseException;
+import at.gv.egovernment.moa.id.auth.frontend.builder.DefaultGUIFormBuilderConfiguration;
+import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;
+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.SSOContainerUtils;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.commons.api.exceptions.SessionDataStorageException;
+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.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;
+
+
+
+/**
+ * @author tlenz
+ *
+ */
+//@WebServlet(name = "SSOTransferGUI", value = "/TransferSSOSession")
+@Controller
+public class SSOTransferServlet{
+
+ private static final long transmisionTimeOut = 90 * 1000; // default 90 secundes
+
+ @Autowired SSOManager ssomanager;
+ @Autowired IAuthenticationSessionStoreage authenticationSessionStorage;
+ @Autowired SSOContainerUtils ssoTransferUtils;
+ @Autowired ITransactionStorage transactionStorage;
+ @Autowired IDPCredentialProvider idpCredentials;
+ @Autowired AuthConfiguration authConfig;
+ @Autowired IGUIFormBuilder guiBuilder;
+
+ public SSOTransferServlet() {
+ super();
+ Logger.debug("Registering servlet " + getClass().getName()
+ + " 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 {
+ //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.");
+
+ }
+
+ DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration(
+ authURL,
+ DefaultGUIFormBuilderConfiguration.VIEW_SSO_SESSION_TRANSFER,
+ null);
+
+ internalCreateQRCodeForTransfer(resp, authURL,
+ "123456", "/TestTransmitSSOSession", config);
+
+ } 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 {
+ Logger.debug("Load token:" + token + " from storage.");
+ 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) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CredentialsNotAvailableException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (PKCSException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (CertificateException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeyException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (NoSuchAlgorithmException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (InvalidKeySpecException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (SessionDataStorageException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (ParseException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (IllegalBlockSizeException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (BadPaddingException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ } catch (NoSuchPaddingException e) {
+ Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+
+ }
+
+ } 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, RequestMethod.POST})
+ 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 {
+ 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.");
+ 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) {
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ } catch (IllegalBlockSizeException e) {
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ } catch (BadPaddingException e) {
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ } catch (NoSuchPaddingException e) {
+ e.printStackTrace();
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ }
+
+
+
+ } else {
+ Logger.info("Servlet " + getClass().getName() + " receive a NOT valid request.");
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Request not valid.");
+
+ }
+
+
+ }
+
+
+ @RequestMapping(value = { "/TransferSSOSession"
+ },
+ method = {RequestMethod.GET, RequestMethod.POST})
+ public void transferSSOSessionGUI(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ //search SSO session
+ String ssoid = ssomanager.getSSOSessionID(req);
+
+ try {
+ 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.");
+
+ }
+
+ DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration(
+ authURL,
+ DefaultGUIFormBuilderConfiguration.VIEW_SSO_SESSION_TRANSFER,
+ null);
+
+ if (ssomanager.isValidSSOSession(ssoid, null)) {
+ //Object createQRObj = req.getParameter(SSOTransferConstants.REQ_PARAM_GENERATE_QR);
+
+ //create first step of SSO Transfer GUI
+
+ 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, config);
+
+ return;
+ }
+ }
+
+ }
+
+ config.putCustomParameter("errorMsg",
+ "No active Single Sign-On session found! SSO Session transfer is not possible.");
+
+ guiBuilder.build(resp, config, "SSO-Transfer-Module");
+
+ } 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, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
+ Logger.debug("");
+ JsonObject receivedData = getJSONObjectFromPostMessage(req, developmentMode);
+
+ if (receivedData == null) {
+ Logger.warn("No data received");
+ throw new IOException("No data received");
+
+ }
+
+ String mobilePubKeyBase64 = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();
+ String mobileCSRBase64 = receivedData.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_CSR).getAsString();
+
+ Logger.debug("Receive PubKey:" +mobilePubKeyBase64 + " | CSR:" + mobileCSRBase64);
+
+ //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 CSR decryption ...");
+ byte[] encryptedCSR = Base64Utils.decode(mobileCSRBase64, true);
+ Logger.debug("EncCSR:" + Base64Utils.encode(encryptedCSR) + " | Key:" + Base64Utils.encode(hashedSecret));
+
+ 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 ...");
+
+ //generate certificate from CSR
+ X509Certificate mobileCert = signCSRWithMOAKey(decryptedCSR);
+
+ Logger.debug("CSR validation finished. --> Starting personData generation ... ");
+
+ moaSession.setGenericDataToSession(
+ SSOTransferConstants.MOASESSION_DATA_HOLDEROFKEY_CERTIFICATE,
+ mobileCert.getEncoded());
+
+ //generate assertion
+ Date now = new Date();
+ String personInformationToTransfer =
+ ssoTransferUtils.generateSignedAndEncryptedSSOContainer(
+ container.getAuthURL(), moaSession, now, hashedSecret);
+ Logger.debug("PersonData:" + personInformationToTransfer);
+
+ //encrypt personal information
+ Logger.debug("PersonData generation finished. --> Starting personData encryption ... ");
+
+ Logger.debug("Encrypt personData finished. --> Send token to device.");
+ 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, DefaultGUIFormBuilderConfiguration config) 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 = ssoTransferUtils.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());
+ config.putCustomParameter("QRImage", base64EncodedImage);
+
+ config.putCustomParameter("successMsg", "Scan the QR-Code with your <i>SSO-Transfer App</i> to start the transfer operation.");
+
+
+ guiBuilder.build(resp, config, "SSO-Session Transfer-Module");
+
+ }
+
+ 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 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;
+ Logger.debug("JSON POST msg: " + sb.toString());
+ 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;
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferSignalServlet.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferSignalServlet.java
new file mode 100644
index 000000000..e92925dfb
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferSignalServlet.java
@@ -0,0 +1,101 @@
+/*
+ * 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.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils;
+import at.gv.egovernment.moa.id.auth.servlet.AbstractProcessEngineSignalController;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+@Controller
+public class SSOTransferSignalServlet extends AbstractProcessEngineSignalController {
+ public SSOTransferSignalServlet() {
+ super();
+ Logger.debug("Registering servlet " + getClass().getName() + " with mappings '/SSOTransferEndpoint'.");
+
+ }
+
+ @RequestMapping(value = { "/SSOTransferSignalEndpoint"
+ },
+ method = {RequestMethod.POST, RequestMethod.GET})
+ public void performSSOTransfer(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ signalProcessManagement(req, resp);
+
+ }
+
+ @Override
+ protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ String pendingRequestID = StringEscapeUtils.escapeHtml(getPendingRequestId(req));
+ IRequest pendingReq = null;
+ try {
+ if (pendingRequestID == null) {
+ throw new IllegalStateException("Unable to determine MOA pending-request id.");
+ }
+
+ pendingReq = requestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //add transactionID and unique sessionID to Logger
+ TransactionIDUtils.setSessionId(pendingReq.getUniqueSessionIdentifier());
+ TransactionIDUtils.setTransactionId(pendingReq.getUniqueTransactionIdentifier());
+
+ // process instance is mandatory
+ if (pendingReq.getProcessInstanceId() == null) {
+ throw new IllegalStateException("MOA session does not provide process instance id.");
+ }
+
+ // wake up next task
+ processEngine.signal(pendingReq);
+
+ } catch (Exception ex) {
+ handleError(null, ex, req, resp, pendingReq);
+
+ } finally {
+ //MOASessionDBUtils.closeSession();
+ TransactionIDUtils.removeTransactionId();
+ TransactionIDUtils.removeSessionId();
+
+ }
+
+
+ }
+}
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
new file mode 100644
index 000000000..be27de9a1
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java
@@ -0,0 +1,115 @@
+/*
+ * 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.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;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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
+ *
+ */
+@Component("InitializeRestoreSSOSessionTask")
+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)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext,
+ HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+
+ try {
+ //create first step of SSO Transfer GUI
+ String authURL = HTTPUtils.extractAuthURLFromRequest(request);
+ if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().
+ contains(authURL)) {
+ Logger.warn("Requested URL is not allowed.");;
+ response.sendError(500, "Requested URL is not allowed.");
+
+ }
+
+ //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);
+
+ } catch (Exception e) {
+ Logger.error(this.getClass().getName() + " has an interal Error.", e);
+ throw new TaskExecutionException(pendingReq, this.getClass().getName() + " has an interal Error.", 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
new file mode 100644
index 000000000..dd133e4fb
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java
@@ -0,0 +1,306 @@
+/*
+ * 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.task;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+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.joda.time.DateTime;
+import org.opensaml.saml2.core.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+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.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
+ *
+ */
+@Component("RestoreSSOSessionTask")
+public class RestoreSSOSessionTask extends AbstractAuthServletTask {
+
+ @Autowired SSOContainerUtils ssoTransferUtils;
+ @Autowired IGUIFormBuilder guiBuilder;
+
+ /* (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)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext,
+ HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+
+ Logger.debug("Receive " + this.getClass().getName() + " request");
+
+ StringBuffer sb = new StringBuffer();
+ String receivedPostMessage = null;
+ String authURL =null;
+ try {
+ BufferedReader reader = request.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);
+
+ }
+
+ 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",
+ 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 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 respNonce = receivedSession.get(
+ SSOTransferConstants.PENDINGREQ_NONCE).getAsString();
+ String encSessionBlobBase64 = receivedSession.get(
+ SSOTransferConstants.SSOCONTAINER_KEY_BLOB).getAsString();
+
+ 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,
+ 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);
+
+ //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 ...");
+
+
+ //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);
+
+ // 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);
+
+
+ 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
+//
+// 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);
+ //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 {
+ Logger.debug("Reveive NO POST-message data. Start check-session process ... ");
+
+ boolean isSSOSessionRestored =
+ BooleanUtils.isTrue((Boolean) executionContext.get(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED));
+
+ if (isSSOSessionRestored) {
+ Logger.info("Found restored SSO session. Resume authentication process ...");
+ executionContext.remove(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED);
+ 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(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.",
+ 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.");
+ executionContext.put("sessionRestoreFinished", false);
+
+ try {
+ //create first step of SSO Transfer GUI
+ authURL = HTTPUtils.extractAuthURLFromRequest(request);
+ if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().
+ contains(authURL)) {
+ Logger.warn("Requested URL is not allowed.");;
+ response.sendError(500, "Requested URL is not allowed.");
+
+ }
+
+ GUIUtils.buildSSOTransferGUI(guiBuilder, response,
+ 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
new file mode 100644
index 000000000..13a278d1d
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java
@@ -0,0 +1,120 @@
+/*
+ * 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.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.servlet.http.HttpServletResponse;
+
+import com.google.gson.JsonObject;
+
+import at.gv.egovernment.moa.id.auth.frontend.builder.DefaultGUIFormBuilderConfiguration;
+import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;
+import at.gv.egovernment.moa.id.auth.frontend.exception.GUIBuildException;
+import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants;
+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;
+
+/**
+ * @author tlenz
+ *
+ */
+public class GUIUtils {
+ public static final int REFESH_TIMEOUT = 5 * 1000; //5 sec
+
+ 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 + "=" + 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(350, 350).stream();
+ String base64EncodedImage = Base64Utils.encode(qrStream.toByteArray());
+
+ DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration(
+ authURL,
+ DefaultGUIFormBuilderConfiguration.VIEW_SSO_SESSION_TRANSFER,
+ null);
+
+ config.putCustomParameter("QRImage", base64EncodedImage);
+ config.putCustomParameter("successMsg", "Select the SSO Session in your <i>SSO-Transfer App</i> and scan the QR-Code to start the process.");
+ config.putCustomParameter("timeoutURL", containerURL);
+ config.putCustomParameter("timeout", REFESH_TIMEOUT);
+
+ 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
new file mode 100644
index 000000000..0785f767b
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java
@@ -0,0 +1,553 @@
+/*
+ * 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.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;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.joda.time.DateTime;
+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.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.security.SAMLSignatureProfileValidator;
+import org.opensaml.xml.XMLObject;
+import org.opensaml.xml.encryption.EncryptionException;
+import org.opensaml.xml.io.Marshaller;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.io.Unmarshaller;
+import org.opensaml.xml.io.UnmarshallerFactory;
+import org.opensaml.xml.io.UnmarshallingException;
+import org.opensaml.xml.parse.BasicParserPool;
+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.signature.Signature;
+import org.opensaml.xml.signature.SignatureException;
+import org.opensaml.xml.signature.SignatureValidator;
+import org.opensaml.xml.signature.Signer;
+import org.opensaml.xml.validation.ValidationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+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;
+import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
+import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.MISMandate;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoCredentialsException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSignedException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider;
+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.protocols.pvp2x.utils.AssertionAttributeExtractor;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngineSP;
+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;
+
+/**
+ * @author tlenz
+ *
+ */
+@Service("SSOContainerUtils")
+public class SSOContainerUtils {
+
+ private static final String PVP_HOLDEROFKEY_NAME = PVPConstants.URN_OID_PREFIX +
+ "1.2.40.0.10.2.1.1.261.xx.xx";
+
+ public static final List<String> REQUIRED_ATTRIBUTES;
+ static {
+ List<String> tmp = new ArrayList<String>();
+ tmp.add(PVPConstants.EID_AUTH_BLOCK_NAME);
+ tmp.add(PVPConstants.EID_IDENTITY_LINK_NAME);
+ tmp.add(PVPConstants.EID_ISSUING_NATION_NAME);
+ tmp.add(PVPConstants.EID_SIGNER_CERTIFICATE_NAME);
+ tmp.add(PVPConstants.EID_SOURCE_PIN_NAME);
+ tmp.add(PVPConstants.EID_SOURCE_PIN_TYPE_NAME);
+ tmp.add(PVPConstants.MANDATE_REFERENCE_VALUE_NAME);
+ tmp.add(PVPConstants.MANDATE_FULL_MANDATE_NAME);
+ tmp.add(PVPConstants.MANDATE_TYPE_NAME);
+ tmp.add(PVPConstants.MANDATE_PROF_REP_OID_NAME);
+ tmp.add(PVPConstants.MANDATE_PROF_REP_DESC_NAME);
+ tmp.add(PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME);
+
+ //TODO: change to final definition
+ tmp.add(PVP_HOLDEROFKEY_NAME);
+
+ REQUIRED_ATTRIBUTES = Collections.unmodifiableList(tmp);
+ }
+
+ @Autowired IDPCredentialProvider credentials;
+ @Autowired SAMLVerificationEngineSP samlVerificationEngine;
+ @Autowired AuthConfiguration authConfig;
+
+ 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
+ moasession.setBkuURL("http://egiz.gv.at/sso_session-transfer_app");
+
+
+ String qaaLevel = attributeExtractor.getSingleAttributeValue(PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME);
+ if (MiscUtil.isNotEmpty(qaaLevel)) {
+ if (qaaLevel.startsWith(PVPConstants.STORK_QAA_PREFIX))
+ moasession.setQAALevel(qaaLevel);
+ else
+ moasession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + qaaLevel);
+
+
+ } else {
+ Logger.warn("SSO session-container contains NO QAA-level");
+
+ }
+
+ String authBlock = attributeExtractor.getSingleAttributeValue(PVPConstants.EID_AUTH_BLOCK_NAME);
+ if (MiscUtil.isNotEmpty(authBlock))
+ moasession.setAuthBlock(authBlock);
+ else
+ Logger.warn("SSO session-container contains NO AuthBlock");
+
+ try {
+ String signerCert = attributeExtractor.getSingleAttributeValue(PVPConstants.EID_SIGNER_CERTIFICATE_NAME);
+ if (MiscUtil.isNotEmpty(signerCert))
+ moasession.setSignerCertificate(new X509Certificate(Base64Utils.decode(signerCert, false)));
+ else
+ Logger.warn("SSO session-container contains NO SignerCertificate");
+
+ } catch (CertificateException | IOException e) {
+ Logger.error("SignerCertificate is not parseable.", e);
+
+ }
+
+ String idlStr = attributeExtractor.getSingleAttributeValue(PVPConstants.EID_IDENTITY_LINK_NAME);
+ try {
+ if (MiscUtil.isNotEmpty(idlStr)) {
+ IdentityLinkAssertionParser idlParser = new IdentityLinkAssertionParser(Base64Utils.decodeToStream(idlStr, false));
+ moasession.setIdentityLink(idlParser.parseIdentityLink());
+
+ } else {
+ Logger.warn("SSO session-container contains NO IdentityLink");
+ throw new AssertionAttributeExtractorExeption("SSO session-container contains NO IdentityLink");
+
+ }
+
+ } catch (ParseException e) {
+ Logger.error("IdentityLink is not parseable.", e);
+ throw new AssertionAttributeExtractorExeption("IdentityLink is not parseable.");
+
+ }
+
+
+ String mandateRefValue = attributeExtractor.getSingleAttributeValue(PVPConstants.MANDATE_REFERENCE_VALUE_NAME);
+ if (MiscUtil.isNotEmpty(mandateRefValue)) {
+ moasession.setMandateReferenceValue(mandateRefValue);
+ moasession.setUseMandate("true");
+ Logger.info("Found mandate information in SSO session-container.");
+
+ try {
+ MISMandate mandate = new MISMandate();
+
+ String mandateFull = attributeExtractor.getSingleAttributeValue(PVPConstants.MANDATE_FULL_MANDATE_NAME);
+ if (MiscUtil.isNotEmpty(mandateFull)) {
+ mandate.setMandate(Base64Utils.decode(mandateFull, false));
+
+ } else {
+ Logger.warn("No Full-Mandate information found in SSO session-container.");
+
+ }
+
+ String oid = attributeExtractor.getSingleAttributeValue(PVPConstants.MANDATE_PROF_REP_OID_NAME);
+ if (MiscUtil.isNotEmpty(oid))
+ mandate.setProfRep(oid );
+
+ NodeList mandateElements = mandate.getMandateDOM().getChildNodes();
+ for (int i=0; i<mandateElements.getLength(); i++) {
+ Element mandateEl = (Element) mandateElements.item(i);
+ if (mandateEl.hasAttribute("OWbPK")) {
+ mandate.setOWbPK(mandateEl.getAttribute("OWbPK"));
+ }
+ }
+
+ moasession.setMISMandate(mandate);
+
+ } catch (IOException e) {
+ Logger.error("Full-Mandate information is not parseable.", e);
+
+ }
+ }
+
+
+
+
+
+ }
+
+ 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(signedEncryptedContainer.getBytes()));
+ Element domElement = document.getDocumentElement();
+
+ UnmarshallerFactory saml2UnmarshallerFactory = Configuration.getUnmarshallerFactory();
+ Unmarshaller saml2Unmarshaller = saml2UnmarshallerFactory.getUnmarshaller(domElement);
+ XMLObject responseXMLObj = saml2Unmarshaller.unmarshall(domElement);
+
+ if (responseXMLObj instanceof Response) {
+ Response ssoContainer = (Response) responseXMLObj;
+
+ try {
+ SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator();
+ sigValidator.validate(ssoContainer.getSignature());
+
+ } catch (ValidationException e) {
+ Logger.error("Failed to validate Signature", e);
+ throw new SAMLRequestNotSignedException(e);
+ }
+
+ Credential credential = credentials.getIDPAssertionSigningCredential();
+ if (credential == null) {
+ throw new NoCredentialsException("moaID IDP");
+ }
+
+ SignatureValidator sigValidator = new SignatureValidator(credential);
+ try {
+ sigValidator.validate(ssoContainer.getSignature());
+
+ } catch (ValidationException e) {
+ Logger.error("Failed to verfiy Signature", e);
+ throw new SAMLRequestNotSignedException(e);
+ }
+
+ if (ssoContainer.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
+
+ //validate PVP 2.1 assertion
+ samlVerificationEngine.validateAssertion(ssoContainer, false,
+ credentials.getIDPAssertionEncryptionCredential(),
+ ssoContainer.getIssuer().getValue(),
+ "SSO-Session Transfer module",
+ false);
+ return ssoContainer;
+
+ } else {
+ Logger.debug("Receive StatusCode " + ssoContainer.getStatus().getStatusCode().getValue()
+ + " from interfederated IDP.");
+ throw new MOAIDException("SSO Container has a not valid Status Code", null);
+
+ }
+
+ } else {
+ Logger.warn("SSO Container is not of type SAML2 Response");
+ throw new MOAIDException("SSO Container is not of type SAML2 Response", null);
+
+ }
+ }
+
+
+ public String generateSignedAndEncryptedSSOContainer(String authURL,
+ AuthenticationSession authSession, Date date, byte[] hashedSecret) {
+ try {
+ String entityID = PVPConfiguration.getInstance().getIDPSSOMetadataService(authURL);
+ AuthnContextClassRef authnContextClassRef = SAML2Utils
+ .createSAMLObject(AuthnContextClassRef.class);
+ authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel());
+
+ NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);
+ String random = Random.nextLongRandom();
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] hash = md.digest((random).getBytes("ISO-8859-1"));
+ subjectNameID.setValue(Base64Utils.encode(hash));
+ subjectNameID.setNameQualifier(null);
+ subjectNameID.setFormat(NameID.TRANSIENT);
+
+ } catch (Exception e) {
+ Logger.warn("PVP2 subjectNameID error", e);
+
+ }
+
+ SubjectConfirmationData subjectConfirmationData = SAML2Utils
+ .createSAMLObject(SubjectConfirmationData.class);
+ long maxSSOSessionTime = AuthConfigurationProviderFactory.getInstance().getSSOCreatedTimeOut() * 1000;
+ Date ssoSessionValidTo = new Date(authSession.getSessionCreated().getTime() + maxSSOSessionTime);
+ subjectConfirmationData.setNotOnOrAfter(new DateTime(ssoSessionValidTo.getTime()));
+
+ String sessionIndex = SAML2Utils.getSecureIdentifier();
+
+ IAuthData authData = new SSOTransferAuthenticationData(authConfig, authSession);
+
+ Assertion assertion = PVP2AssertionBuilder.buildGenericAssertion(
+ entityID,
+ entityID,
+ new DateTime(date.getTime()),
+ authnContextClassRef,
+ buildSSOAttributeForTransfer(authSession, authData),
+ subjectNameID,
+ subjectConfirmationData,
+ sessionIndex,
+ subjectConfirmationData.getNotOnOrAfter());
+
+ //build blob with signed session information
+ String ssoDataBlob = buildSSOContainerObject(entityID, assertion, new DateTime(date.getTime()));
+ Logger.debug("Unencrypted SessionBlob:" + ssoDataBlob);
+
+ //encrypt session information with ephemeral key
+ byte[] encPersonData = enOrDeCryptCSR(ssoDataBlob.getBytes(), hashedSecret, Cipher.ENCRYPT_MODE);
+ String encAndEncodedPersonalData = Base64Utils.encode(encPersonData);
+ Logger.debug("Encrypted SessionBlob:" + encAndEncodedPersonalData);
+
+ //build JSON response
+ 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, encAndEncodedPersonalData);
+ container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_UNIQUEUSERID,
+ BpkUtil.calcBPK(authData.getIdentificationValue(), "AB"));
+
+ //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 | 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 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(entityID);
+ nissuer.setFormat(NameID.ENTITY);
+ authResponse.setIssuer(nissuer);
+
+ //set responseID
+ String remoteSessionID = SAML2Utils.getSecureIdentifier();
+ authResponse.setID(remoteSessionID);
+
+
+ //SAML2 response required IssueInstant
+ authResponse.setIssueInstant(date);
+ 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);
+
+ //add unencrypted assertion
+ authResponse.getAssertions().add(assertion);
+
+ //sign container
+ Credential signingCredential = credentials.getIDPAssertionSigningCredential();
+ Signature signature = AbstractCredentialProvider.getIDPSignature(signingCredential);
+
+ SecurityHelper.prepareSignatureParams(signature, signingCredential, null, null);
+ authResponse.setSignature(signature);
+
+ DocumentBuilder builder;
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+
+ builder = factory.newDocumentBuilder();
+ Document document = builder.newDocument();
+ Marshaller out = Configuration.getMarshallerFactory()
+ .getMarshaller(authResponse);
+ out.marshall(authResponse, document);
+
+ Signer.signObject(signature);
+
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+
+ StringWriter sw = new StringWriter();
+ StreamResult sr = new StreamResult(sw);
+ DOMSource source = new DOMSource(document);
+ transformer.transform(source, sr);
+ sw.close();
+
+ return sw.toString();
+
+ }
+
+ private static List<Attribute> buildSSOAttributeForTransfer(AuthenticationSession authSession, IAuthData authData) {
+ List<Attribute> attrList = new ArrayList<Attribute>();
+
+ IOAAuthParameters oaParam = new SSOTransferOnlineApplication();
+
+ for (String el : REQUIRED_ATTRIBUTES) {
+ try {
+ Attribute attr = PVPAttributeBuilder.buildAttribute(
+ el, oaParam, authData);
+ if (attr != null)
+ attrList.add(attr);
+ else
+ Logger.info("SSO-Transfer attribute " + el + " is empty!");
+
+ } catch (Exception e) {
+ Logger.info("Build SSO-Transfer attribute " + el + " FAILED:" + e.getMessage());
+
+ }
+ }
+
+ return attrList;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 000000000..b0744b49b
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferSpringResourceProvider \ No newline at end of file
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransfer.authmodule.beans.xml b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransfer.authmodule.beans.xml
new file mode 100644
index 000000000..1a8709e15
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransfer.authmodule.beans.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+ <context:annotation-config />
+
+ <bean id="ssoTransferAuthModule" class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferAuthModuleImpl">
+ <property name="priority" value="1" />
+ </bean>
+
+</beans>
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthentication.process.xml b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthentication.process.xml
new file mode 100644
index 000000000..e7d98c8c8
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferAuthentication.process.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pd:ProcessDefinition id="SSOTransferAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1">
+
+<!--
+ STORK authentication both with C-PEPS supporting xml signatures and with C-PEPS not supporting xml signatures.
+-->
+ <pd:Task id="initializeRestoreSSOSessionTask" class="InitializeRestoreSSOSessionTask" />
+ <pd:Task id="restoreSSOSessionTask" class="RestoreSSOSessionTask" async="true" />
+ <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" />
+
+ <!-- Process is triggered either by GenerateIFrameTemplateServlet (upon bku selection) or by AuthenticationManager (upon legacy authentication start using legacy parameters. -->
+ <pd:StartEvent id="start" />
+
+ <pd:Transition from="start" to="initializeRestoreSSOSessionTask" />
+ <pd:Transition from="initializeRestoreSSOSessionTask" to="restoreSSOSessionTask"/>
+
+ <pd:Transition from="restoreSSOSessionTask" to="restoreSSOSessionTask" conditionExpression="!ctx['sessionRestoreFinished']"/>
+ <pd:Transition from="restoreSSOSessionTask" to="finalizeAuthentication" />
+
+ <pd:Transition from="finalizeAuthentication" to="end" />
+
+ <pd:EndEvent id="end" />
+
+</pd:ProcessDefinition>
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/moaid_ssotransfer_auth.beans.xml b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/moaid_ssotransfer_auth.beans.xml
new file mode 100644
index 000000000..4a4af4ac5
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/moaid_ssotransfer_auth.beans.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+
+ <bean id="SSOContainerUtils"
+ class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.SSOContainerUtils"/>
+
+
+ <bean id="SSOTransferSignalServlet"
+ class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.servlet.SSOTransferSignalServlet"/>
+
+
+ <bean id="SSOTransferServlet"
+ class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.servlet.SSOTransferServlet"/>
+
+
+<!-- Federated Authentication Process Tasks -->
+ <bean id="RestoreSSOSessionTask"
+ class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.task.RestoreSSOSessionTask"
+ scope="prototype"/>
+
+ <bean id="InitializeRestoreSSOSessionTask"
+ class="at.gv.egovernment.moa.id.auth.modules.ssotransfer.task.InitializeRestoreSSOSessionTask"
+ scope="prototype"/>
+
+</beans> \ No newline at end of file
diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/sso_transfer_template.html b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/sso_transfer_template.html
new file mode 100644
index 000000000..962faa58f
--- /dev/null
+++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/resources/sso_transfer_template.html
@@ -0,0 +1,447 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+
+ <!-- MOA-ID 2.x BKUSelection Layout CSS -->
+ <style type="text/css">
+ @media screen and (min-width: 650px) {
+
+ body {
+ margin:0;
+ padding:0;
+ color : #000;
+ background-color : #fff;
+ text-align: center;
+ background-color: #6B7B8B;
+ }
+
+ #page {
+ display: block;
+ border: 2px solid rgb(0,0,0);
+ width: 650px;
+ height: 460px;
+ margin: 0 auto;
+ margin-top: 5%;
+ position: relative;
+ border-radius: 25px;
+ background: rgb(255,255,255);
+ }
+
+ #page1 {
+ text-align: center;
+ }
+
+ #main {
+ /* clear:both; */
+ position:relative;
+ margin: 0 auto;
+ width: 250px;
+ text-align: center;
+ }
+
+ .OA_header {
+ /* background-color: white;*/
+ font-size: 20pt;
+ margin-bottom: 25px;
+ margin-top: 25px;
+ }
+
+ #leftcontent {
+ /*float:left; */
+ width:250px;
+ margin-bottom: 25px;
+ text-align: left;
+ /*border: 1px solid rgb(0,0,0);*/
+ }
+
+ #leftcontent {
+ width: 300px;
+ margin-top: 30px;
+ }
+
+ h2#tabheader{
+ font-size: 1.1em;
+ padding-left: 2%;
+ padding-right: 2%;
+ position: relative;
+ }
+
+ .setAssertionButton_full {
+ background: #efefef;
+ cursor: pointer;
+ margin-top: 15px;
+ width: 100px;
+ height: 30px
+ }
+
+ #leftbutton {
+ width: 30%;
+ float:left;
+ margin-left: 40px;
+ }
+
+ #rightbutton {
+ width: 30%;
+ float:right;
+ margin-right: 45px;
+ text-align: right;
+ }
+
+ button {
+ height: 25px;
+ width: 75px;
+ margin-bottom: 10px;
+ }
+
+ #validation {
+ position: absolute;
+ bottom: 0px;
+ margin-left: 270px;
+ padding-bottom: 10px;
+ }
+
+ }
+
+ @media screen and (max-width: 205px) {
+ #localBKU p {
+ font-size: 0.6em;
+ }
+
+ #localBKU input {
+ font-size: 0.6em;
+ min-width: 60px;
+ /* max-width: 65px; */
+ min-height: 1.0em;
+ /* border-radius: 5px; */
+ }
+
+ }
+
+ @media screen and (max-width: 249px) and (min-width: 206px) {
+ #localBKU p {
+ font-size: 0.7em;
+ }
+
+ #localBKU input {
+ font-size: 0.7em;
+ min-width: 70px;
+ /* max-width: 75px; */
+ min-height: 0.95em;
+ /* border-radius: 6px; */
+ }
+
+ }
+
+ @media screen and (max-width: 299px) and (min-width: 250px) {
+ #localBKU p {
+ font-size: 0.9em;
+ }
+
+ #localBKU input {
+ font-size: 0.8em;
+ min-width: 70px;
+ /* max-width: 75px; */
+ /* border-radius: 6px; */
+ }
+
+ }
+
+ @media screen and (max-width: 399px) and (min-width: 300px) {
+ #localBKU p {
+ font-size: 0.9em;
+ }
+
+ #localBKU input {
+ font-size: 0.8em;
+ min-width: 70px;
+ /* max-width: 75px; */
+ /* border-radius: 6px; */
+ }
+
+ }
+
+ @media screen and (max-width: 649px) and (min-width: 400px) {
+ #localBKU p {
+ font-size: 0.9em;
+ }
+
+ #localBKU input {
+ font-size: 0.8em;
+ min-width: 70px;
+ /* max-width: 80px; */
+ /* border-radius: 6px; */
+ }
+
+ }
+
+
+
+ @media screen and (max-width: 649px) {
+
+ body {
+ margin:0;
+ padding:0;
+ color : #000;
+ text-align: center;
+ font-size: 100%;
+ background-color: #MAIN_BACKGOUNDCOLOR#;
+ }
+
+ #page {
+ visibility: hidden;
+ margin-top: 0%;
+ }
+
+ #page1 {
+ visibility: hidden;
+ }
+
+ #main {
+ visibility: hidden;
+ }
+
+ #validation {
+ visibility: hidden;
+ display: none;
+ }
+
+ .OA_header {
+ margin-bottom: 0px;
+ margin-top: 0px;
+ font-size: 0pt;
+ visibility: hidden;
+ }
+
+ #leftcontent {
+ visibility: visible;
+ margin-bottom: 0px;
+ text-align: left;
+ border:none;
+ vertical-align: middle;
+ min-height: 173px;
+ min-width: 204px;
+
+ }
+
+ input[type=button] {
+/* height: 11%; */
+ width: 70%;
+ }
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ font-family: #FONTTYPE#;
+ }
+
+ #selectArea {
+ padding-top: 10px;
+ padding-bottom: 55px;
+ padding-left: 10px;
+ }
+
+ .setAssertionButton {
+ background: #efefef;
+ cursor: pointer;
+ margin-top: 15px;
+ width: 70px;
+ height: 25px;
+ }
+
+ #leftbutton {
+ width: 35%;
+ float:left;
+ margin-left: 15px;
+ }
+
+ #rightbutton {
+ width: 35%;
+ float:right;
+ margin-right: 25px;
+ text-align: right;
+ }
+
+/* input[type=button], .sendButton {
+ background: #BUTTON_BACKGROUNDCOLOR#;
+ color: #BUTTON_COLOR#;
+/* border:1px solid #000; */
+/* cursor: pointer;
+/* box-shadow: 3px 3px 3px #222222; */
+/* }
+
+/* button:hover, button:focus, button:active,
+ .sendButton:hover , .sendButton:focus, .sendButton:active,
+ #mandateCheckBox:hover, #mandateCheckBox:focus, #mandateCheckBox:active {
+ background: #BUTTON_BACKGROUNDCOLOR_FOCUS#;
+ color: #BUTTON_COLOR#;
+/* border:1px solid #000; */
+/* cursor: pointer;
+/* box-shadow: -1px -1px 3px #222222; */
+/* }
+
+*/
+ input {
+ /*border:1px solid #000;*/
+ cursor: pointer;
+ }
+
+ #localBKU input {
+/* color: #BUTTON_COLOR#; */
+ border: 0px;
+ display: inline-block;
+
+ }
+
+ #localBKU input:hover, #localBKU input:focus, #localBKU input:active {
+ text-decoration: underline;
+ }
+
+ #installJava, #BrowserNOK {
+ clear:both;
+ font-size:0.8em;
+ padding:4px;
+ }
+
+ .selectText{
+
+ }
+
+ .selectTextHeader{
+
+ }
+
+ .sendButton {
+ width: 30%;
+ margin-bottom: 1%;
+ }
+
+ #leftcontent a {
+ text-decoration:none;
+ color: #000;
+ /* display:block;*/
+ padding:4px;
+ }
+
+ #leftcontent a:hover, #leftcontent a:focus, #leftcontent a:active {
+ text-decoration:underline;
+ color: #000;
+ }
+
+ .infobutton {
+ background-color: #005a00;
+ color: white;
+ font-family: serif;
+ text-decoration: none;
+ padding-top: 2px;
+ padding-right: 4px;
+ padding-bottom: 2px;
+ padding-left: 4px;
+ font-weight: bold;
+ }
+
+ .hell {
+ background-color : #MAIN_BACKGOUNDCOLOR#;
+ color: #MAIN_COLOR#;
+ }
+
+ .dunkel {
+ background-color: #HEADER_BACKGROUNDCOLOR#;
+ color: #HEADER_COLOR#;
+ }
+
+ .main_header {
+ color: black;
+ font-size: 32pt;
+ position: absolute;
+ right: 10%;
+ top: 40px;
+
+ }
+
+ #alert {
+ margin: 100px 250px;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ font-weight: normal;
+ color: red;
+ }
+
+ .reqframe {
+ /*display: none;*/
+ visibility: hidden;
+
+ }
+
+ </style>
+
+ #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 to resume
+ the authentication process after the SSO session transfer from smartphone to application is complete.
+ </p>
+
+ <a href="$timeoutURL">Press this link to resume</a>
+ </noscript>
+
+ <div id="page">
+ <div id="page1" class="case selected-case" role="main">
+ <h2 class="OA_header" role="heading">MOA-ID Single Sign-On Session Transfer Service</h2>
+ <div id="main">
+ <div id="leftcontent" class="hell" role="application">
+
+ #if($errorMsg)
+ <div class="alert">
+ <p>$errorMsg</p>
+ </div>
+ #end
+
+ #if($successMsg)
+ <div>
+ <p>$successMsg</p>
+ </div>
+ #end
+
+ #if($QRImage)
+ <div>
+ <img src="data:image/gif;base64,$QRImage">
+ </div>
+ #end
+
+ </div>
+ </div>
+ </div>
+ <div id="validation">
+ <a href="http://validator.w3.org/check?uri="> <img
+ style="border: 0; width: 88px; height: 31px"
+ src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" />
+ </a> <a href="http://jigsaw.w3.org/css-validator/"> <img
+ style="border: 0; width: 88px; height: 31px"
+ src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
+ alt="CSS ist valide!" />
+ </a>
+ </div>
+ </div>
+
+</body>
+</html> \ No newline at end of file