diff options
| author | Thomas Lenz <tlenz@iaik.tugraz.at> | 2014-06-06 13:49:25 +0200 | 
|---|---|---|
| committer | Thomas Lenz <tlenz@iaik.tugraz.at> | 2014-06-06 13:49:25 +0200 | 
| commit | f54870a55c9830caa2862d95e2e7f8f3cd6e0243 (patch) | |
| tree | fb25a52c2f8afad1adafa3d92696aa21ad9e81ed /id/server/idserverlib/src | |
| parent | 0334cd30ddd9719b0801a274250be8476e0e95be (diff) | |
| download | moa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.tar.gz moa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.tar.bz2 moa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.zip | |
final betaversion if MOA-ID-Auth Single LogOut
Diffstat (limited to 'id/server/idserverlib/src')
16 files changed, 863 insertions, 271 deletions
| 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 "sourceID" */    public static final String PARAM_SOURCEID = "sourceID";      /** servlet parameter "BKUSelectionTemplate" */ 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 | 
