From cc20e4171331f78a1bb188f2b885c9754da58a28 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Tue, 3 Jun 2014 17:09:42 +0200
Subject: update IDP single logout

---
 .../moa/id/data/SLOInformationContainer.java       | 102 ++++++++++++++-------
 .../moa/id/protocols/pvp2x/MetadataAction.java     |  58 ++++++------
 .../moa/id/protocols/pvp2x/SingleLogOutAction.java |  12 ++-
 .../pvp2x/builder/SingleLogOutBuilder.java         |  19 ++--
 .../id/storage/AuthenticationSessionStoreage.java  |  53 ++++++++---
 5 files changed, 161 insertions(+), 83 deletions(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
index a0f3dd309..df195c0de 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
@@ -29,8 +29,10 @@ import java.util.LinkedHashMap;
 import java.util.List;
 
 import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.core.NameID;
 import org.opensaml.saml2.metadata.SingleLogoutService;
 
+import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
 import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
 import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol;
 import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
@@ -52,47 +54,87 @@ public class SLOInformationContainer implements Serializable {
 	
 	
 	public void parseActiveOAs(List<OASessionStore> dbOAs, String removeOAID) {
-		activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>();
-		activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>();
+		if (activeBackChannelOAs == null)
+			activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>();
+		if (activeFrontChannalOAs == null)
+			activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>();
 		
 		if (dbOAs != null) {
 			for (OASessionStore oa : dbOAs) {
-				//Actually only PVP 2.1 support Single LogOut
-				if (PVP2XProtocol.NAME.equals(oa.getProtocolType()) &&
-						!oa.getOaurlprefix().equals(removeOAID)) {					
+				if (!oa.getOaurlprefix().equals(removeOAID)) {
+					
+					//Actually only PVP 2.1 support Single LogOut
+					if (PVP2XProtocol.PATH.equals(oa.getProtocolType())) {					
+						SingleLogoutService sloDesc;
+						try {
+							sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(oa.getOaurlprefix());
+						
+							if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI))										
+								activeBackChannelOAs.put(oa.getOaurlprefix(), 
+										new SLOInformationImpl(
+											oa.getAssertionSessionID(), 
+											oa.getUserNameID(), 
+											oa.getUserNameIDFormat(), 
+											oa.getProtocolType(),
+											sloDesc));
+						
+							else
+								activeFrontChannalOAs.put(oa.getOaurlprefix(), 
+										new SLOInformationImpl(
+											oa.getAssertionSessionID(), 
+											oa.getUserNameID(), 
+											oa.getUserNameIDFormat(), 
+											oa.getProtocolType(),
+											sloDesc));
+							
+						} catch (NOSLOServiceDescriptorException e) {
+							putFailedOA(oa.getOaurlprefix());
+													
+						}
+					
+					} else
+						putFailedOA(oa.getOaurlprefix());
+				}
+			}			
+		}		
+	}
+
+	/**
+	 * @param dbIDPs
+	 * @param value
+	 */
+	public void parseActiveIDPs(List<InterfederationSessionStore> dbIDPs,
+			String removeIDP) {		
+		if (activeBackChannelOAs == null)
+			activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>();
+		if (activeFrontChannalOAs == null)
+			activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>();
+		
+		if (dbIDPs != null) {
+			for (InterfederationSessionStore el : dbIDPs) {				
+				if (!el.getIdpurlprefix().equals(removeIDP)) {
+					
 					SingleLogoutService sloDesc;
 					try {
-						sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(oa.getOaurlprefix());
-					
-						if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI))										
-							activeBackChannelOAs.put(oa.getOaurlprefix(), 
-									new SLOInformationImpl(
-										oa.getAssertionSessionID(), 
-										oa.getUserNameID(), 
-										oa.getUserNameIDFormat(), 
-										oa.getProtocolType(),
-										sloDesc));
+						sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(el.getIdpurlprefix());
 					
-						else
-							activeFrontChannalOAs.put(oa.getOaurlprefix(), 
-									new SLOInformationImpl(
-										oa.getAssertionSessionID(), 
-										oa.getUserNameID(), 
-										oa.getUserNameIDFormat(), 
-										oa.getProtocolType(),
+						activeFrontChannalOAs.put(el.getIdpurlprefix(), 
+								new SLOInformationImpl(
+										el.getSessionIndex(), 
+										el.getUserNameID(), 
+										NameID.TRANSIENT, 
+										PVP2XProtocol.PATH,
 										sloDesc));
 						
 					} catch (NOSLOServiceDescriptorException e) {
-						putFailedOA(oa.getOaurlprefix());
+						putFailedOA(el.getIdpurlprefix());
 												
 					}
-					
-				} else
-					putFailedOA(oa.getOaurlprefix());
+				}				
 			}			
 		}		
 	}
-		
+	
 	public String getNextFrontChannelOA() {
 		Iterator<String> interator = activeFrontChannalOAs.keySet().iterator();
 		if (interator.hasNext())
@@ -147,9 +189,5 @@ public class SLOInformationContainer implements Serializable {
 		if (sloFailedOAs == null)
 			sloFailedOAs = new ArrayList<String>();
 		sloFailedOAs.add(oaID);
-	}
-
-
-	
-	
+	}	
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
index 01f7e18ba..c60e69df6 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
@@ -258,21 +258,21 @@ public class MetadataAction implements IAction {
 		
 		
 		//add SLO descriptor
-//		SingleLogoutService postSLOService = 
-//				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-//		postSLOService.setLocation(PVPConfiguration
-//				.getInstance().getIDPSSOPostService());
-//		postSLOService
-//				.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
-//		spSSODescriptor.getSingleLogoutServices().add(postSLOService);
-//		
-//		SingleLogoutService redirectSLOService = 
-//				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-//		redirectSLOService.setLocation(PVPConfiguration
-//				.getInstance().getIDPSSOPostService());
-//		redirectSLOService
-//				.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
-//		spSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
+		SingleLogoutService postSLOService = 
+				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+		postSLOService.setLocation(PVPConfiguration
+				.getInstance().getIDPSSOPostService());
+		postSLOService
+				.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+		spSSODescriptor.getSingleLogoutServices().add(postSLOService);
+		
+		SingleLogoutService redirectSLOService = 
+				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+		redirectSLOService.setLocation(PVPConfiguration
+				.getInstance().getIDPSSOPostService());
+		redirectSLOService
+				.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+		spSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
 		
 		
 		spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
@@ -333,13 +333,13 @@ public class MetadataAction implements IAction {
 					postSingleSignOnService);
 			
 			//add SLO descriptor
-//			SingleLogoutService postSLOService = 
-//					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-//			postSLOService.setLocation(PVPConfiguration
-//					.getInstance().getIDPSSOPostService());
-//			postSLOService
-//					.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
-//			idpSSODescriptor.getSingleLogoutServices().add(postSLOService);
+			SingleLogoutService postSLOService = 
+					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+			postSLOService.setLocation(PVPConfiguration
+					.getInstance().getIDPSSOPostService());
+			postSLOService
+					.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+			idpSSODescriptor.getSingleLogoutServices().add(postSLOService);
 			
 		}
 
@@ -355,13 +355,13 @@ public class MetadataAction implements IAction {
 					redirectSingleSignOnService);
 			
 			//add SLO descriptor
-//			SingleLogoutService redirectSLOService = 
-//					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-//			redirectSLOService.setLocation(PVPConfiguration
-//					.getInstance().getIDPSSOPostService());
-//			redirectSLOService
-//					.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
-//			idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
+			SingleLogoutService redirectSLOService = 
+					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+			redirectSLOService.setLocation(PVPConfiguration
+					.getInstance().getIDPSSORedirectService());
+			redirectSLOService
+					.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+			idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
 		}
 
 		/*if (PVPConfiguration.getInstance().getIDPResolveSOAPService() != null) {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
index c67d10ab7..92441e663 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
@@ -42,6 +42,7 @@ import org.opensaml.xml.security.SecurityException;
 
 import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
 import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
 import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
@@ -124,9 +125,11 @@ public class SingleLogOutAction implements IAction {
 				}
 
 				//store active OAs to SLOContaine
-				List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);				
+				List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);
+				List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session);
 				SLOInformationContainer sloContainer = new SLOInformationContainer();
 				sloContainer.setSloRequest(pvpReq);
+				sloContainer.parseActiveIDPs(dbIDPs, logOutReq.getIssuer().getValue());
 				sloContainer.parseActiveOAs(dbOAs, logOutReq.getIssuer().getValue());
 								
 				//terminate MOASession
@@ -247,10 +250,13 @@ public class SingleLogOutAction implements IAction {
 	
 	private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) {
 		Status status = logOutResp.getStatus();				
-		if (!status.getStatusCode().equals(StatusCode.SUCCESS_URI)) {
+		if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
+			String message = " Message: ";
+			if (status.getStatusMessage() != null) 
+				message += status.getStatusMessage().getMessage();
 			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue()
 					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue()
-					+ " Message: " + status.getStatusMessage().getMessage() + ")");
+					+ message + ")");
 			sloContainer.putFailedOA(logOutResp.getIssuer().getValue());
 			
 		} else
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
index 04d374e93..7aa860c5c 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
@@ -35,6 +35,7 @@ import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.saml2.core.StatusMessage;
 import org.opensaml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.SSODescriptor;
 import org.opensaml.saml2.metadata.SingleLogoutService;
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 
@@ -125,7 +126,7 @@ public class SingleLogOutBuilder {
 	public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException {
 		try {
 			EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID);
-			SPSSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+			SSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
 			
 			SingleLogoutService sloService = null;			
 			for (SingleLogoutService el : spsso.getSingleLogoutServices()) {
@@ -173,14 +174,18 @@ public class SingleLogOutBuilder {
 			if (el.getBinding().equals(spRequest.getBinding()))
 				sloService = el;
 		}
-		if (sloService == null && spsso.getSingleLogoutServices().size() != 0)
-			sloService = spsso.getSingleLogoutServices().get(0);
 		
-		else {
-			Logger.error("Found no SLO ServiceDescriptor in Metadata");				
-			throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null);
+		if (sloService == null)  {
+			if (spsso.getSingleLogoutServices().size() != 0)		
+				sloService = spsso.getSingleLogoutServices().get(0);
+		
+			else {
+				Logger.error("Found no SLO ServiceDescriptor in Metadata");				
+				throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null);
+			}
 		}
-		return sloService;
+		
+		return sloService;		
 	}
 	
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
index 6c2900752..5daca0888 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
@@ -64,7 +64,7 @@ public class AuthenticationSessionStoreage {
 		AuthenticatedSessionStore session;
 		
 		try {
-			session = searchInDatabase(moaSessionID);
+			session = searchInDatabase(moaSessionID, true);
 			return session.isAuthenticated();
 			
 		} catch (MOADatabaseException e) {
@@ -102,7 +102,7 @@ public class AuthenticationSessionStoreage {
 	public static AuthenticationSession getSession(String sessionID) throws MOADatabaseException {
 		
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID);
+			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true);
 			return decryptSession(dbsession);
 								
 		} catch (MOADatabaseException e) {
@@ -122,7 +122,7 @@ public class AuthenticationSessionStoreage {
 	public static void storeSession(AuthenticationSession session, String pendingRequestID) throws MOADatabaseException, BuildException {
 		
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID());
+			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true);
 			
 			if (MiscUtil.isNotEmpty(pendingRequestID))
 				dbsession.setPendingRequestID(pendingRequestID);
@@ -175,7 +175,7 @@ public class AuthenticationSessionStoreage {
 			throws AuthenticationException, BuildException {
 		
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID());
+			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true);
 			
 			String id = Random.nextRandom();
 			
@@ -207,7 +207,7 @@ public class AuthenticationSessionStoreage {
 		AuthenticatedSessionStore session;
 		
 		try {
-			session = searchInDatabase(moaSessionID);
+			session = searchInDatabase(moaSessionID, true);
 			session.setAuthenticated(value);
 			MOASessionDBUtils.saveOrUpdate(session);
 
@@ -249,7 +249,7 @@ public class AuthenticationSessionStoreage {
 	
 	public static boolean isSSOSession(String sessionID) throws MOADatabaseException {
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID);
+			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true);
 			return dbsession.isSSOSession();
 			
 		} catch (MOADatabaseException e) {
@@ -391,8 +391,36 @@ public class AuthenticationSessionStoreage {
 		MiscUtil.assertNotNull(moaSession, "MOASession");
 		
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID());
-			return dbsession.getActiveOAsessions();
+			List<OASessionStore> oas = new ArrayList<OASessionStore>();
+			
+			AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID(), false);
+			oas.addAll(dbsession.getActiveOAsessions());
+			
+			Session session = MOASessionDBUtils.getCurrentSession();
+			session.getTransaction().commit();
+			
+			return oas;
+			
+		} catch (MOADatabaseException e) {
+			Logger.warn("NO session information found for sessionID " + moaSession.getSessionID(), e);
+			
+		}
+				
+		return null;
+	}
+	
+	public static List<InterfederationSessionStore> getAllActiveIDPsFromMOASession(AuthenticationSession moaSession) {
+		MiscUtil.assertNotNull(moaSession, "MOASession");
+		
+		try {
+			List<InterfederationSessionStore> idps = new ArrayList<InterfederationSessionStore>();			
+			AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID(), false);
+			idps.addAll(dbsession.getInderfederation());
+			
+			Session session = MOASessionDBUtils.getCurrentSession();
+			session.getTransaction().commit();
+			
+			return idps;
 			
 		} catch (MOADatabaseException e) {
 			Logger.warn("NO session information found for sessionID " + moaSession.getSessionID(), e);
@@ -475,7 +503,7 @@ public class AuthenticationSessionStoreage {
 	
 	public static String getPendingRequestID(String sessionID) {
 		try {
-			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID);
+			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true);
 			return dbsession.getPendingRequestID();
 			
 		} catch (MOADatabaseException e) {
@@ -654,7 +682,7 @@ public class AuthenticationSessionStoreage {
 			String moaSession = getMOASessionSSOID(ssoID);		
 			if (MiscUtil.isNotEmpty(moaSession)) {
 				try {
-					dbsession = searchInDatabase(moaSession);
+					dbsession = searchInDatabase(moaSession, true);
 				
 				}catch (MOADatabaseException e) {
 				
@@ -889,7 +917,7 @@ public class AuthenticationSessionStoreage {
 	}
 	
 	@SuppressWarnings("rawtypes")
-	private static AuthenticatedSessionStore searchInDatabase(String sessionID) throws MOADatabaseException {
+	private static AuthenticatedSessionStore searchInDatabase(String sessionID, boolean commit) throws MOADatabaseException {
 		  MiscUtil.assertNotNull(sessionID, "moasessionID");	  
 		  Logger.trace("Get authenticated session with sessionID " + sessionID + " from database.");
 		  Session session = MOASessionDBUtils.getCurrentSession();
@@ -903,7 +931,8 @@ public class AuthenticationSessionStoreage {
 			  result = query.list();
 			  
 			  //send transaction
-			  session.getTransaction().commit();
+			  if (commit)
+				  session.getTransaction().commit();
 		  }
 		  
 		  Logger.trace("Found entries: " + result.size());
-- 
cgit v1.2.3


From 985bb947881f880216c97fda93491a305f33c6de Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Thu, 5 Jun 2014 16:27:18 +0200
Subject: add SSO session timeout to AuthData and SAML2 assertion

---
 .../id/auth/builder/AuthenticationDataBuilder.java | 22 +++++++++++--
 .../moa/id/auth/data/AuthenticationSession.java    | 14 +++++++-
 .../moa/id/data/AuthenticationData.java            | 17 ++++++++++
 .../at/gv/egovernment/moa/id/data/IAuthData.java   |  2 ++
 .../builder/assertion/PVP2AssertionBuilder.java    | 18 +++++------
 .../id/storage/AuthenticationSessionStoreage.java  | 37 +++++++++++-----------
 6 files changed, 80 insertions(+), 30 deletions(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
index 632227d79..c0e1dd3ca 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
@@ -27,6 +27,8 @@ import iaik.x509.X509Certificate;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.GregorianCalendar;
 import java.util.List;
 
 import javax.naming.ldap.LdapName;
@@ -445,6 +447,9 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
 		
 		authData.setSsoSession(true);
 		
+		if (assertion.getConditions() != null && assertion.getConditions().getNotOnOrAfter() != null)
+			authData.setSsoSessionValidTo(assertion.getConditions().getNotOnOrAfter().toDate());
+		
 		//only for SAML1
 		if (PVPConstants.STORK_QAA_1_4.equals(authData.getQAALevel()))
 			authData.setQualifiedCertificate(true);
@@ -454,7 +459,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
 	}
 	
 	private static void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session, 
-			IOAAuthParameters oaParam) throws BuildException {
+			IOAAuthParameters oaParam) throws BuildException, ConfigurationException {
 
 		String target = oaParam.getTarget();
 		
@@ -465,7 +470,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
 		boolean businessService = oaParam.getBusinessService();
 
 		authData.setIssuer(session.getAuthURL());
-
+				
 		//baseID or wbpk in case of BusinessService without SSO or BusinessService SSO
 		authData.setIdentificationValue(identityLink.getIdentificationValue());
 		authData.setIdentificationType(identityLink.getIdentificationType());
@@ -529,6 +534,19 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {
 
 			authData.setSsoSession(AuthenticationSessionStoreage.isSSOSession(session.getSessionID()));
 			
+			//set max. SSO session time
+			if (authData.isSsoSession()) {
+				long maxSSOSessionTime = AuthConfigurationProvider.getInstance().getTimeOuts().getMOASessionCreated().longValue() * 1000;		
+				Date ssoSessionValidTo = new Date(session.getSessionCreated().getTime() + maxSSOSessionTime);
+				authData.setSsoSessionValidTo(ssoSessionValidTo);
+				
+			} else {
+				//set valid to 5 min
+				Date ssoSessionValidTo = new Date(new Date().getTime() + 5 * 60 * 1000);
+				authData.setSsoSessionValidTo(ssoSessionValidTo);
+				
+			}
+			
 			
 			/* TODO: Support SSO Mandate MODE!
 			 * Insert functionality to translate mandates in case of SSO  
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
index c5ba49b2e..8726c1618 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
@@ -42,6 +42,7 @@ import java.io.Serializable;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Vector;
@@ -78,6 +79,9 @@ public class AuthenticationSession implements Serializable {
 	 * session ID
 	 */
 	private String sessionID;
+	
+	private Date sessionCreated = null;
+	
 	/**
 	 * "Gesch&auml;ftsbereich" the online application belongs to; maybe <code>null</code> if the
 	 * online application is a business application
@@ -344,8 +348,9 @@ public class AuthenticationSession implements Serializable {
 	 * @param id
 	 *            Session ID
 	 */
-	public AuthenticationSession(String id) {
+	public AuthenticationSession(String id, Date created) {
 		sessionID = id;
+		sessionCreated = created;
 		// setTimestampStart();
 //		infoboxValidators = new ArrayList();
 	}
@@ -1050,6 +1055,13 @@ public class AuthenticationSession implements Serializable {
 		this.storkAuthnResponse = storkAuthnResponse;
 	}
 
+	/**
+	 * @return the sessionCreated
+	 */
+	public Date getSessionCreated() {
+		return sessionCreated;
+	}
+
 	
 	
 	
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
index 33e62d3d0..5685977bc 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java
@@ -135,6 +135,7 @@ public class AuthenticationData  implements IAuthData, Serializable {
 	  private String QAALevel = null;
 	  
 	  private boolean ssoSession = false;
+	  private Date ssoSessionValidTo = null;
 
 	  private boolean interfederatedSSOSession = false;
 	  private String interfederatedIDP = null;
@@ -656,7 +657,23 @@ public class AuthenticationData  implements IAuthData, Serializable {
 	public void setInterfederatedIDP(String interfederatedIDP) {
 		this.interfederatedIDP = interfederatedIDP;
 	}
+
+	/**
+	 * @return the ssoSessionValidTo
+	 */
+	public Date getSsoSessionValidTo() {
+		return ssoSessionValidTo;
+	}
+
+	/**
+	 * @param ssoSessionValidTo the ssoSessionValidTo to set
+	 */
+	public void setSsoSessionValidTo(Date ssoSessionValidTo) {
+		this.ssoSessionValidTo = ssoSessionValidTo;
+	}
+
 	
+
 	
 	
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
index 4ea81f134..7e421da0f 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java
@@ -53,6 +53,8 @@ public interface IAuthData {
 	 String getBPK();
 	 String getBPKType();
 	 
+	 Date getSsoSessionValidTo();
+	 
 	 String getInterfederatedIDP();
 	 
 	 String getIdentificationValue();
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java
index 4d6343fce..fa5d252bd 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java
@@ -135,7 +135,8 @@ public class PVP2AssertionBuilder implements PVPConstants {
 		SubjectConfirmationData subjectConfirmationData = null;
 		
 		return buildGenericAssertion(attrQuery.getIssuer().getValue(), date, 
-				authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex);
+				authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex,
+				new DateTime(authData.getSsoSessionValidTo().getTime()));
 	}
 		
 	public static Assertion buildAssertion(AuthnRequest authnRequest,
@@ -393,8 +394,8 @@ public class PVP2AssertionBuilder implements PVPConstants {
 		SubjectConfirmationData subjectConfirmationData = SAML2Utils
 				.createSAMLObject(SubjectConfirmationData.class);
 		subjectConfirmationData.setInResponseTo(authnRequest.getID());
-		subjectConfirmationData.setNotOnOrAfter(date.plusMinutes(5));
-				
+		subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime()));
+		
 		subjectConfirmationData.setRecipient(assertionConsumerService.getLocation());
 		
 		//set SLO information
@@ -402,13 +403,13 @@ public class PVP2AssertionBuilder implements PVPConstants {
 		sloInformation.setNameIDFormat(subjectNameID.getFormat());
 		sloInformation.setSessionIndex(sessionIndex);
 		
-		return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex);
+		return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter());
 	}
 	
 	private static Assertion buildGenericAssertion(String entityID, DateTime date, 
 			AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, 
 			NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, 
-			String sessionIndex) throws ConfigurationException {
+			String sessionIndex, DateTime isValidTo) throws ConfigurationException {
 		Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class);
 		
 		AuthnContext authnContext = SAML2Utils
@@ -448,10 +449,9 @@ public class PVP2AssertionBuilder implements PVPConstants {
 		
 		audience.setAudienceURI(entityID);
 		audienceRestriction.getAudiences().add(audience);
-		conditions.setNotBefore(date);
-		
-		conditions.setNotOnOrAfter(date.plusMinutes(5));
-		
+		conditions.setNotBefore(date);		
+		conditions.setNotOnOrAfter(isValidTo);
+				
 		conditions.getAudienceRestrictions().add(audienceRestriction);
 
 		assertion.setConditions(conditions);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
index 5daca0888..1c74aea55 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java
@@ -72,19 +72,20 @@ public class AuthenticationSessionStoreage {
 		}
 	}
 
-	public static AuthenticationSession createSession() throws MOADatabaseException {
+	public static AuthenticationSession createSession() throws MOADatabaseException, BuildException {
 		String id = Random.nextRandom();
-		AuthenticationSession session = new AuthenticationSession(id);
-		
+
 		AuthenticatedSessionStore dbsession = new AuthenticatedSessionStore();
 		dbsession.setSessionid(id);
 		dbsession.setAuthenticated(false);
 		
-		//set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 
-		dbsession.setCreated(new Date());
-		dbsession.setUpdated(new Date());
+		//set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1
+		Date now = new Date();
+		dbsession.setCreated(now);
+		dbsession.setUpdated(now);
 		
-		dbsession.setSession(SerializationUtils.serialize(session));
+		AuthenticationSession session = new AuthenticationSession(id, now);
+		encryptSession(session, dbsession);
 		
 		//store AssertionStore element to Database
 		try {
@@ -674,7 +675,7 @@ public class AuthenticationSessionStoreage {
 		  return result.get(0).getInderfederation().get(0);
 	}
 	
-	public static String createInterfederatedSession(IRequest req, boolean isAuthenticated, String ssoID) throws MOADatabaseException, AssertionAttributeExtractorExeption {		
+	public static String createInterfederatedSession(IRequest req, boolean isAuthenticated, String ssoID) throws MOADatabaseException, AssertionAttributeExtractorExeption, BuildException {		
 		AuthenticatedSessionStore dbsession = null;
 		
 		//search for active SSO session
@@ -692,28 +693,28 @@ public class AuthenticationSessionStoreage {
 		
 		String id = null;
 		Date now = new Date();
-		
 		//create new MOASession if any exists
+		AuthenticationSession session = null;
 		if (dbsession == null) {
 			id = Random.nextRandom();
 			dbsession = new AuthenticatedSessionStore();
 			dbsession.setSessionid(id);
 			dbsession.setCreated(now);
-			
+			session = new AuthenticationSession(id, now);
+		
 		} else {
 			id = dbsession.getSessionid();
-			
+			session = decryptSession(dbsession);
+		
 		}
-				
+			
 		dbsession.setInterfederatedSSOSession(true);
 		dbsession.setAuthenticated(isAuthenticated);
-		dbsession.setUpdated(now);
-		
-		AuthenticationSession session = new AuthenticationSession(id);
+		dbsession.setUpdated(now);		
 		session.setAuthenticated(true);
-		session.setAuthenticatedUsed(false);
-		dbsession.setSession(SerializationUtils.serialize(session));
-		
+		session.setAuthenticatedUsed(false);		
+		encryptSession(session, dbsession);
+			
 		//add interfederation information
 		List<InterfederationSessionStore> idpList = dbsession.getInderfederation();
 		InterfederationSessionStore idp = null;
-- 
cgit v1.2.3


From c8a872dcffe918d9ed1e867cb9fc18f639a715b4 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Fri, 6 Jun 2014 07:06:20 +0200
Subject: only use redirectBinding for inbound SLO

---
 .../moa/id/protocols/pvp2x/MetadataAction.java     | 30 +++++++++++-----------
 1 file changed, 15 insertions(+), 15 deletions(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
index c60e69df6..1085e4cbc 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
@@ -253,18 +253,18 @@ public class MetadataAction implements IAction {
 		redirectassertionConsumerService.setIndex(1);
 		redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
 		redirectassertionConsumerService.setLocation(PVPConfiguration
-				.getInstance().getIDPSSORedirectService());		
+				.getInstance().getIDPSSORedirectService());
 		spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService);
 		
 		
 		//add SLO descriptor
-		SingleLogoutService postSLOService = 
-				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-		postSLOService.setLocation(PVPConfiguration
-				.getInstance().getIDPSSOPostService());
-		postSLOService
-				.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
-		spSSODescriptor.getSingleLogoutServices().add(postSLOService);
+//		SingleLogoutService postSLOService = 
+//				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+//		postSLOService.setLocation(PVPConfiguration
+//				.getInstance().getIDPSSOPostService());
+//		postSLOService
+//				.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+//		spSSODescriptor.getSingleLogoutServices().add(postSLOService);
 		
 		SingleLogoutService redirectSLOService = 
 				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
@@ -333,13 +333,13 @@ public class MetadataAction implements IAction {
 					postSingleSignOnService);
 			
 			//add SLO descriptor
-			SingleLogoutService postSLOService = 
-					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
-			postSLOService.setLocation(PVPConfiguration
-					.getInstance().getIDPSSOPostService());
-			postSLOService
-					.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
-			idpSSODescriptor.getSingleLogoutServices().add(postSLOService);
+//			SingleLogoutService postSLOService = 
+//					SAML2Utils.createSAMLObject(SingleLogoutService.class);			
+//			postSLOService.setLocation(PVPConfiguration
+//					.getInstance().getIDPSSOPostService());
+//			postSLOService
+//					.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+//			idpSSODescriptor.getSingleLogoutServices().add(postSLOService);
 			
 		}
 
-- 
cgit v1.2.3


From 5677982c24ada5c0a56e11588b5839bc2a75b83e Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Fri, 6 Jun 2014 13:47:15 +0200
Subject: use different endpoints for IDP and interfederation SP

---
 .../moa/id/protocols/pvp2x/MetadataAction.java     |  6 +--
 .../moa/id/protocols/pvp2x/PVP2XProtocol.java      | 59 ++++++++++++++++------
 .../protocols/pvp2x/binding/ArtifactBinding.java   |  2 +-
 .../moa/id/protocols/pvp2x/binding/IDecoder.java   |  2 +-
 .../id/protocols/pvp2x/binding/PostBinding.java    | 33 ++++++------
 .../protocols/pvp2x/binding/RedirectBinding.java   | 31 ++++++------
 .../id/protocols/pvp2x/binding/SoapBinding.java    |  2 +-
 .../protocols/pvp2x/config/PVPConfiguration.java   | 36 ++++++++-----
 8 files changed, 103 insertions(+), 68 deletions(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
index 1085e4cbc..fec8e3b98 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java
@@ -244,7 +244,7 @@ public class MetadataAction implements IAction {
 		postassertionConsumerService.setIndex(0);
 		postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
 		postassertionConsumerService.setLocation(PVPConfiguration
-				.getInstance().getIDPSSOPostService());	
+				.getInstance().getSPSSOPostService());	
 		postassertionConsumerService.setIsDefault(true);
 		spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService);
 				
@@ -253,7 +253,7 @@ public class MetadataAction implements IAction {
 		redirectassertionConsumerService.setIndex(1);
 		redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
 		redirectassertionConsumerService.setLocation(PVPConfiguration
-				.getInstance().getIDPSSORedirectService());
+				.getInstance().getSPSSORedirectService());
 		spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService);
 		
 		
@@ -269,7 +269,7 @@ public class MetadataAction implements IAction {
 		SingleLogoutService redirectSLOService = 
 				SAML2Utils.createSAMLObject(SingleLogoutService.class);			
 		redirectSLOService.setLocation(PVPConfiguration
-				.getInstance().getIDPSSOPostService());
+				.getInstance().getSPSSORedirectService());
 		redirectSLOService
 				.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
 		spSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java
index d9ce6250a..7f8ea91bd 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java
@@ -111,6 +111,11 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 	public static final String ATTRIBUTEQUERY = "AttributeQuery";
 	public static final String SINGLELOGOUT = "SingleLogOut";
 
+	public static final String ENDPOINT_IDP = "idp";
+	public static final String ENDPOINT_SP = "sp";
+	
+	public static final String PARAMETER_ENDPOINT = "endpointtype";
+	
 	private static List<IDecoder> decoder = new ArrayList<IDecoder>();
 
 	private static HashMap<String, IAction> actions = new HashMap<String, IAction>();
@@ -168,6 +173,23 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 		return null;
 	}
 
+	private boolean isServiceProviderEndPointUsed(HttpServletRequest req) throws InvalidProtocolRequestException {
+		Object obj = req.getParameter(PARAMETER_ENDPOINT);
+		if (obj instanceof String) {
+			String param = (String) obj;
+			if (MiscUtil.isNotEmpty(param)) {
+				if (ENDPOINT_IDP.equals(param))
+					return false;
+				
+				else if (ENDPOINT_SP.equals(param))
+					return true;
+			}			
+		}
+		
+		Logger.error("No valid PVP 2.1 entpoint descriptor");
+		throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
+	}
+	
 	public PVP2XProtocol() {
 		super();
 	}
@@ -193,7 +215,8 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 			return null;
 		}
 		try {
-			InboundMessage msg = (InboundMessage) decoder.decode(request, response);
+						
+			InboundMessage msg = (InboundMessage) decoder.decode(request, response, isServiceProviderEndPointUsed(request));
 			
 			if (MiscUtil.isEmpty(msg.getEntityID())) {
 				throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
@@ -217,13 +240,14 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 
 			else if (msg instanceof MOARequest && 
 					((MOARequest)msg).getSamlRequest() instanceof LogoutRequest)
-				return preProcessLogOut(request, response, (MOARequest) msg);
+				return preProcessLogOut(request, response, msg);
 			
-			else if (msg instanceof MOARequest && 
-					((MOARequest)msg).getSamlRequest() instanceof LogoutResponse)
-				return preProcessLogOut(request, response, (MOARequest) msg);
+			else if (msg instanceof MOAResponse && 
+					((MOAResponse)msg).getResponse() instanceof LogoutResponse)
+				return preProcessLogOut(request, response, msg);
 			
-			else if (msg instanceof MOAResponse) {
+			else if (msg instanceof MOAResponse &&
+					((MOAResponse)msg).getResponse() instanceof Response) {
 				//load service provider AuthRequest from session
 											
 				IRequest obj = RequestStorage.getPendingRequest(msg.getRelayState());
@@ -420,20 +444,22 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 	 * @throws MOAIDException 
 	 */
 	private IRequest preProcessLogOut(HttpServletRequest request,
-			HttpServletResponse response, MOARequest msg) throws MOAIDException {
+			HttpServletResponse response, InboundMessage inMsg) throws MOAIDException {
 
 		PVPTargetConfiguration config = new PVPTargetConfiguration();
 		
-		if (((MOARequest)msg).getSamlRequest() instanceof LogoutRequest) {
+		MOARequest msg;
+		if (inMsg instanceof MOARequest && 
+				((MOARequest)inMsg).getSamlRequest() instanceof LogoutRequest) {
 			//preProcess single logout request from service provider
-					
+			
+			msg = (MOARequest) inMsg;
+			
 			EntityDescriptor metadata = msg.getEntityMetadata();
 			if(metadata == null) {
 				throw new NoMetadataInformationException();
 			}
 
-
-			
 			String oaURL = metadata.getEntityID();
 			oaURL = StringEscapeUtils.escapeHtml(oaURL);
 			
@@ -443,10 +469,11 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 			config.setBinding(msg.getRequestBinding());									
 
 						
-		} else if (((MOARequest)msg).getSamlRequest() instanceof LogoutResponse) {
+		} else if (inMsg instanceof MOAResponse && 
+				((MOAResponse)inMsg).getResponse() instanceof LogoutResponse) {
 			//preProcess single logour response from service provider
 						
-			LogoutResponse resp = (LogoutResponse) (((MOARequest)msg).getSamlRequest());
+			LogoutResponse resp = (LogoutResponse) (((MOAResponse)inMsg).getResponse());
 			
 			Logger.debug("PreProcess SLO Response from " + resp.getIssuer());
 			
@@ -458,14 +485,14 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 			}
 						
 			//TODO: check if relayState exists
-			msg.getRelayState();
+			inMsg.getRelayState();
 						
 						
 		} else 
 			throw new MOAIDException("Unsupported request", new Object[] {});
 		
 		
-		config.setRequest(msg);
+		config.setRequest(inMsg);
 		config.setAction(SINGLELOGOUT);
 		return config;
 	}
@@ -624,7 +651,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {
 	 */
 	private MOAResponse preProcessAuthResponse(MOAResponse msg) {
 		Logger.debug("Start PVP21 assertion processing... ");
-		Response samlResp = msg.getResponse();
+		Response samlResp = (Response) msg.getResponse();
 		
 		try {
 			if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java
index 8691667f0..4d353ffcd 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java
@@ -102,7 +102,7 @@ public class ArtifactBinding implements IDecoder, IEncoder {
 	}
 
 	public InboundMessageInterface decode(HttpServletRequest req,
-			HttpServletResponse resp) throws MessageDecodingException,
+			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,
 			SecurityException {
 
 		return null;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java
index fb17c02b8..6619876dc 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java
@@ -33,7 +33,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface
 
 public interface IDecoder {
 	public InboundMessageInterface decode(HttpServletRequest req, 
-			HttpServletResponse resp)
+			HttpServletResponse resp, boolean isSPEndPoint)
 					throws MessageDecodingException, SecurityException, PVP2Exception;
 		
 	public boolean handleDecode(String action, HttpServletRequest req);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java
index a2fe5c01b..7f73b1ed7 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java
@@ -139,7 +139,7 @@ public class PostBinding implements IDecoder, IEncoder {
 	}
 
 	public InboundMessageInterface decode(HttpServletRequest req,
-			HttpServletResponse resp) throws MessageDecodingException,
+			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,
 			SecurityException {
 
 		HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool());
@@ -152,39 +152,38 @@ public class PostBinding implements IDecoder, IEncoder {
 		} catch (ConfigurationException e) {
 			throw new SecurityException(e);
 		}
-		
-		decode.decode(messageContext);		
-				
+							
 		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance());
 		
-		InboundMessage msg = null;
+		//set metadata descriptor type
+		if (isSPEndPoint)
+			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+		else
+			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
 		
-		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
-			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);			
-			
+		decode.decode(messageContext);
+		
+		InboundMessage msg = null;		
+		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {			
 			RequestAbstractType inboundMessage = (RequestAbstractType) messageContext
 					.getInboundMessage();			
 			msg = new MOARequest(inboundMessage, getSAML2BindingName());
 			
-		} else if (messageContext.getInboundMessage() instanceof Response){
-			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
-			
-			Response inboundMessage = (Response) messageContext.getInboundMessage();			
+		} else if (messageContext.getInboundMessage() instanceof StatusResponseType){
+			StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();			
 			msg = new MOAResponse(inboundMessage);
 			
 		} else
 			//create empty container if request type is unknown
 			msg = new InboundMessage();
-		
-		msg.setVerified(false);
-		
-		decode.decode(messageContext);
+				
 		if (messageContext.getPeerEntityMetadata() != null)
 			msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
 		
 		else
 			Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
-				
+		
+		msg.setVerified(false);
 		msg.setRelayState(messageContext.getRelayState());
 		
 		return msg;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java
index 8fba6cde0..26f6f3a62 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java
@@ -129,7 +129,7 @@ public class RedirectBinding implements IDecoder, IEncoder {
 	}
 
 	public InboundMessageInterface decode(HttpServletRequest req,
-			HttpServletResponse resp) throws MessageDecodingException,
+			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,
 			SecurityException {
 
 		HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(
@@ -146,8 +146,6 @@ public class RedirectBinding implements IDecoder, IEncoder {
 		BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
 		messageContext
 				.setInboundMessageTransport(new HttpServletRequestAdapter(req));
-
-		decode.decode(messageContext);
 					
 		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance());
 				
@@ -161,36 +159,39 @@ public class RedirectBinding implements IDecoder, IEncoder {
 				policy);		
 		messageContext.setSecurityPolicyResolver(resolver);
 		
-		InboundMessage msg = null;
-		
-		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
+		//set metadata descriptor type
+		if (isSPEndPoint)
+			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+		else
 			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
-			
+		
+		decode.decode(messageContext);
+
+		//check signature
+		signatureRule.evaluate(messageContext);		
+
+		InboundMessage msg = null;
+		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {			
 			RequestAbstractType inboundMessage = (RequestAbstractType) messageContext
 					.getInboundMessage();			
 			msg = new MOARequest(inboundMessage, getSAML2BindingName());
 			
 			
-		} else if (messageContext.getInboundMessage() instanceof Response){
-			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
-			
-			Response inboundMessage = (Response) messageContext.getInboundMessage();			
+		} else if (messageContext.getInboundMessage() instanceof StatusResponseType){
+			StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();			
 			msg = new MOAResponse(inboundMessage);
 			
 		} else 
 			//create empty container if request type is unknown
 			msg = new InboundMessage();
 
-		signatureRule.evaluate(messageContext);		
-		msg.setVerified(true);
-
-		decode.decode(messageContext);
 		if (messageContext.getPeerEntityMetadata() != null)
 			msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
 		
 		else
 			Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
 		
+		msg.setVerified(true);
 		msg.setRelayState(messageContext.getRelayState());
 		
 		return msg;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java
index 75332cfea..f0eafe272 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java
@@ -59,7 +59,7 @@ import at.gv.egovernment.moa.logging.Logger;
 public class SoapBinding implements IDecoder, IEncoder {
 
 	public InboundMessageInterface decode(HttpServletRequest req,
-			HttpServletResponse resp) throws MessageDecodingException,
+			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,
 			SecurityException, PVP2Exception {
 		HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool());
 		BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = 
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java
index 255fba093..d3a9ad3e7 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java
@@ -33,7 +33,6 @@ import java.util.Properties;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
 
-import org.opensaml.Configuration;
 import org.opensaml.saml2.metadata.Company;
 import org.opensaml.saml2.metadata.ContactPerson;
 import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration;
@@ -46,7 +45,6 @@ import org.opensaml.saml2.metadata.OrganizationName;
 import org.opensaml.saml2.metadata.OrganizationURL;
 import org.opensaml.saml2.metadata.SurName;
 import org.opensaml.saml2.metadata.TelephoneNumber;
-import org.opensaml.xml.security.SecurityConfiguration;
 
 import at.gv.egovernment.moa.id.commons.db.dao.config.Contact;
 import at.gv.egovernment.moa.id.commons.db.dao.config.OAPVP2;
@@ -71,10 +69,12 @@ public class PVPConfiguration {
 	}
 
 	public static final String PVP2_METADATA = 	"/pvp2/metadata";
-	public static final String PVP2_REDIRECT = 	"/pvp2/redirect";
-	public static final String PVP2_POST = 		"/pvp2/post";
-	public static final String PVP2_SOAP = 		"/pvp2/soap";
-	public static final String PVP2_ATTRIBUTEQUERY = "/pvp2/attributequery";
+	public static final String PVP2_IDP_REDIRECT = 	"/pvp2/redirect";
+	public static final String PVP2_IDP_POST = 		"/pvp2/post";
+	public static final String PVP2_IDP_SOAP = 		"/pvp2/soap";
+	public static final String PVP2_IDP_ATTRIBUTEQUERY = "/pvp2/attributequery";
+	public static final String PVP2_SP_REDIRECT = 	"/pvp2/sp/redirect";
+	public static final String PVP2_SP_POST = 		"/pvp2/sp/post";
 	
 	public static final String PVP_CONFIG_FILE = "pvp2config.properties";
 	
@@ -143,22 +143,30 @@ public class PVPConfiguration {
 		return publicPath;
 	}
 
-	public String getIDPSSOPostService() throws ConfigurationException {
-		return getIDPPublicPath() + PVP2_POST;
+	public String getSPSSOPostService() throws ConfigurationException {
+		return getIDPPublicPath() + PVP2_SP_POST;
 	}
 
-	public String getIDPSSOSOAPService() throws ConfigurationException {
-		return getIDPPublicPath() + PVP2_SOAP;
+	public String getSPSSORedirectService() throws ConfigurationException {
+		return getIDPPublicPath() + PVP2_SP_REDIRECT;
 	}
 	
-	public String getIDPAttributeQueryService() throws ConfigurationException {
-		return getIDPPublicPath() + PVP2_ATTRIBUTEQUERY;
+	public String getIDPSSOPostService() throws ConfigurationException {
+		return getIDPPublicPath() + PVP2_IDP_POST;
 	}
-	
+
 	public String getIDPSSORedirectService() throws ConfigurationException {
-		return getIDPPublicPath() + PVP2_REDIRECT;
+		return getIDPPublicPath() + PVP2_IDP_REDIRECT;
 	}
 	
+	public String getIDPSSOSOAPService() throws ConfigurationException {
+		return getIDPPublicPath() + PVP2_IDP_SOAP;
+	}
+	
+	public String getIDPAttributeQueryService() throws ConfigurationException {
+		return getIDPPublicPath() + PVP2_IDP_ATTRIBUTEQUERY;
+	}
+		
 	public String getIDPSSOMetadataService() throws ConfigurationException {
 		return getIDPPublicPath() + PVP2_METADATA;
 	}
-- 
cgit v1.2.3


From f54870a55c9830caa2862d95e2e7f8f3cd6e0243 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Fri, 6 Jun 2014 13:49:25 +0200
Subject: final betaversion if MOA-ID-Auth Single LogOut

---
 .../moa/id/auth/MOAIDAuthConstants.java            |   4 +
 .../id/auth/servlet/IDPSingleLogOutServlet.java    | 122 +++++++
 .../moa/id/auth/servlet/LogOutServlet.java         |   2 +-
 .../moa/id/auth/servlet/RedirectServlet.java       |  22 +-
 .../moa/id/data/SLOInformationContainer.java       |  16 +-
 .../moa/id/entrypoints/DispatcherServlet.java      |   6 +-
 .../moa/id/moduls/AuthenticationManager.java       | 170 ++++++++-
 .../gv/egovernment/moa/id/moduls/SSOManager.java   |  26 ++
 .../opemsaml/MOAStringRedirectDeflateEncoder.java  |  71 ++++
 .../moa/id/protocols/pvp2x/SingleLogOutAction.java | 380 ++++++++++-----------
 .../pvp2x/builder/SingleLogOutBuilder.java         | 228 +++++++++++--
 .../id/protocols/pvp2x/messages/MOAResponse.java   |   8 +-
 .../pvp2x/utils/AssertionAttributeExtractor.java   |  12 +-
 .../pvp2x/verification/SAMLVerificationEngine.java |   3 +-
 .../resources/properties/id_messages_de.properties |   7 +-
 .../resources/templates/slo_template.html          |  57 ++++
 16 files changed, 863 insertions(+), 271 deletions(-)
 create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java
 create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java
 create mode 100644 id/server/idserverlib/src/main/resources/resources/templates/slo_template.html

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
index 6f83da367..e2c0c1f18 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
@@ -33,6 +33,10 @@ public interface MOAIDAuthConstants {
   public static final String PARAM_SSO = "SSO";
   public static final String INTERFEDERATION_IDP = "interIDP";
   
+  public static final String PARAM_SLOSTATUS = "status";	
+  public static final String SLOSTATUS_SUCCESS = "success";
+  public static final String SLOSTATUS_ERROR = "error";
+  
   /** servlet parameter &quot;sourceID&quot; */
   public static final String PARAM_SOURCEID = "sourceID";  
   /** servlet parameter &quot;BKUSelectionTemplate&quot; */
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java
new file mode 100644
index 000000000..ac4e56023
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java
@@ -0,0 +1,122 @@
+/*
+ * 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.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.VelocityContext;
+
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.moduls.AuthenticationManager;
+import at.gv.egovernment.moa.id.moduls.SSOManager;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * @author tlenz
+ *
+ */
+public class IDPSingleLogOutServlet extends AuthServlet {
+
+	private static final long serialVersionUID = -1301786072691577221L;
+		
+	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+			    throws ServletException, IOException {
+		Logger.debug("receive IDP SingleLogOut Request");
+		SSOManager ssomanager = SSOManager.getInstance();		
+		String ssoid = ssomanager.getSSOSessionID(req);
+		
+		Object tokkenObj = req.getParameter(PARAM_SLOSTATUS);
+		String tokken = null;
+		String status = null;
+		if (tokkenObj != null && tokkenObj instanceof String) {
+			tokken = (String) tokkenObj;
+			try {	
+				status = AssertionStorage.getInstance().get(tokken, String.class);
+				if (MiscUtil.isNotEmpty(status)) {
+					AssertionStorage.getInstance().remove(tokken);
+					
+				}
+				VelocityContext context = new VelocityContext();
+				if (SLOSTATUS_SUCCESS.equals(status))
+					context.put("successMsg",
+							MOAIDMessageProvider.getInstance().getMessage("slo.00", null));
+				else
+					context.put("errorMsg", 
+							MOAIDMessageProvider.getInstance().getMessage("slo.01", null));
+	                	
+					ssomanager.printSingleLogOutInfo(context, resp);
+				
+			} catch (MOAIDException e) {
+				handleErrorNoRedirect(e.getMessage(), e, req, resp);
+				
+			} catch (MOADatabaseException e) {
+				handleErrorNoRedirect(e.getMessage(), e, req, resp);
+				
+			}
+			
+		}
+
+		if (MiscUtil.isNotEmpty(status)) {
+			//print status information
+			
+			
+		} else if (MiscUtil.isNotEmpty(ssoid)) {			
+			if (ssomanager.isValidSSOSession(ssoid, null)) {
+				
+				AuthenticationManager authmanager = AuthenticationManager.getInstance();
+				String moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoid);
+
+				if (MiscUtil.isNotEmpty(moaSessionID)) {
+					AuthenticationSession authSession;
+					try {
+						authSession = AuthenticationSessionStoreage
+								.getSession(moaSessionID);
+						if(authSession != null) {
+							authmanager.performSingleLogOut(req, resp, authSession, null);
+							
+						}
+						
+					} catch (MOADatabaseException e) {
+						//TODO: insert error Handling
+						
+					} catch (MOAIDException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+				}																
+			}						
+		}
+				
+	}
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java
index 9b300578a..d7de985a4 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java
@@ -109,7 +109,7 @@ public class LogOutServlet extends AuthServlet {
 	
 			RequestStorage.removePendingRequest(AuthenticationSessionStoreage.getPendingRequestID(moasessionid));
 			
-			authmanager.logout(req, resp, moasessionid);
+			authmanager.performOnlyIDPLogOut(req, resp, moasessionid);
 			Logger.info("User with SSO Id " + ssoid + " is logged out and get redirect to "+ redirectUrl);
 		} else {
 			Logger.info("No active SSO session found. User is maybe logout already and get redirect to "+ redirectUrl);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
index 57755ca9f..6e1811c8b 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
@@ -46,6 +46,8 @@ public class RedirectServlet extends AuthServlet{
 
 	public static final String REDIRCT_PARAM_URL = "redirecturl";
 
+	private static final String DEFAULT_REDIRECTTARGET = "_parent";
+	
 	
 	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 			throws ServletException, IOException {
@@ -55,16 +57,10 @@ public class RedirectServlet extends AuthServlet{
 		String target = req.getParameter(PARAM_TARGET);
 		String artifact = req.getParameter(PARAM_SAMLARTIFACT);
 		String interIDP = req.getParameter(INTERFEDERATION_IDP);
-		
 				
-		if (MiscUtil.isEmpty(artifact) && MiscUtil.isEmpty(interIDP)) {
-			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid");
-			return;
-		}
-		
 		Logger.debug("Check URL against online-applications");
 		OnlineApplication oa = null;
-		String redirectTarget = "_parent";
+		String redirectTarget = DEFAULT_REDIRECTTARGET;
 		try {
 			oa = ConfigurationDBRead.getActiveOnlineApplication(url);			
 			if (oa == null) {		
@@ -118,10 +114,16 @@ public class RedirectServlet extends AuthServlet{
 					resp.addHeader("Location", url);
 					
 					
-				} else {
-					resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid");
-					return;
+				} else {					
+					Logger.debug("Redirect to " + url);					
+					String redirect_form = RedirectFormBuilder.buildLoginForm(url, DEFAULT_REDIRECTTARGET);
 					
+					resp.setContentType("text/html;charset=UTF-8");
+					resp.setStatus(HttpServletResponse.SC_OK);
+					PrintWriter out = new PrintWriter(resp.getOutputStream()); 
+					out.write(redirect_form);
+					out.flush();
+						
 				}
 				
 			}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
index df195c0de..d1e04e107 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
@@ -24,9 +24,12 @@ package at.gv.egovernment.moa.id.data;
 
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
 
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.NameID;
@@ -135,17 +138,12 @@ public class SLOInformationContainer implements Serializable {
 		}		
 	}
 	
-	public String getNextFrontChannelOA() {
-		Iterator<String> interator = activeFrontChannalOAs.keySet().iterator();
-		if (interator.hasNext())
-			return interator.next();
-		
-		else
-			return null;	
+	public boolean hasFrontChannelOA() {
+		return !activeFrontChannalOAs.isEmpty();
 	}
 	
-	public SLOInformationImpl getFrontChannelOASessionDescripten(String oaID) {
-		return activeFrontChannalOAs.get(oaID);
+	public Set<Entry<String, SLOInformationImpl>> getFrontChannelOASessionDescriptions() {
+		return activeFrontChannalOAs.entrySet();
 	}
 	
 	public void removeFrontChannelOA(String oaID) {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
index a3827ab73..0cbe749e0 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
@@ -143,7 +143,7 @@ public class DispatcherServlet extends AuthServlet{
 										
 										//remove MOASession
 										AuthenticationSession moaSession = AuthenticationSessionStoreage.getSessionWithPendingRequestID(pendingRequestID);
-										AuthenticationManager.getInstance().logout(req, resp, moaSession.getSessionID());
+										AuthenticationManager.getInstance().performOnlyIDPLogOut(req, resp, moaSession.getSessionID());
 										
 										return;
 									}
@@ -468,12 +468,12 @@ public class DispatcherServlet extends AuthServlet{
 						} catch (AuthenticationException e) {
 							Logger.warn("SSO Session information can not be stored  -> SSO is not enabled!");
 							
-							authmanager.logout(req, resp, moasessionID);
+							authmanager.performOnlyIDPLogOut(req, resp, moasessionID);
 							isSSOSession = false;
 						}
 					
 					} else {
-						authmanager.logout(req, resp, moasessionID);
+						authmanager.performOnlyIDPLogOut(req, resp, moasessionID);
 					}
 				
 					//Advanced statistic logging
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
index 5a06b3ecd..ee26d9223 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
@@ -24,13 +24,21 @@ package at.gv.egovernment.moa.id.moduls;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
 import org.joda.time.DateTime;
 import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
 import org.opensaml.common.xml.SAMLConstants;
@@ -38,6 +46,8 @@ import org.opensaml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
 import org.opensaml.saml2.core.AuthnRequest;
 import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.LogoutResponse;
 import org.opensaml.saml2.core.NameID;
 import org.opensaml.saml2.core.NameIDPolicy;
 import org.opensaml.saml2.core.NameIDType;
@@ -45,12 +55,15 @@ import org.opensaml.saml2.core.RequestedAuthnContext;
 import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.SingleLogoutService;
 import org.opensaml.saml2.metadata.SingleSignOnService;
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.security.MetadataCredentialResolver;
 import org.opensaml.security.MetadataCredentialResolverFactory;
 import org.opensaml.security.MetadataCriteria;
 import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.ws.soap.common.SOAPException;
+import org.opensaml.xml.XMLObject;
 import org.opensaml.xml.security.CriteriaSet;
 import org.opensaml.xml.security.SecurityException;
 import org.opensaml.xml.security.criteria.EntityIDCriteria;
@@ -64,19 +77,32 @@ import at.gv.egovernment.moa.id.auth.exception.BuildException;
 import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;
 import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
+import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
+import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
 import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
 import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.SLOInformationContainer;
+import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.ArtifactBinding;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
 import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;
 import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
 import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
 import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MessageProvider;
 import at.gv.egovernment.moa.util.MiscUtil;
 import at.gv.egovernment.moa.util.StringUtils;
 
@@ -138,7 +164,149 @@ public class AuthenticationManager extends AuthServlet {
 		return false;
 	}
 	
-	public void logout(HttpServletRequest request,
+	public void performSingleLogOut(HttpServletRequest httpReq,
+	HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException {		
+		String pvpSLOIssuer = null;
+		String inboundRelayState = null;
+		
+		if (pvpReq != null) {
+			MOARequest samlReq = (MOARequest) pvpReq.getRequest();
+			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
+			pvpSLOIssuer = logOutReq.getIssuer().getValue();
+			inboundRelayState = samlReq.getRelayState();
+		}
+		
+		SSOManager ssomanager = SSOManager.getInstance();
+		
+		//store active OAs to SLOContaine
+		List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);
+		List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session);
+		SLOInformationContainer sloContainer = new SLOInformationContainer();
+		sloContainer.setSloRequest(pvpReq);
+		sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer);
+		sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer);
+						
+		//terminate MOASession
+		try {
+			AuthenticationSessionStoreage.destroySession(session.getSessionID());
+			ssomanager.deleteSSOSessionID(httpReq, httpResp);
+			
+		} catch (MOADatabaseException e) {
+			Logger.warn("Delete MOASession FAILED.");
+			sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix());
+			
+		}
+		
+		//start service provider back channel logout process
+		Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();	
+		while (nextOAInterator.hasNext()) {
+			SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next());
+			LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
+
+			try {
+				List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq);
+				
+				LogoutResponse sloResp = null;						
+				for (XMLObject el : soapResp) {
+					if (el instanceof LogoutResponse)
+						sloResp = (LogoutResponse) el;							
+				}
+				
+				if (sloResp == null) {
+					Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
+							+ " FAILED. NO LogOut response received.");
+					sloContainer.putFailedOA(sloReq.getIssuer().getValue());
+					
+				}
+				
+				SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp);
+										
+			} catch (SOAPException e) {
+				Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
+						+ " FAILED.", e);
+				sloContainer.putFailedOA(sloReq.getIssuer().getValue());
+				
+			} catch (SecurityException e) {
+				Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
+						+ " FAILED.", e);
+				sloContainer.putFailedOA(sloReq.getIssuer().getValue());
+				
+			}					
+		}
+						
+		//start service provider front channel logout process
+		try {
+			if (sloContainer.hasFrontChannelOA()) {
+				String relayState = Random.nextRandom();
+				
+				Collection<Entry<String, SLOInformationImpl>> sloDescr = sloContainer.getFrontChannelOASessionDescriptions();
+				List<String> sloReqList = new ArrayList<String>();
+				for (Entry<String, SLOInformationImpl> el : sloDescr) {
+					LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue());
+					try {
+						sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), 
+								sloReq, httpReq, httpResp, relayState));
+						
+					} catch (Exception e) {
+						Logger.warn("Failed to build SLO request for OA:" + el.getKey());
+						sloContainer.putFailedOA(el.getKey());
+						
+					}														
+				}
+				
+				AssertionStorage.getInstance().put(relayState, sloContainer);
+				
+		        VelocityContext context = new VelocityContext();
+		        context.put("redirectURLs", sloReqList);
+		        ssomanager.printSingleLogOutInfo(context, httpResp);
+				
+								
+			} else {
+				if (pvpReq != null) {
+					//send SLO response to SLO request issuer
+					SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
+					LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs());
+					SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState);
+					
+				} else {
+					//print SLO information directly
+			        VelocityContext context = new VelocityContext();
+			        if (sloContainer.getSloFailedOAs() == null || 
+			        		sloContainer.getSloFailedOAs().size() == 0)
+			        	context.put("successMsg", 
+			        			MessageProvider.getInstance().getMessage("slo.00", null));
+			        else
+			        	context.put("errorMsg", 
+			        			MessageProvider.getInstance().getMessage("slo.01", null));
+			        ssomanager.printSingleLogOutInfo(context, httpResp);
+										
+				}
+									
+			}	
+								
+		} catch (MOADatabaseException e) {
+			Logger.error("MOA AssertionDatabase ERROR", e);
+			if (pvpReq != null) {
+				SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
+				LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
+				SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState);
+				
+			}else {
+				//print SLO information directly
+		        VelocityContext context = new VelocityContext();
+	        	context.put("errorMsg", 
+	        			MessageProvider.getInstance().getMessage("slo.01", null));
+		        ssomanager.printSingleLogOutInfo(context, httpResp);
+									
+			}
+			
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}				
+	}
+		
+	public void performOnlyIDPLogOut(HttpServletRequest request,
 			HttpServletResponse response, String moaSessionID) {
 		Logger.info("Logout");
 
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
index f4f89a4ba..02e252412 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
@@ -22,17 +22,22 @@
  *******************************************************************************/
 package at.gv.egovernment.moa.id.moduls;
 
+import java.io.StringWriter;
 import java.util.List;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
 import org.hibernate.Query;
 import org.hibernate.Session;
 
 import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
 import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
 import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore;
 import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
@@ -42,6 +47,7 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
 import at.gv.egovernment.moa.logging.Logger;
 import at.gv.egovernment.moa.util.MiscUtil;
 
@@ -267,6 +273,26 @@ public class SSOManager {
 		
 	}
 	
+	public void printSingleLogOutInfo(VelocityContext context, HttpServletResponse httpResp) throws MOAIDException {		
+		try {		
+			Logger.trace("Initialize VelocityEngine...");
+			VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+			Template template = velocityEngine.getTemplate("/resources/templates/slo_template.html");
+
+			StringWriter writer = new StringWriter();
+			template.merge(context, writer);
+        
+			httpResp.setContentType("text/html;charset=UTF-8");            
+			httpResp.getOutputStream().write(writer.toString().getBytes());
+			
+		} catch (Exception e) {
+			Logger.error("Single LogOut from can not created.", e);
+			throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
+		}
+			
+	}
+	
+	
 	private String getValueFromCookie(HttpServletRequest httpReq, String cookieName) {
 		Cookie[] cookies = httpReq.getCookies();
 		
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java
new file mode 100644
index 000000000..ece1a805d
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.opemsaml;
+
+import org.opensaml.common.binding.SAMLMessageContext;
+import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
+import org.opensaml.ws.message.MessageContext;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAStringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {
+
+	private String redirectURL = null;
+	
+	public void encode(MessageContext messageContext)
+			throws MessageEncodingException {
+		if (!(messageContext instanceof SAMLMessageContext)) {
+			Logger.error("Invalid message context type, this encoder only support SAMLMessageContext");
+			throw new MessageEncodingException(
+					"Invalid message context type, this encoder only support SAMLMessageContext");
+		}
+
+		SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
+
+		String endpointURL = getEndpointURL(samlMsgCtx).buildURL();
+
+		setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL);
+
+		removeSignature(samlMsgCtx);
+
+		String encodedMessage = deflateAndBase64Encode(samlMsgCtx
+				.getOutboundSAMLMessage());
+
+		redirectURL = buildRedirectURL(samlMsgCtx, endpointURL,
+				encodedMessage);
+	}
+
+	/**
+	 * @return the redirectURL
+	 */
+	public String getRedirectURL() {
+		return redirectURL;
+	}
+	
+	
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
index 92441e663..46e02d048 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
@@ -22,26 +22,50 @@
  */
 package at.gv.egovernment.moa.id.protocols.pvp2x;
 
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.lang.SerializationUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.LogoutRequest;
 import org.opensaml.saml2.core.LogoutResponse;
 import org.opensaml.saml2.core.RequestAbstractType;
 import org.opensaml.saml2.core.Status;
 import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;
 import org.opensaml.ws.message.encoder.MessageEncodingException;
 import org.opensaml.ws.soap.common.SOAPException;
 import org.opensaml.xml.XMLObject;
 import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.X509Credential;
 
 import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet;
+import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
+import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore;
 import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
 import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
 import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
@@ -50,9 +74,11 @@ import at.gv.egovernment.moa.id.data.IAuthData;
 import at.gv.egovernment.moa.id.data.SLOInformationContainer;
 import at.gv.egovernment.moa.id.data.SLOInformationImpl;
 import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.AuthenticationManager;
 import at.gv.egovernment.moa.id.moduls.IAction;
 import at.gv.egovernment.moa.id.moduls.IRequest;
 import at.gv.egovernment.moa.id.moduls.SSOManager;
+import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
 import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
@@ -60,12 +86,17 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;
 import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;
 import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
+import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;
 import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;
 import at.gv.egovernment.moa.id.storage.AssertionStorage;
 import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
 import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MessageProvider;
 import at.gv.egovernment.moa.util.MiscUtil;
+import at.gv.egovernment.moa.util.URLEncoder;
 
 /**
  * @author tlenz
@@ -83,16 +114,16 @@ public class SingleLogOutAction implements IAction {
 
 		PVPTargetConfiguration pvpReq = (PVPTargetConfiguration) req;  
 				
-		if (pvpReq.getRequest() instanceof MOARequest) {
+		if (pvpReq.getRequest() instanceof MOARequest &&
+				((MOARequest)pvpReq.getRequest()).getSamlRequest() instanceof LogoutRequest) {
+			Logger.debug("Process Single LogOut request");
 			MOARequest samlReq = (MOARequest) pvpReq.getRequest();
-			if (samlReq.getSamlRequest() instanceof LogoutRequest) {
-				Logger.debug("Process Single LogOut request");
-				LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
+			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
 				
-				AuthenticationSession session = 
-						AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID(
-								logOutReq.getIssuer().getValue(), 
-								logOutReq.getNameID().getValue());
+			AuthenticationSession session = 
+					AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID(
+							logOutReq.getIssuer().getValue(), 
+							logOutReq.getNameID().getValue());
 				
 				if (session == null) {
 					Logger.warn("Can not find active SSO session with nameID " 
@@ -105,7 +136,7 @@ public class SingleLogOutAction implements IAction {
 						Logger.warn("Can not find active Session. Single LogOut not possible!");
 						SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
 						LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
-						sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
+						SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
 						return null;
 						
 					} else {
@@ -117,103 +148,150 @@ public class SingleLogOutAction implements IAction {
 							Logger.warn("Can not find active Session. Single LogOut not possible!");
 							SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
 							LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
-							sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
+							SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
 							return null;
 							
 						}						
 					}					
 				}
 
-				//store active OAs to SLOContaine
-				List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);
-				List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session);
-				SLOInformationContainer sloContainer = new SLOInformationContainer();
-				sloContainer.setSloRequest(pvpReq);
-				sloContainer.parseActiveIDPs(dbIDPs, logOutReq.getIssuer().getValue());
-				sloContainer.parseActiveOAs(dbOAs, logOutReq.getIssuer().getValue());
-								
-				//terminate MOASession
-				try {
-					AuthenticationSessionStoreage.destroySession(session.getSessionID());
-					
-				} catch (MOADatabaseException e) {
-					Logger.warn("Delete MOASession FAILED.");
-					sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix());
-					
-				}
-				
-				//start service provider back channel logout process
-				Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();	
-				while (nextOAInterator.hasNext()) {
-					SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next());
-					LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
-
-					try {
-						List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq);
-						
-						LogoutResponse sloResp = null;						
-						for (XMLObject el : soapResp) {
-							if (el instanceof LogoutResponse)
-								sloResp = (LogoutResponse) el;							
-						}
-						
-						if (sloResp == null) {
-							Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
-									+ " FAILED. NO LogOut response received.");
-							sloContainer.putFailedOA(sloReq.getIssuer().getValue());
+				AuthenticationManager authManager = AuthenticationManager.getInstance();
+				authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq);
 							
-						}
-						
-						checkStatusCode(sloContainer, sloResp);
-												
-					} catch (SOAPException e) {
-						Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
-								+ " FAILED.", e);
-						sloContainer.putFailedOA(sloReq.getIssuer().getValue());
-						
-					} catch (SecurityException e) {
-						Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
-								+ " FAILED.", e);
-						sloContainer.putFailedOA(sloReq.getIssuer().getValue());
-						
-					}					
-				}
-								
-				//start service provider front channel logout process
-				try {
-					doFrontChannelLogOut(sloContainer, httpReq, httpResp);
-					
-				} catch (MOADatabaseException e) {
-					Logger.error("MOA AssertionDatabase ERROR", e);
-					SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
-					LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
-					sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
-					return null;
-					
-				}
-				
-			} else if (samlReq.getSamlRequest() instanceof LogoutResponse) {
+			} else if (pvpReq.getRequest() instanceof MOAResponse &&
+					((MOAResponse)pvpReq.getRequest()).getResponse() instanceof LogoutResponse) {
 				Logger.debug("Process Single LogOut response");
-				LogoutResponse logOutResp = (LogoutResponse) samlReq.getSamlRequest();
+				LogoutResponse logOutResp = (LogoutResponse) ((MOAResponse)pvpReq.getRequest()).getResponse();
 														
-				try {
-					if (MiscUtil.isEmpty(samlReq.getRelayState())) {
+				try {					
+					String relayState = pvpReq.getRequest().getRelayState();
+					if (MiscUtil.isEmpty(relayState)) {
 						Logger.warn("SLO Response from " + logOutResp.getIssuer().getValue() 
 								+ " has no SAML2 RelayState.");					
 						throw new SLOException("pvp2.19", null);
 						
 					}
 					
-					SLOInformationContainer sloContainer = 
-							AssertionStorage.getInstance().get(samlReq.getRelayState(), SLOInformationContainer.class);					
-					checkStatusCode(sloContainer, logOutResp);
-					sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue());
-					doFrontChannelLogOut(sloContainer, httpReq, httpResp);
+					Session session = MOASessionDBUtils.getCurrentSession();					
+					boolean storageSuccess = false;
+					int counter = 0;
+					
+					//TODO: add counter to prevent deadlock
+					
+					while (!storageSuccess) {
+						Transaction tx = session.beginTransaction();
+						
+						List result;
+						Query query = session.getNamedQuery("getAssertionWithArtifact");
+						query.setParameter("artifact", relayState);
+						result = query.list();					  
+						Logger.trace("Found entries: " + result.size());
+						  
+						//Assertion requires an unique artifact
+						if (result.size() != 1) {
+							Logger.trace("No entries found.");
+						   	throw new MOADatabaseException("No sessioninformation found with this ID");
+						}
+						  
+						AssertionStore element = (AssertionStore) result.get(0);					
+						Object data = SerializationUtils.deserialize(element.getAssertion());
+						
+						if (data instanceof SLOInformationContainer) {
+							SLOInformationContainer sloContainer = (SLOInformationContainer) data;
+							
+							//check status
+							SingleLogOutBuilder.checkStatusCode(sloContainer, logOutResp);
+														
+							if (sloContainer.hasFrontChannelOA()) {							
+								try {
+									//some response are open
+									byte[] serializedSLOContainer = SerializationUtils.serialize((Serializable) sloContainer);
+									element.setAssertion(serializedSLOContainer);
+									element.setType(sloContainer.getClass().getName());
+							
+									session.saveOrUpdate(element);							
+									tx.commit();
+									
+									//sloContainer could be stored to database
+									storageSuccess = true;
+									
+								} catch(HibernateException e) {
+									tx.rollback();
+
+									counter++;									
+									Logger.debug("SLOContainter could not stored to database. Wait some time and restart storage process ... ");
+									java.util.Random rand = new java.util.Random();
+									
+									try {
+										Thread.sleep(rand.nextInt(20)*10);
+										
+									} catch (InterruptedException e1) {
+										Logger.warn("Thread could not stopped. ReStart storage process immediately", e1);
+									}																	
+								}
+								
+							} else {
+								//last response received.
+								try {
+									session.delete(element);
+									tx.commit();
+
+								} catch(HibernateException e) {
+									tx.rollback();								
+									Logger.error("SLOContainter could not deleted from database. ");
+									
+								}
+									
+								storageSuccess = true;
+								String redirectURL = null;
+								if (sloContainer.getSloRequest() != null) {
+									//send SLO response to SLO request issuer
+									SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(sloContainer.getSloRequest());
+									LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs());
+									redirectURL = SingleLogOutBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState());
+																	
+								} else {
+									//print SLO information directly
+									redirectURL = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/idpSingleLogout";
+									
+									String artifact = Random.nextRandom();
+									
+							        String statusCode = null;
+									if (sloContainer.getSloFailedOAs() == null || 
+							        		sloContainer.getSloFailedOAs().size() == 0)							       							   							        	
+							        	statusCode  = SLOSTATUS_SUCCESS;
+							        else
+							        	statusCode  = SLOSTATUS_ERROR;
+
+									AssertionStorage.getInstance().put(artifact, statusCode);
+							        redirectURL = addURLParameter(redirectURL, PARAM_SLOSTATUS, artifact);
+							        
+								}								
+								//redirect to Redirect Servlet
+								String url = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/RedirectServlet";
+								url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8"));
+								url = httpResp.encodeRedirectURL(url);
+							
+								httpResp.setContentType("text/html");
+								httpResp.setStatus(302);
+								httpResp.addHeader("Location", url);
+		
+							}
+						} else {
+							Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + relayState);
+							throw new MOADatabaseException("Sessioninformation Cast-Exception");
+						
+						}						
+					}
 					
 				} catch (MOADatabaseException e) {
 					Logger.error("MOA AssertionDatabase ERROR", e);
 					throw new SLOException("pvp2.19", null);
 					
+				} catch (UnsupportedEncodingException e) {
+					Logger.error("Finale SLO redirct not possible.", e);
+					throw new AuthenticationException("pvp2.13", new Object[]{});
+
 				}
 							
 			} else {
@@ -221,13 +299,7 @@ public class SingleLogOutAction implements IAction {
 				throw new MOAIDException("pvp2.13", null);
 				
 			}
-			
-		} else {
-			Logger.error("Process SingleLogOutAction but request is NOT of type MOARequest.");
-			throw new MOAIDException("pvp2.13", null);
-			
-		}
-				
+							
 		return null;		
 	}
 
@@ -248,120 +320,12 @@ public class SingleLogOutAction implements IAction {
 		return PVP2XProtocol.SINGLELOGOUT;
 	}
 	
-	private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) {
-		Status status = logOutResp.getStatus();				
-		if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
-			String message = " Message: ";
-			if (status.getStatusMessage() != null) 
-				message += status.getStatusMessage().getMessage();
-			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue()
-					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue()
-					+ message + ")");
-			sloContainer.putFailedOA(logOutResp.getIssuer().getValue());
-			
-		} else
-			Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS");
-		
+	protected static String addURLParameter(String url, String paramname,
+			String paramvalue) {
+		String param = paramname + "=" + paramvalue;
+		if (url.indexOf("?") < 0)
+			return url + "?" + param;
+		else
+			return url + "&" + param;
 	}
-	
-	private void doFrontChannelLogOut(SLOInformationContainer sloContainer,
-			HttpServletRequest httpReq, HttpServletResponse httpResp 
-			) throws MOAIDException, MOADatabaseException {
-		String nextOA = sloContainer.getNextFrontChannelOA();
-		if (MiscUtil.isNotEmpty(nextOA)) {					
-			SLOInformationImpl sloDescr = sloContainer.getFrontChannelOASessionDescripten(nextOA);
-			LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
-			String relayState = Random.nextRandom();
-			
-			AssertionStorage.getInstance().put(relayState, sloContainer);
-			
-			sendFrontChannelSLOMessage(sloDescr.getServiceURL(), sloDescr.getBinding(), 
-					sloReq, httpReq, httpResp, relayState);
-			
-		} else {
-			//send SLO response to SLO request issuer
-			PVPTargetConfiguration pvpReq = sloContainer.getSloRequest();
-			MOARequest samlReq = (MOARequest) pvpReq.getRequest();
-			SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
-			LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs());
-			sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
-								
-		}		
-	}
-	
-	/**
-	 * @param serviceURL
-	 * @param binding
-	 * @param sloReq
-	 * @param httpReq
-	 * @param httpResp
-	 * @param relayState
-	 */
-	private void sendFrontChannelSLOMessage(String serviceURL, String bindingType,
-			RequestAbstractType sloReq, HttpServletRequest httpReq,
-			HttpServletResponse httpResp, String relayState) throws MOAIDException {
-		IEncoder binding = null;
-		if (bindingType.equals(
-				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
-			binding = new RedirectBinding();
-						
-		} else if (bindingType.equals(
-				SAMLConstants.SAML2_POST_BINDING_URI)) {
-			binding = new PostBinding();
-			
-		}
-
-		if (binding == null) {
-			throw new BindingNotSupportedException(bindingType);
-		}
-		
-		try {
-			binding.encodeRequest(httpReq, httpResp, sloReq, 
-					serviceURL, relayState);
-			
-		} catch (MessageEncodingException e) {
-			Logger.error("Message Encoding exception", e);
-			throw new MOAIDException("pvp2.01", null, e);
-			
-		} catch (SecurityException e) {
-			Logger.error("Security exception", e);
-			throw new MOAIDException("pvp2.01", null, e);
-
-		}
-		
-	}
-
-	private void sendFrontChannelSLOMessage(SingleLogoutService consumerService, 
-			LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp, 
-			String relayState) throws MOAIDException {
-		IEncoder binding = null;
-		if (consumerService.getBinding().equals(
-				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
-			binding = new RedirectBinding();
-						
-		} else if (consumerService.getBinding().equals(
-				SAMLConstants.SAML2_POST_BINDING_URI)) {
-			binding = new PostBinding();
-			
-		}
-
-		if (binding == null) {
-			throw new BindingNotSupportedException(consumerService.getBinding());
-		}
-		
-		try {
-			binding.encodeRespone(req, resp, sloResp, 
-					consumerService.getLocation(), relayState);
-			
-		} catch (MessageEncodingException e) {
-			Logger.error("Message Encoding exception", e);
-			throw new MOAIDException("pvp2.01", null, e);
-			
-		} catch (SecurityException e) {
-			Logger.error("Security exception", e);
-			throw new MOAIDException("pvp2.01", null, e);
-
-		}
-		
-	}	
 }
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
index 7aa860c5c..eeb1dd104 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java
@@ -22,31 +22,53 @@
  */
 package at.gv.egovernment.moa.id.protocols.pvp2x.builder;
 
+import java.security.NoSuchAlgorithmException;
 import java.util.List;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.joda.time.DateTime;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.Issuer;
 import org.opensaml.saml2.core.LogoutRequest;
 import org.opensaml.saml2.core.LogoutResponse;
 import org.opensaml.saml2.core.NameID;
+import org.opensaml.saml2.core.RequestAbstractType;
 import org.opensaml.saml2.core.Status;
 import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.saml2.core.StatusMessage;
+import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml2.metadata.SPSSODescriptor;
 import org.opensaml.saml2.metadata.SSODescriptor;
 import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.X509Credential;
 
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.data.SLOInformationContainer;
 import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;
 import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
 import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;
 import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException;
 import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;
 import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
 import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;
 import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
 import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
 import at.gv.egovernment.moa.logging.Logger;
@@ -57,9 +79,141 @@ import at.gv.egovernment.moa.logging.Logger;
  */
 public class SingleLogOutBuilder {
 
-	public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException {
+	public static void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) {
+		Status status = logOutResp.getStatus();				
+		if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
+			String message = " Message: ";
+			if (status.getStatusMessage() != null) 
+				message += status.getStatusMessage().getMessage();
+			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue()
+					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue()
+					+ message + ")");
+			sloContainer.putFailedOA(logOutResp.getIssuer().getValue());
+			
+		} else
+			sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue());
+			Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS");
+		
+	}
+		
+	/**
+	 * @param serviceURL
+	 * @param binding
+	 * @param sloReq
+	 * @param httpReq
+	 * @param httpResp
+	 * @param relayState
+	 * @return 
+	 */
+	public static String getFrontChannelSLOMessageURL(String serviceURL, String bindingType,
+			RequestAbstractType sloReq, HttpServletRequest httpReq,
+			HttpServletResponse httpResp, String relayState) throws MOAIDException {
+		
+		try {
+			X509Credential credentials = CredentialProvider
+					.getIDPAssertionSigningCredential();
+
+			Logger.debug("create SAML RedirectBinding response");
+			
+			MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();			
+			BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+			SingleLogoutService service = new SingleLogoutServiceBuilder()
+					.buildObject();
+			service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+			service.setLocation(serviceURL);
+			context.setOutboundSAMLMessageSigningCredential(credentials);
+			context.setPeerEntityEndpoint(service);
+			context.setOutboundSAMLMessage(sloReq);
+			context.setRelayState(relayState);
+
+			encoder.encode(context);
+			
+			return encoder.getRedirectURL();
+			
+		} catch (MessageEncodingException e) {
+			Logger.error("Message Encoding exception", e);
+			throw new MOAIDException("pvp2.01", null, e);
+			
+		}		
+	}
+
+	public static String getFrontChannelSLOMessageURL(SingleLogoutService service,
+			StatusResponseType sloResp, HttpServletRequest httpReq,
+			HttpServletResponse httpResp, String relayState) throws MOAIDException {
+		
+		try {
+			X509Credential credentials = CredentialProvider
+					.getIDPAssertionSigningCredential();
+
+			Logger.debug("create SAML RedirectBinding response");
+			
+			MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();			
+			BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+			context.setOutboundSAMLMessageSigningCredential(credentials);
+			context.setPeerEntityEndpoint(service);
+			context.setOutboundSAMLMessage(sloResp);
+			context.setRelayState(relayState);
+
+			encoder.encode(context);
+			
+			return encoder.getRedirectURL();
+			
+		} catch (MessageEncodingException e) {
+			Logger.error("Message Encoding exception", e);
+			throw new MOAIDException("pvp2.01", null, e);
+			
+		}		
+	}
+	
+	public static void sendFrontChannelSLOMessage(SingleLogoutService consumerService, 
+			LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp, 
+			String relayState) throws MOAIDException {
+		IEncoder binding = null;
+		if (consumerService.getBinding().equals(
+				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+			binding = new RedirectBinding();
+						
+		} else if (consumerService.getBinding().equals(
+				SAMLConstants.SAML2_POST_BINDING_URI)) {
+			binding = new PostBinding();
+			
+		}
+
+		if (binding == null) {
+			throw new BindingNotSupportedException(consumerService.getBinding());
+		}
+		
+		try {
+			binding.encodeRespone(req, resp, sloResp, 
+					consumerService.getLocation(), relayState);
+			
+		} catch (MessageEncodingException e) {
+			Logger.error("Message Encoding exception", e);
+			throw new MOAIDException("pvp2.01", null, e);
+			
+		} catch (SecurityException e) {
+			Logger.error("Security exception", e);
+			throw new MOAIDException("pvp2.01", null, e);
+
+		}		
+	}
+	
+	
+	public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException, MOAIDException {
 		LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class);
 		
+		SecureRandomIdentifierGenerator gen;
+		try {
+			gen = new SecureRandomIdentifierGenerator();
+			sloReq.setID(gen.generateIdentifier());
+			
+		} catch (NoSuchAlgorithmException e) {
+			Logger.error("Internal server error", e);
+			throw new AuthenticationException("pvp2.13", new Object[]{});
+			
+		}			
+
+		
 		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		
 		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
 		issuer.setFormat(NameID.ENTITY);
@@ -76,14 +230,9 @@ public class SingleLogOutBuilder {
 		return sloReq;		
 	}
 	
-	public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException {
-		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		
-		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		
-		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
-		issuer.setFormat(NameID.ENTITY);
-		sloResp.setIssuer(issuer);		
-		sloResp.setIssueInstant(new DateTime());		
-		sloResp.setDestination(sloService.getLocation());		
+	public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException {
+		LogoutResponse sloResp = buildBasicResponse(sloService, spRequest);
+		
 		Status status = SAML2Utils.createSAMLObject(Status.class);
 		StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
 		StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);
@@ -95,14 +244,8 @@ public class SingleLogOutBuilder {
 		return sloResp;
 	}
 	
-	public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws ConfigurationException {		
-		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		
-		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		
-		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
-		issuer.setFormat(NameID.ENTITY);
-		sloResp.setIssuer(issuer);		
-		sloResp.setIssueInstant(new DateTime());		
-		sloResp.setDestination(sloService.getLocation());
+	public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws MOAIDException {		
+		LogoutResponse sloResp = buildBasicResponse(sloService, spRequest);
 		
 		Status status;
 		if (failedOAs == null || failedOAs.size() == 0) {
@@ -123,6 +266,37 @@ public class SingleLogOutBuilder {
 		
 	}
 	
+	private static LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException {
+		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		
+		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		
+		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
+		issuer.setFormat(NameID.ENTITY);
+		sloResp.setIssuer(issuer);		
+		sloResp.setIssueInstant(new DateTime());		
+		sloResp.setDestination(sloService.getLocation());
+		
+		SecureRandomIdentifierGenerator gen;
+		try {
+			gen = new SecureRandomIdentifierGenerator();
+			sloResp.setID(gen.generateIdentifier());
+			
+		} catch (NoSuchAlgorithmException e) {
+			Logger.error("Internal server error", e);
+			throw new AuthenticationException("pvp2.13", new Object[]{});
+			
+		}			
+
+		if (spRequest.getRequest() instanceof MOARequest &&
+				((MOARequest)spRequest.getRequest()).getSamlRequest() instanceof LogoutRequest) {
+			LogoutRequest sloReq =  (LogoutRequest) ((MOARequest)spRequest.getRequest()).getSamlRequest();
+			sloResp.setInResponseTo(sloReq.getID());
+			
+		}
+		
+		return sloResp;
+		
+	}
+	
 	public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException {
 		try {
 			EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID);
@@ -140,19 +314,19 @@ public class SingleLogOutBuilder {
 							)
 					sloService = el;
 
-				else  if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)
-						&& (
-								(sloService != null 
-									&& !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)
-									&& !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) 
-								|| sloService == null)
-						)
-					sloService = el;				
+//				else  if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)
+//						&& (
+//								(sloService != null 
+//									&& !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)
+//									&& !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) 
+//								|| sloService == null)
+//						)
+//					sloService = el;				
 			}
 
 			if (sloService == null) {
-				Logger.error("Found no SLO ServiceDescriptor in Metadata");				
-				throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null);
+				Logger.error("Found no valid SLO ServiceDescriptor in Metadata");				
+				throw new NOSLOServiceDescriptorException("NO valid SLO ServiceDescriptor", null);
 				
 			}			
 			return sloService;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
index 870273cf3..f2512b122 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
@@ -23,7 +23,7 @@
 package at.gv.egovernment.moa.id.protocols.pvp2x.messages;
 
 import org.opensaml.Configuration;
-import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.xml.io.Unmarshaller;
 import org.opensaml.xml.io.UnmarshallerFactory;
 import org.opensaml.xml.io.UnmarshallingException;
@@ -35,16 +35,16 @@ public class MOAResponse extends InboundMessage {
 		
 	private static final long serialVersionUID = -1133012928130138501L;
 
-	public MOAResponse(Response response) {
+	public MOAResponse(StatusResponseType response) {
 		setSAMLMessage(response.getDOM());
 	}
 
-	public Response getResponse() {		
+	public StatusResponseType getResponse() {		
 		UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
 		Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
 		
 		try {
-			return (Response) unmashaller.unmarshall(getInboundMessage());
+			return (StatusResponseType) unmashaller.unmarshall(getInboundMessage());
 			
 		} catch (UnmarshallingException e) {
 			Logger.warn("AuthnResponse Unmarshaller error", e);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
index 61b481447..ee0088576 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
@@ -28,6 +28,7 @@ import org.opensaml.saml2.core.Assertion;
 import org.opensaml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml2.core.AuthnStatement;
 import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.core.Subject;
 
 import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;
@@ -38,15 +39,16 @@ public class AssertionAttributeExtractor {
 	
 	private Assertion assertion = null;
 	
-	public AssertionAttributeExtractor(Response samlResponse) throws AssertionAttributeExtractorExeption {
-		if (samlResponse != null) {
-			if (samlResponse.getAssertions().size() == 0) 
+	public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption {
+		if (samlResponse != null && samlResponse instanceof Response) {
+			List<Assertion> assertions = ((Response) samlResponse).getAssertions();			
+			if (assertions.size() == 0) 
 				throw new AssertionAttributeExtractorExeption("Assertion");
 				
-			else if (samlResponse.getAssertions().size() > 1)
+			else if (assertions.size() > 1)
 				Logger.warn("Found more then ONE PVP2.1 assertions. Only the First is used.");
 			
-			assertion = samlResponse.getAssertions().get(0);			
+			assertion = assertions.get(0);			
 					
 		} else 
 			throw new AssertionAttributeExtractorExeption();		
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
index 6388042d9..3be5df917 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
@@ -32,6 +32,7 @@ import org.opensaml.saml2.core.EncryptedAssertion;
 import org.opensaml.saml2.core.RequestAbstractType;
 import org.opensaml.saml2.core.Response;
 import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.encryption.Decrypter;
 import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
 import org.opensaml.saml2.metadata.IDPSSODescriptor;
@@ -76,7 +77,7 @@ public class SAMLVerificationEngine {
 	}
 	
 	
-	public void verifyResponse(Response samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
+	public void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
 		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
 		try {
 		    profileValidator.validate(samlObj.getSignature());
diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
index c8cca157d..9aab22ef5 100644
--- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
+++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
@@ -243,9 +243,9 @@ pvp2.16=Fehler beim verschl\u00FCsseln der PVP2 Assertion
 pvp2.17=Der QAA Level {0} entspricht nicht dem angeforderten QAA Level {1}
 pvp2.18=Es konnten nicht alle Single Sign-On Sessions beendet werden.
 pvp2.19=Der Single LogOut Vorgang musste wegen eines unkorregierbaren Fehler abgebrochen werden. 
-pvp2.20=Für die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
+pvp2.20=F\u00FCr die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
 pvp2.21=Die Signature des Requests konnte nicht g\u00FCltig validiert werden.  
-pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler={0}).
+pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler\={0}).
 
 oauth20.01=Fehlerhafte redirect url
 oauth20.02=Fehlender Parameter "{0}"
@@ -256,3 +256,6 @@ oauth20.06=Die angegebene OA kann nicht verwendet werden
 oauth20.07=Angeforderter grant_type ist nicht erlaubt
 oauth20.08=Nicht berechtigt f\u00FCr Token-Request
 oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{0}"
+
+slo.00=Sie konnten erfolgreich von allen Online-Applikation abgemeldet werden.
+slo.01=Sie konnten NICHT erfolgreich von allen Online-Applikationen abgemeldet werden\!<BR>Bitte schlie\u00DFen Sie aus sicherheitsgr\u00FCnden Ihren Browser.
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
new file mode 100644
index 000000000..16c9e87eb
--- /dev/null
+++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
@@ -0,0 +1,57 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+
+<body>
+	<noscript>
+		<p>
+			<strong>Note:</strong> Since your browser does not support
+			JavaScript, you must press the Continue button once to proceed.
+		</p>
+	</noscript>
+
+	<h1>MOA-ID Single LogOut Information</h1>
+
+	<style type="text/css">
+
+	#alert {
+		margin: 100px 250px;
+		font-family: Verdana, Arial, Helvetica, sans-serif;
+		font-size: 14px;
+		font-weight: normal;
+		color: red;
+	}
+	
+	#reqFrame {
+		display: none;
+		
+	}
+
+</style>
+
+	#if($errorMsg)
+	<div class="alert">
+		<p>$errorMsg</p> 
+	</div>	
+	#end
+
+	#if($successMsg)
+	<div>
+		<p>$successMsg</p> 
+	</div>	
+	#end
+
+	#if($redirectURLs)
+		<div>
+			<p>
+				Sie werden von allen Online-Applikationen abgemeldet. <br>
+				Dieser Vorgang kann einige Zeit in Anspruch nehmen.
+			</p>
+		</div>
+	#end
+
+	#foreach( $el in $redirectURLs )
+		<iframe src=$el class="reqFrame"></iframe>
+	#end
+
+
+</body>
+</html>
\ No newline at end of file
-- 
cgit v1.2.3


From 205061d2ac31d0c36909e37ab3e5db98725610aa Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Tue, 10 Jun 2014 08:28:56 +0200
Subject: use ServletContextPath from configuration

---
 .../java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
index ee26d9223..a7eb51877 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
@@ -364,7 +364,8 @@ public class AuthenticationManager extends AuthServlet {
 			throws ServletException, IOException, MOAIDException { 
 		
 			String form = SendAssertionFormBuilder.buildForm(target.requestedModule(), 
-					target.requestedAction(), target.getRequestID(), oaParam, request.getContextPath());
+					target.requestedAction(), target.getRequestID(), oaParam, 
+					AuthConfigurationProvider.getInstance().getPublicURLPrefix());
 						
 			response.setContentType("text/html;charset=UTF-8");
 			PrintWriter out = new PrintWriter(response.getOutputStream()); 
-- 
cgit v1.2.3


From d515dc2465a1daf5baa88c3059b9c2b0ea968df0 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <tlenz@iaik.tugraz.at>
Date: Tue, 10 Jun 2014 08:30:53 +0200
Subject: Load SLO template from configuration directory

---
 .../gv/egovernment/moa/id/moduls/SSOManager.java   |  67 ++-
 .../resources/templates/slo_template.html          | 463 +++++++++++++++++++--
 2 files changed, 480 insertions(+), 50 deletions(-)

(limited to 'id/server/idserverlib/src')

diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
index 02e252412..a46b11c6e 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
@@ -22,7 +22,15 @@
  *******************************************************************************/
 package at.gv.egovernment.moa.id.moduls;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.io.StringWriter;
+import java.net.URI;
 import java.util.List;
 
 import javax.servlet.http.Cookie;
@@ -31,6 +39,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
 import org.apache.velocity.app.VelocityEngine;
 import org.hibernate.Query;
 import org.hibernate.Session;
@@ -53,6 +62,9 @@ import at.gv.egovernment.moa.util.MiscUtil;
 
 public class SSOManager {
 	
+	private static final String HTMLTEMPLATESDIR = "htmlTemplates/";
+	private static final String HTMLTEMPLATEFULL = "slo_template.html";
+	
 	private static final String SSOCOOKIE = "MOA_ID_SSO";
 	private static final String SSOINTERFEDERATION = "MOA_INTERFEDERATION_SSO";
 	
@@ -274,24 +286,61 @@ public class SSOManager {
 	}
 	
 	public void printSingleLogOutInfo(VelocityContext context, HttpServletResponse httpResp) throws MOAIDException {		
-		try {		
+		try {			
 			Logger.trace("Initialize VelocityEngine...");
 			VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
-			Template template = velocityEngine.getTemplate("/resources/templates/slo_template.html");
-
-			StringWriter writer = new StringWriter();
-			template.merge(context, writer);
-        
-			httpResp.setContentType("text/html;charset=UTF-8");            
-			httpResp.getOutputStream().write(writer.toString().getBytes());
+			
+			InputStream is = null;
+			try {
+				String rootconfigdir = AuthConfigurationProvider.getInstance().getRootConfigFileDir();
+				String pathLocation = rootconfigdir + HTMLTEMPLATESDIR + HTMLTEMPLATEFULL;
+				File file = new File(new URI(pathLocation));
+				is = new  FileInputStream(file);
+				evaluateSLOTemplate(context, httpResp, is);
+				
+			} catch (Exception e) {
+				Logger.warn("SLO Template is not found in configuration directory. Load template from project library ... ");
+				
+				try  {
+					String pathLocation = "resources/templates/" + HTMLTEMPLATEFULL;
+					is = Thread.currentThread()
+							.getContextClassLoader()
+							.getResourceAsStream(pathLocation);				
+					evaluateSLOTemplate(context, httpResp, is);
+					
+				} catch (Exception e1) {
+					Logger.error("Single LogOut form can not created.", e);
+					throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
+				}
+				
+			} finally {
+				if (is != null)
+					is.close();
+				
+			}
 			
 		} catch (Exception e) {
-			Logger.error("Single LogOut from can not created.", e);
+			Logger.error("Single LogOut form can not created.", e);
 			throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
 		}
 			
 	}
 	
+	private void evaluateSLOTemplate(VelocityContext context, HttpServletResponse httpResp, InputStream is) throws ConfigurationException, IOException {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(is ));
+		
+		//set default elements to velocity context
+		context.put("contextpath", AuthConfigurationProvider.getInstance().getPublicURLPrefix());
+		
+		StringWriter writer = new StringWriter();			
+		//velocityEngine.evaluate(context, writer, "SLO_Template", reader);			
+		Velocity.evaluate(context, writer, "SLO Template", reader);
+
+		
+		httpResp.setContentType("text/html;charset=UTF-8");            
+		httpResp.getOutputStream().write(writer.toString().getBytes());
+		
+	}
 	
 	private String getValueFromCookie(HttpServletRequest httpReq, String cookieName) {
 		Cookie[] cookies = httpReq.getCookies();
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
index 16c9e87eb..a652855c4 100644
--- a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
+++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
@@ -1,57 +1,438 @@
 <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> 
+
+
+  <title>Single LogOut Vorgang ... </title>
+</head>
 
 <body>
-	<noscript>
+  <noscript>
 		<p>
 			<strong>Note:</strong> Since your browser does not support
 			JavaScript, you must press the Continue button once to proceed.
 		</p>
 	</noscript>
 
-	<h1>MOA-ID Single LogOut Information</h1>
+  <div id="page">
+		<div id="page1" class="case selected-case" role="main">
+			<h2 class="OA_header" role="heading">MOA-ID Single LogOut Information</h2>
+			<div id="main">
+				<div id="leftcontent" class="hell" role="application">
+          
+          #if($errorMsg)
+	         <div class="alert">
+		        <p>$errorMsg</p> 
+	         </div>	
+	        #end
 
-	<style type="text/css">
+	        #if($successMsg)
+	         <div>
+		        <p>$successMsg</p> 
+	         </div>	
+	        #end
 
-	#alert {
-		margin: 100px 250px;
-		font-family: Verdana, Arial, Helvetica, sans-serif;
-		font-size: 14px;
-		font-weight: normal;
-		color: red;
-	}
-	
-	#reqFrame {
-		display: none;
-		
-	}
-
-</style>
-
-	#if($errorMsg)
-	<div class="alert">
-		<p>$errorMsg</p> 
-	</div>	
-	#end
-
-	#if($successMsg)
-	<div>
-		<p>$successMsg</p> 
-	</div>	
-	#end
-
-	#if($redirectURLs)
-		<div>
-			<p>
-				Sie werden von allen Online-Applikationen abgemeldet. <br>
-				Dieser Vorgang kann einige Zeit in Anspruch nehmen.
-			</p>
+	        #if($redirectURLs)
+		        <div>
+			       <p>
+				        Sie werden von allen Online-Applikationen abgemeldet. <br>
+				        Dieser Vorgang kann einige Zeit in Anspruch nehmen.
+			       </p>
+		       </div>
+	       #end
+          
+				</div>
+			</div>
 		</div>
-	#end
-
-	#foreach( $el in $redirectURLs )
-		<iframe src=$el class="reqFrame"></iframe>
-	#end
+		<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>
 
 
+  #foreach( $el in $redirectURLs )
+	   <iframe src=$el class="reqframe"></iframe>
+  #end
+  
 </body>
 </html>
\ No newline at end of file
-- 
cgit v1.2.3