diff options
Diffstat (limited to 'id/server/idserverlib')
10 files changed, 1180 insertions, 347 deletions
| 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 new file mode 100644 index 000000000..a0f3dd309 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java @@ -0,0 +1,155 @@ +/* + * 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.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; + +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.metadata.SingleLogoutService; + +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; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; + +/** + * @author tlenz + * + */ +public class SLOInformationContainer implements Serializable { + +	private static final long serialVersionUID = 7148730740582881862L; +	 +	private PVPTargetConfiguration sloRequest = null; +	private LinkedHashMap<String, SLOInformationImpl> activeFrontChannalOAs = null; +	private LinkedHashMap<String, SLOInformationImpl> activeBackChannelOAs = null; +	private List<String> sloFailedOAs = null; +	 +	 +	public void parseActiveOAs(List<OASessionStore> dbOAs, String removeOAID) { +		activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); +		activeBackChannelOAs = 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)) {					 +					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()); +			}			 +		}		 +	} +		 +	public String getNextFrontChannelOA() { +		Iterator<String> interator = activeFrontChannalOAs.keySet().iterator(); +		if (interator.hasNext()) +			return interator.next(); +		 +		else +			return null;	 +	} +	 +	public SLOInformationImpl getFrontChannelOASessionDescripten(String oaID) { +		return activeFrontChannalOAs.get(oaID); +	} +	 +	public void removeFrontChannelOA(String oaID) { +		activeFrontChannalOAs.remove(oaID); +	} +	 +	public Iterator<String> getNextBackChannelOA() { +		return activeBackChannelOAs.keySet().iterator();	 +	} +	 +	public SLOInformationImpl getBackChannelOASessionDescripten(String oaID) { +		return activeBackChannelOAs.get(oaID); +	} +	 +	public void removeBackChannelOA(String oaID) { +		activeBackChannelOAs.remove(oaID); +	} +	 +	/** +	 * @return the sloRequest +	 */ +	public PVPTargetConfiguration getSloRequest() { +		return sloRequest; +	} +	 +	/** +	 * @param sloRequest the sloRequest to set +	 */ +	public void setSloRequest(PVPTargetConfiguration sloRequest) { +		this.sloRequest = sloRequest; +	} + +	/** +	 * @return the sloFailedOAs +	 */ +	public List<String> getSloFailedOAs() { +		return sloFailedOAs; +	} +	 +	public void putFailedOA(String oaID) { +		if (sloFailedOAs == null) +			sloFailedOAs = new ArrayList<String>(); +		sloFailedOAs.add(oaID); +	} + + +	 +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java index 02bd74291..55b213702 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java @@ -22,24 +22,39 @@   */  package at.gv.egovernment.moa.id.data; +import java.io.Serializable; + +import org.opensaml.saml2.metadata.SingleLogoutService; +  /**   * @author tlenz   *   */ -public class SLOInformationImpl implements SLOInformationInterface { - +public class SLOInformationImpl implements SLOInformationInterface, Serializable { +	private static final long serialVersionUID = 295577931870512387L;  	private String sessionIndex = null;  	private String nameID = null;  	private String protocolType = null;  	private String nameIDFormat = null; +	private String binding = null; +	private String serviceURL = null;  	public SLOInformationImpl(String sessionID, String nameID, String nameIDFormat, String protocolType) { +		new SLOInformationImpl(sessionID, nameID, nameIDFormat, protocolType, null); +	} +	 +	public SLOInformationImpl(String sessionID, String nameID, String nameIDFormat, String protocolType, SingleLogoutService sloService) {  		this.sessionIndex = sessionID;  		this.nameID = nameID;  		this.nameIDFormat = nameIDFormat;  		this.protocolType = protocolType; -				 +		 +		if (sloService != null) { +			this.binding = sloService.getBinding(); +			this.serviceURL = sloService.getLocation(); +			 +		}				  	} @@ -119,6 +134,20 @@ public class SLOInformationImpl implements SLOInformationInterface {  	public void setNameIDFormat(String nameIDFormat) {  		this.nameIDFormat = nameIDFormat;  	} + +	/** +	 * @return the binding +	 */ +	public String getBinding() { +		return binding; +	} + +	/** +	 * @return the serviceURL +	 */ +	public String getServiceURL() { +		return serviceURL; +	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java index 2c5682c0f..b2241f8ed 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java @@ -26,7 +26,7 @@ package at.gv.egovernment.moa.id.data;   * @author tlenz   *   */ -public interface SLOInformationInterface { +public interface SLOInformationInterface{  	/** 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 e2e6e752b..280b6495e 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 @@ -87,6 +87,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotH  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; @@ -288,6 +289,10 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  		} else if (e instanceof NameIDFormatNotSupportedException) {  			statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI);  			statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + +		} else if (e instanceof SLOException) { +			//SLOExecpetions only occurs if session information is lost +			return false;  		} else if(e instanceof PVP2Exception) {  			PVP2Exception ex = (PVP2Exception) e; 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 new file mode 100644 index 000000000..c67d10ab7 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java @@ -0,0 +1,361 @@ +/* + * 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.protocols.pvp2x; + +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.metadata.SingleLogoutService; +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 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.OASessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +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.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.SSOManager; +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.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.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.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public class SingleLogOutAction implements IAction { + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) +	 */ +	@Override +	public SLOInformationInterface processRequest(IRequest req, +			HttpServletRequest httpReq, HttpServletResponse httpResp, +			IAuthData authData) throws MOAIDException { + +		PVPTargetConfiguration pvpReq = (PVPTargetConfiguration) req;   +				 +		if (pvpReq.getRequest() instanceof MOARequest) { +			MOARequest samlReq = (MOARequest) pvpReq.getRequest(); +			if (samlReq.getSamlRequest() instanceof LogoutRequest) { +				Logger.debug("Process Single LogOut request"); +				LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); +				 +				AuthenticationSession session =  +						AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID( +								logOutReq.getIssuer().getValue(),  +								logOutReq.getNameID().getValue()); +				 +				if (session == null) { +					Logger.warn("Can not find active SSO session with nameID "  +							+ logOutReq.getNameID().getValue() + " and OA "  +							+ logOutReq.getIssuer().getValue()); +					Logger.info("Search active SSO session with SSO session cookie"); +					SSOManager ssomanager =  SSOManager.getInstance(); +					String ssoID = ssomanager.getSSOSessionID(httpReq); +					if (MiscUtil.isEmpty(ssoID)) { +						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()); +						return null; +						 +					} else { +						String moasession = ssomanager.getMOASession(ssoID);						 +						try { +							session = AuthenticationSessionStoreage.getSession(moasession); +														 +						} catch (MOADatabaseException e) { +							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()); +							return null; +							 +						}						 +					}					 +				} + +				//store active OAs to SLOContaine +				List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);				 +				SLOInformationContainer sloContainer = new SLOInformationContainer(); +				sloContainer.setSloRequest(pvpReq); +				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()); +							 +						} +						 +						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) { +				Logger.debug("Process Single LogOut response"); +				LogoutResponse logOutResp = (LogoutResponse) samlReq.getSamlRequest(); +														 +				try { +					if (MiscUtil.isEmpty(samlReq.getRelayState())) { +						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); +					 +				} catch (MOADatabaseException e) { +					Logger.error("MOA AssertionDatabase ERROR", e); +					throw new SLOException("pvp2.19", null); +					 +				} +							 +			} else { +				Logger.error("Process SingleLogOutAction but request is NOT of type LogoutRequest or LogoutResponse."); +				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;		 +	} + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) +	 */ +	@Override +	public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, +			HttpServletResponse httpResp) { +		return false; +	} + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() +	 */ +	@Override +	public String getDefaultActionName() { +		return PVP2XProtocol.SINGLELOGOUT; +	} +	 +	private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) { +		Status status = logOutResp.getStatus();				 +		if (!status.getStatusCode().equals(StatusCode.SUCCESS_URI)) { +			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue() +					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue() +					+ " Message: " + status.getStatusMessage().getMessage() + ")"); +			sloContainer.putFailedOA(logOutResp.getIssuer().getValue()); +			 +		} else +			Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS"); +		 +	} +	 +	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 new file mode 100644 index 000000000..04d374e93 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java @@ -0,0 +1,186 @@ +/* + * 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.protocols.pvp2x.builder; + +import java.util.List; + +import org.joda.time.DateTime; +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.Status; +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.SingleLogoutService; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; + +import at.gv.egovernment.moa.id.config.ConfigurationException; +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.config.PVPConfiguration; +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.utils.SAML2Utils; +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class SingleLogOutBuilder { + +	public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException { +		LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class); +		 +		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		 +		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); +		issuer.setFormat(NameID.ENTITY); +		sloReq.setIssuer(issuer);		 +		sloReq.setIssueInstant(new DateTime()); +		 +		sloReq.setDestination(sloInfo.getServiceURL()); +		 +		NameID nameID = SAML2Utils.createSAMLObject(NameID.class); +		nameID.setFormat(sloInfo.getUserNameIDFormat()); +		nameID.setValue(sloInfo.getUserNameIdentifier()); +		sloReq.setNameID(nameID ); +				 +		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());		 +		Status status = SAML2Utils.createSAMLObject(Status.class); +		StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); +		StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); +		statusCode.setValue(StatusCode.PARTIAL_LOGOUT_URI); +		statusMessage.setMessage(MOAIDMessageProvider.getInstance().getMessage("pvp2.18", null)); +		status.setStatusCode(statusCode); +		status.setStatusMessage(statusMessage); +		sloResp.setStatus(status); +		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()); +		 +		Status status; +		if (failedOAs == null || failedOAs.size() == 0) { +			status = SAML2Utils.getSuccessStatus(); +			 +		} else { +			status = SAML2Utils.createSAMLObject(Status.class); +			StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); +			StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); +			statusCode.setValue(StatusCode.PARTIAL_LOGOUT_URI); +			statusMessage.setMessage(MOAIDMessageProvider.getInstance().getMessage("pvp2.18", null)); +			status.setStatusCode(statusCode); +			status.setStatusMessage(statusMessage); +			 +		}						 +		sloResp.setStatus(status); +		return sloResp; +		 +	} +	 +	public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException { +		try { +			EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID); +			SPSSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); +			 +			SingleLogoutService sloService = null;			 +			for (SingleLogoutService el : spsso.getSingleLogoutServices()) { +				if (el.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) +					sloService = el; +				 +				else  if (el.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)   +						&& ( +								(sloService != null && !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_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); +				 +			}			 +			return sloService; +			 +		} catch (MetadataProviderException e) { +			Logger.error("Found no SLO ServiceDescriptor in Metadata");				 +			throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); +		}		 + +	} +	 +	public static SingleLogoutService getResponseSLODescriptor(PVPTargetConfiguration spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException { +		MOARequest moaReq = (MOARequest) spRequest.getRequest(); +		EntityDescriptor metadata = moaReq.getEntityMetadata(); +		SPSSODescriptor spsso = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); +			 +		SingleLogoutService sloService = null;			 +		for (SingleLogoutService el : spsso.getSingleLogoutServices()) { +			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); +		} +		return sloService; +	} +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NOSLOServiceDescriptorException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NOSLOServiceDescriptorException.java new file mode 100644 index 000000000..204e1c2a5 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NOSLOServiceDescriptorException.java @@ -0,0 +1,44 @@ +/* + * 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.protocols.pvp2x.exceptions; + +/** + * @author tlenz + * + */ +public class NOSLOServiceDescriptorException extends PVP2Exception { + +	/** +	 *  +	 */ +	private static final long serialVersionUID = -3073730570511152661L; + +	/** +	 * @param messageId +	 * @param parameters +	 */ +	public NOSLOServiceDescriptorException(String messageId, Object[] parameters) { +		super(messageId, parameters); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SLOException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SLOException.java new file mode 100644 index 000000000..9f1b6168e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SLOException.java @@ -0,0 +1,41 @@ +/* + * 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.protocols.pvp2x.exceptions; + +/** + * @author tlenz + * + */ +public class SLOException extends PVP2Exception { +	private static final long serialVersionUID = -5284624715788385022L; + +	/** +	 * @param messageId +	 * @param parameters +	 */ +	public SLOException(String messageId, Object[] parameters) { +		super(messageId, parameters); +		// TODO Auto-generated constructor stub +	} + +} 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 6437a4cac..74a5e01ad 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 @@ -69,21 +69,6 @@ public class AuthenticationSessionStoreage {  		}  	} -	public static void setAuthenticated(String moaSessionID, boolean value) { -		 -		AuthenticatedSessionStore session; -		 -		try { -			session = searchInDatabase(moaSessionID); -			session.setAuthenticated(value); -			MOASessionDBUtils.saveOrUpdate(session); - -			 -		} catch (MOADatabaseException e) { -			Logger.warn("isAuthenticated can not be stored in MOASession " + moaSessionID, e); -		} -	} -	  	public static AuthenticationSession createSession() throws MOADatabaseException {  		String id = Random.nextRandom();  		AuthenticationSession session = new AuthenticationSession(id); @@ -110,108 +95,39 @@ public class AuthenticationSessionStoreage {  		return session;  	} -	 -	public static String createInterfederatedSession(IRequest req, boolean isAuthenticated) throws MOADatabaseException, AssertionAttributeExtractorExeption { -		String id = Random.nextRandom(); -		AuthenticationSession session = new AuthenticationSession(id); -		session.setAuthenticated(true); -		session.setAuthenticatedUsed(false); -		 -		AuthenticatedSessionStore dbsession = new AuthenticatedSessionStore(); -		dbsession.setSessionid(id); -		dbsession.setAuthenticated(isAuthenticated); -		dbsession.setInterfederatedSSOSession(true); -		 -		//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)); -		 -		//add interfederation information -		List<InterfederationSessionStore> idpList = dbsession.getInderfederation(); -		InterfederationSessionStore idp = null; -		if (idpList == null) { -			idpList = new ArrayList<InterfederationSessionStore>(); -			dbsession.setInderfederation(idpList); -			 -		} else { -			for (InterfederationSessionStore el : idpList) { -				//resue old entry if interfederation IDP is reused for authentication -				if (el.getIdpurlprefix().equals(req.getInterfederationResponse().getEntityID())) -					idp = el; -				 -			}			 -		} -		//create new interfederation IDP entry -		if (idp == null) { -			idp = new InterfederationSessionStore(); -			idp.setCreated(now); -			idp.setIdpurlprefix(req.getInterfederationResponse().getEntityID()); -			 -		} -		 -		AssertionAttributeExtractor extract = new AssertionAttributeExtractor(req.getInterfederationResponse().getResponse());		 -		idp.setSessionIndex(extract.getSessionIndex()); -		idp.setUserNameID(extract.getNameID()); -		idp.setAttributesRequested(false); -		idp.setQAALevel(extract.getQAALevel()); -		idp.setMoasession(dbsession); -		idpList.add(idp); -		 +	public static AuthenticationSession getSession(String sessionID) throws MOADatabaseException { -		//store AssertionStore element to Database  		try { -			MOASessionDBUtils.saveOrUpdate(dbsession); -			Logger.info("MOASession with sessionID=" + id + " is stored in Database"); -			 +			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); +			return decryptSession(dbsession); +								  		} catch (MOADatabaseException e) { -			Logger.warn("MOASession could not be created."); -			throw new MOADatabaseException(e); +			Logger.info("No MOA Session with id: " + sessionID); +			throw new MOADatabaseException("No MOA Session with id: " + sessionID); +			 +		} catch (Throwable e) { +			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + sessionID, e); +			throw new MOADatabaseException("MOASession deserialization-exception");  		} -		 -		return id;  	} -		 +	  	public static void storeSession(AuthenticationSession session) throws MOADatabaseException, BuildException { -		 -		try { -			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID()); -			dbsession.setAuthenticated(session.isAuthenticated()); -			byte[] serialized = SerializationUtils.serialize(session); -			 -			EncryptedData encdata = SessionEncrytionUtil.encrypt(serialized); -			dbsession.setSession(encdata.getEncData()); -			dbsession.setIv(encdata.getIv()); -			 -			//set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 -			dbsession.setUpdated(new Date()); -			 -			MOASessionDBUtils.saveOrUpdate(dbsession); -			Logger.debug("MOASession with sessionID=" + session.getSessionID() + " is stored in Database"); -			 -		} catch (MOADatabaseException e) { -			Logger.warn("MOASession could not be stored."); -			throw new MOADatabaseException(e); -		} 	 +		storeSession(session, null);  	}  	public static void storeSession(AuthenticationSession session, String pendingRequestID) throws MOADatabaseException, BuildException {  		try {  			AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID()); -			dbsession.setPendingRequestID(pendingRequestID); -			dbsession.setAuthenticated(session.isAuthenticated()); -			byte[] serialized = SerializationUtils.serialize(session); -			 -			EncryptedData encdata = SessionEncrytionUtil.encrypt(serialized); -			dbsession.setSession(encdata.getEncData()); -			dbsession.setIv(encdata.getIv()); +			if (MiscUtil.isNotEmpty(pendingRequestID)) +				dbsession.setPendingRequestID(pendingRequestID); +						 +			encryptSession(session, dbsession);  			//set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 +			dbsession.setAuthenticated(session.isAuthenticated());  			dbsession.setUpdated(new Date());  			MOASessionDBUtils.saveOrUpdate(dbsession); @@ -223,7 +139,6 @@ public class AuthenticationSessionStoreage {  		} 	  	} -	  	public static void destroySession(String moaSessionID) throws MOADatabaseException {  		Session session = MOASessionDBUtils.getCurrentSession(); @@ -246,10 +161,8 @@ public class AuthenticationSessionStoreage {  			   	throw new MOADatabaseException("No session found with this sessionID");  			  } -			 AuthenticatedSessionStore dbsession = (AuthenticatedSessionStore) result.get(0); -			  -			 session.getTransaction().commit(); -			   +			 AuthenticatedSessionStore dbsession = (AuthenticatedSessionStore) result.get(0);			  +			 session.getTransaction().commit();			    			 cleanDelete(dbsession);			  		  } @@ -267,16 +180,11 @@ public class AuthenticationSessionStoreage {  					+ "to " + id);  			session.setSessionID(id); +			encryptSession(session, dbsession);  			dbsession.setSessionid(id);  			dbsession.setAuthenticated(session.isAuthenticated()); -			 -			byte[] serialized = SerializationUtils.serialize(session); -			 -			EncryptedData encdata = SessionEncrytionUtil.encrypt(serialized); -			dbsession.setSession(encdata.getEncData()); -			dbsession.setIv(encdata.getIv()); -			 +						  			//set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1  			dbsession.setUpdated(new Date()); @@ -290,7 +198,92 @@ public class AuthenticationSessionStoreage {  			throw new AuthenticationException("TODO!", null);  		}  	} +		 +	public static void setAuthenticated(String moaSessionID, boolean value) { +		 +		AuthenticatedSessionStore session; +		 +		try { +			session = searchInDatabase(moaSessionID); +			session.setAuthenticated(value); +			MOASessionDBUtils.saveOrUpdate(session); +			 +		} catch (MOADatabaseException e) { +			Logger.warn("isAuthenticated can not be stored in MOASession " + moaSessionID, e); +		} +	} +	 +	public static String getMOASessionSSOID(String SSOSessionID) { +		  MiscUtil.assertNotNull(SSOSessionID, "moasessionID");	   +		  Logger.trace("Get authenticated session with SSOID " + SSOSessionID + " from database."); +		  Session session = MOASessionDBUtils.getCurrentSession(); +		   +		  List<AuthenticatedSessionStore> result; +		   +		  synchronized (session) { +			  session.beginTransaction(); +			  Query query = session.getNamedQuery("getSessionWithSSOID"); +			  query.setParameter("sessionid", SSOSessionID); +			  result = query.list(); +			   +			  //send transaction +			  session.getTransaction().commit(); +		  } +		   +		  Logger.trace("Found entries: " + result.size()); +		   +		  //Assertion requires an unique artifact +		  if (result.size() != 1) { +			 Logger.trace("No entries found."); +			 return null; +					  +		  } else { +			  return result.get(0).getSessionid(); +			  +		  }		   +	} +	 +	public static boolean isSSOSession(String sessionID) throws MOADatabaseException { +		try { +			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); +			return dbsession.isSSOSession(); +			 +		} catch (MOADatabaseException e) { +			Logger.info("No MOA Session with id: " + sessionID); +			throw new MOADatabaseException("No MOA Session with id: " + sessionID); +		}				 +	} +	 +	public static AuthenticatedSessionStore isValidSessionWithSSOID(String SSOId, String moaSessionId) {		 +		  MiscUtil.assertNotNull(SSOId, "SSOSessionID");	   +		  Logger.trace("Get authenticated session with SSOID " + SSOId + " from database."); +		  Session session = MOASessionDBUtils.getCurrentSession(); +		   +		  List<AuthenticatedSessionStore> result; +		   +		  synchronized (session) { +			  session.beginTransaction(); +			  Query query = session.getNamedQuery("getSessionWithSSOID"); +			  query.setParameter("sessionid", SSOId); +			  result = query.list(); +			   +			  //send transaction +			  session.getTransaction().commit(); +		  } +		   +		  Logger.trace("Found entries: " + result.size()); +		   +		  //Assertion requires an unique artifact +		  if (result.size() != 1) { +			 Logger.trace("No entries found."); +			 return null; +					  +		  } else { +			  return result.get(0); +		  }		 +	} +	  	public static void addSSOInformation(String moaSessionID, String SSOSessionID,   			SLOInformationInterface SLOInfo, String OAUrl) throws AuthenticationException { @@ -390,56 +383,36 @@ public class AuthenticationSessionStoreage {  	  		 throw new AuthenticationException("SSO Session information can not be stored!  --> SSO is deactivated", null);	  	  	 }  	} -	 -	 -	public static AuthenticationSession getSession(String sessionID) throws MOADatabaseException { + +	public static List<OASessionStore> getAllActiveOAFromMOASession(AuthenticationSession moaSession) { +		MiscUtil.assertNotNull(moaSession, "MOASession");  		try { -			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); +			AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID()); +			return dbsession.getActiveOAsessions(); -			//decrypt Session -			EncryptedData encdata = new EncryptedData(dbsession.getSession(), -					dbsession.getIv()); -			byte[] decrypted = SessionEncrytionUtil.decrypt(encdata); -					 -			AuthenticationSession session = (AuthenticationSession) SerializationUtils.deserialize(decrypted); - -			return session; -								  		} catch (MOADatabaseException e) { -			Logger.info("No MOA Session with id: " + sessionID); -			throw new MOADatabaseException("No MOA Session with id: " + sessionID); -			 -		} catch (Throwable e) { -			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + sessionID, e); -			throw new MOADatabaseException("MOASession deserialization-exception"); -		} -	} -	 -	public static boolean isSSOSession(String sessionID) throws MOADatabaseException { -		try { -			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); -			return dbsession.isSSOSession(); +			Logger.warn("NO session information found for sessionID " + moaSession.getSessionID(), e); -		} catch (MOADatabaseException e) { -			Logger.info("No MOA Session with id: " + sessionID); -			throw new MOADatabaseException("No MOA Session with id: " + sessionID);  		} -		 -		 +				 +		return null;  	} -	public static String getMOASessionSSOID(String SSOSessionID) { -		  MiscUtil.assertNotNull(SSOSessionID, "moasessionID");	   -		  Logger.trace("Get authenticated session with SSOID " + SSOSessionID + " from database."); +	public static AuthenticationSession searchMOASessionWithNameIDandOAID(String oaID, String userNameID) {	   +		  MiscUtil.assertNotNull(oaID, "OnlineApplicationIdentifier"); +		  MiscUtil.assertNotNull(userNameID, "userNameID"); +		  Logger.trace("Get moaSession for userNameID " + userNameID + " and OA "  +				  + oaID + " from database.");  		  Session session = MOASessionDBUtils.getCurrentSession(); -		   +  		  List<AuthenticatedSessionStore> result;  		  synchronized (session) {  			  session.beginTransaction(); -			  Query query = session.getNamedQuery("getSessionWithSSOID"); -			  query.setParameter("sessionid", SSOSessionID); +			  Query query = session.getNamedQuery("getMOASessionWithNameIDandOAID"); +			  query.setParameter("oaID", oaID); +			  query.setParameter("nameID", userNameID);  			  result = query.list();  			  //send transaction @@ -450,28 +423,35 @@ public class AuthenticationSessionStoreage {  		  //Assertion requires an unique artifact  		  if (result.size() != 1) { -			 Logger.trace("No entries found."); -			 return null; -					  -		  } else { -			  return result.get(0).getSessionid(); -			  +			 Logger.trace("No unique entry found."); +		   	 return null; +		   	  		  } -		   +		try {  		   +			return  decryptSession(result.get(0)); +			 +		} catch (BuildException e) { +			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + result.get(0).getSessionid(), e); +			return null; +		}  	} -	public static AuthenticatedSessionStore isValidSessionWithSSOID(String SSOId, String moaSessionId) { -		 -		  MiscUtil.assertNotNull(SSOId, "SSOSessionID");	   -		  Logger.trace("Get authenticated session with SSOID " + SSOId + " from database."); +	public static OASessionStore searchActiveOASSOSession(AuthenticationSession moaSession, String oaID, String protocolType) { +		  MiscUtil.assertNotNull(moaSession, "MOASession");	   +		  MiscUtil.assertNotNull(oaID, "OnlineApplicationIdentifier"); +		  MiscUtil.assertNotNull(protocolType, "usedProtocol"); +		  Logger.trace("Get active OnlineApplication for sessionID " + moaSession.getSessionID() + " with OAID " +				  + oaID + " from database.");  		  Session session = MOASessionDBUtils.getCurrentSession();  		  List<AuthenticatedSessionStore> result;  		  synchronized (session) {  			  session.beginTransaction(); -			  Query query = session.getNamedQuery("getSessionWithSSOID"); -			  query.setParameter("sessionid", SSOId); +			  Query query = session.getNamedQuery("getActiveOAWithSessionIDandOAIDandProtocol"); +			  query.setParameter("sessionID", moaSession.getSessionID()); +			  query.setParameter("oaID", oaID); +			  query.setParameter("protocol", protocolType);  			  result = query.list();  			  //send transaction @@ -481,14 +461,58 @@ public class AuthenticationSessionStoreage {  		  Logger.trace("Found entries: " + result.size());  		  //Assertion requires an unique artifact -		  if (result.size() != 1) { +		  if (result.size() == 0) {  			 Logger.trace("No entries found."); -			 return null; -					  -		  } else { -			  return result.get(0); +		   	 return null; +		   	  		  } -		 +		   +		  return  result.get(0).getActiveOAsessions().get(0); +	} +	 +	public static String getPendingRequestID(String sessionID) { +		try { +			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); +			return dbsession.getPendingRequestID(); +			 +		} catch (MOADatabaseException e) { +			Logger.warn("MOASession with ID " + sessionID + " not found"); +			return ""; +		} +	} +	 +	public static AuthenticationSession getSessionWithPendingRequestID(String pedingRequestID) { +		try { +			  MiscUtil.assertNotNull(pedingRequestID, "pedingRequestID");	   +			  Logger.trace("Get authenticated session with pedingRequestID " + pedingRequestID + " from database."); +			  Session session = MOASessionDBUtils.getCurrentSession(); +			   +			  List<AuthenticatedSessionStore> result; +			   +			  synchronized (session) { +				  session.beginTransaction(); +				  Query query = session.getNamedQuery("getSessionWithPendingRequestID"); +				  query.setParameter("sessionid", pedingRequestID); +				  result = query.list(); +				   +				  //send transaction +				  session.getTransaction().commit(); +			  } +			   +			  Logger.trace("Found entries: " + result.size()); +			   +			  //Assertion requires an unique artifact +			  if (result.size() != 1) { +				 Logger.trace("No entries found."); +			   	return null; +			  } +			 +			  return decryptSession(result.get(0)); +			  								 +		} catch (Throwable e) { +			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + pedingRequestID); +			return null; +		}  	}  	public static boolean deleteSessionWithPendingRequestID(String id) { @@ -522,20 +546,7 @@ public class AuthenticationSessionStoreage {  	} -	 -	public static String getPendingRequestID(String sessionID) { -		try { -			AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); -			return dbsession.getPendingRequestID(); -		} catch (MOADatabaseException e) { -			Logger.warn("MOASession with ID " + sessionID + " not found"); -			return ""; -		} -		 -	} -	 -	  	public static AuthenticationSession getSessionWithUserNameID(String nameID) {  		try { @@ -558,149 +569,20 @@ public class AuthenticationSessionStoreage {  			  Logger.trace("Found entries: " + result.size());  			  //Assertion requires an unique artifact -			  if (result.size() != 1) { +			  if (result.size() == 0) {  				 Logger.trace("No entries found.");  			   	return null;  			  } -			//decrypt Session -			EncryptedData encdata = new EncryptedData(result.get(0).getSession(), -						result.get(0).getIv()); -			byte[] decrypted = SessionEncrytionUtil.decrypt(encdata);			  					 -			return (AuthenticationSession) SerializationUtils.deserialize(decrypted); -			 -								 +			  return decryptSession(result.get(0)); +											  		} catch (Throwable e) {  			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + nameID);  			return null;  		}  	} -	 -	public static AuthenticationSession getSessionWithPendingRequestID(String pedingRequestID) { -		 -		try { -			  MiscUtil.assertNotNull(pedingRequestID, "pedingRequestID");	   -			  Logger.trace("Get authenticated session with pedingRequestID " + pedingRequestID + " from database."); -			  Session session = MOASessionDBUtils.getCurrentSession(); -			   -			  List<AuthenticatedSessionStore> result; -			   -			  synchronized (session) { -				  session.beginTransaction(); -				  Query query = session.getNamedQuery("getSessionWithPendingRequestID"); -				  query.setParameter("sessionid", pedingRequestID); -				  result = query.list(); -				   -				  //send transaction -				  session.getTransaction().commit(); -			  } -			   -			  Logger.trace("Found entries: " + result.size()); -			   -			  //Assertion requires an unique artifact -			  if (result.size() != 1) { -				 Logger.trace("No entries found."); -			   	return null; -			  } -			 -			//decrypt Session -			EncryptedData encdata = new EncryptedData(result.get(0).getSession(), -						result.get(0).getIv()); -			byte[] decrypted = SessionEncrytionUtil.decrypt(encdata);			  					 -			return (AuthenticationSession) SerializationUtils.deserialize(decrypted); -			 -								 -		} catch (Throwable e) { -			Logger.warn("MOASession deserialization-exception by using MOASessionID=" + pedingRequestID); -			return null; -		} -	} -	 -	public static void clean(long now, long authDataTimeOutCreated, long authDataTimeOutUpdated) { -		Date expioredatecreate = new Date(now - authDataTimeOutCreated);		 -		Date expioredateupdate = new Date(now - authDataTimeOutUpdated); -		 -		List<AuthenticatedSessionStore> results; -		Session session = MOASessionDBUtils.getCurrentSession(); -		 -		synchronized (session) {			 -			session.beginTransaction(); -			Query query = session.getNamedQuery("getMOAISessionsWithTimeOut"); -			query.setTimestamp("timeoutcreate", expioredatecreate); -			query.setTimestamp("timeoutupdate", expioredateupdate); -			results = query.list(); -			session.getTransaction().commit(); -		} -		 -		if (results.size() != 0) { -			for(AuthenticatedSessionStore result : results) { -				try {  -					cleanDelete(result); -					Logger.info("Authenticated session with sessionID=" + result.getSessionid()  -							+ " after session timeout."); -				} catch (HibernateException e){ -					Logger.warn("Authenticated session with sessionID=" + result.getSessionid()  -							+ " not removed after timeout! (Error during Database communication)", e); -				} - -			}	 -		}	 -	} -	 -	private static void cleanDelete(AuthenticatedSessionStore result) {		 -		try { -			result.setSession(new byte[] {}); -			MOASessionDBUtils.saveOrUpdate(result); -			 -		} catch (MOADatabaseException e) { -			Logger.warn("Blank authenticated session with sessionID=" + result.getSessionid() + " FAILED.", e); -			 -		} finally { -			if (!MOASessionDBUtils.delete(result)) -				Logger.error("Authenticated session with sessionID=" + result.getSessionid()  -							+ " not removed! (Error during Database communication)"); -			 -		} -		 -		 -	} -	 -	public static OASessionStore searchActiveOASSOSession(AuthenticationSession moaSession, String oaID, String protocolType) { -		  MiscUtil.assertNotNull(moaSession, "MOASession");	   -		  MiscUtil.assertNotNull(oaID, "OnlineApplicationIdentifier"); -		  MiscUtil.assertNotNull(protocolType, "usedProtocol"); -		  Logger.trace("Get active OnlineApplication for sessionID " + moaSession.getSessionID() + " with OAID " -				  + oaID + " from database."); -		  Session session = MOASessionDBUtils.getCurrentSession(); -		   -		  List<AuthenticatedSessionStore> result; -		   -		  synchronized (session) { -			  session.beginTransaction(); -			  Query query = session.getNamedQuery("getActiveOAWithSessionIDandOAIDandProtocol"); -			  query.setParameter("sessionID", moaSession.getSessionID()); -			  query.setParameter("oaID", oaID); -			  query.setParameter("protocol", protocolType); -			  result = query.list(); -			   -			  //send transaction -			  session.getTransaction().commit(); -		  } -		   -		  Logger.trace("Found entries: " + result.size()); -		   -		  //Assertion requires an unique artifact -		  if (result.size() == 0) { -			 Logger.trace("No entries found."); -		   	 return null; -		   	 -		  } -		   -		  return  result.get(0).getActiveOAsessions().get(0); -	} -	  	public static InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASession(String sessionID) {  		  MiscUtil.assertNotNull(sessionID, "MOASession");	    		  Logger.trace("Get interfederated IDP for SSO with sessionID " + sessionID + " from database."); @@ -761,6 +643,70 @@ public class AuthenticationSessionStoreage {  		  return result.get(0).getInderfederation().get(0);  	} +	public static String createInterfederatedSession(IRequest req, boolean isAuthenticated) throws MOADatabaseException, AssertionAttributeExtractorExeption { +		String id = Random.nextRandom(); +		AuthenticationSession session = new AuthenticationSession(id); +		session.setAuthenticated(true); +		session.setAuthenticatedUsed(false); +		 +		AuthenticatedSessionStore dbsession = new AuthenticatedSessionStore(); +		dbsession.setSessionid(id); +		dbsession.setAuthenticated(isAuthenticated); +		dbsession.setInterfederatedSSOSession(true); +		 +		//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)); +		 +		//add interfederation information +		List<InterfederationSessionStore> idpList = dbsession.getInderfederation(); +		InterfederationSessionStore idp = null; +		if (idpList == null) { +			idpList = new ArrayList<InterfederationSessionStore>(); +			dbsession.setInderfederation(idpList); +			 +		} else { +			for (InterfederationSessionStore el : idpList) { +				//resue old entry if interfederation IDP is reused for authentication +				if (el.getIdpurlprefix().equals(req.getInterfederationResponse().getEntityID())) +					idp = el; +				 +			}			 +		} + +		//create new interfederation IDP entry +		if (idp == null) { +			idp = new InterfederationSessionStore(); +			idp.setCreated(now); +			idp.setIdpurlprefix(req.getInterfederationResponse().getEntityID()); +			 +		} +		 +		AssertionAttributeExtractor extract = new AssertionAttributeExtractor(req.getInterfederationResponse().getResponse());		 +		idp.setSessionIndex(extract.getSessionIndex()); +		idp.setUserNameID(extract.getNameID()); +		idp.setAttributesRequested(false); +		idp.setQAALevel(extract.getQAALevel()); +		idp.setMoasession(dbsession); +		idpList.add(idp); +		 +		 +		//store AssertionStore element to Database +		try { +			MOASessionDBUtils.saveOrUpdate(dbsession); +			Logger.info("MOASession with sessionID=" + id + " is stored in Database"); +			 +		} catch (MOADatabaseException e) { +			Logger.warn("MOASession could not be created."); +			throw new MOADatabaseException(e); +		} +		 +		return id; +	} +	  	public static InterfederationSessionStore searchInterfederatedIDPFORAttributeQueryWithSessionID(AuthenticationSession moaSession) {  		  MiscUtil.assertNotNull(moaSession, "MOASession");	    		  Logger.trace("Get interfederated IDP for AttributeQuery with sessionID " + moaSession.getSessionID() + " from database."); @@ -790,35 +736,6 @@ public class AuthenticationSessionStoreage {  		  return result.get(0).getInderfederation().get(0);  	} -	@SuppressWarnings("rawtypes") -	private static AuthenticatedSessionStore searchInDatabase(String sessionID) throws MOADatabaseException { -		  MiscUtil.assertNotNull(sessionID, "moasessionID");	   -		  Logger.trace("Get authenticated session with sessionID " + sessionID + " from database."); -		  Session session = MOASessionDBUtils.getCurrentSession(); -		   -		  List result; -		   -		  synchronized (session) { -			  session.beginTransaction(); -			  Query query = session.getNamedQuery("getSessionWithID"); -			  query.setParameter("sessionid", sessionID); -			  result = query.list(); -			   -			  //send transaction -			  session.getTransaction().commit(); -		  } -		   -		  Logger.trace("Found entries: " + result.size()); -		   -		  //Assertion requires an unique artifact -		  if (result.size() != 1) { -			 Logger.trace("No entries found."); -		   	throw new MOADatabaseException("No session found with this sessionID"); -		  } -		   -		  return (AuthenticatedSessionStore) result.get(0); -	} -  	/**  	 * @param entityID  	 * @param requestID @@ -872,4 +789,97 @@ public class AuthenticationSessionStoreage {  			return false;  		}		  	} +	 +	public static void clean(long now, long authDataTimeOutCreated, long authDataTimeOutUpdated) { +		Date expioredatecreate = new Date(now - authDataTimeOutCreated);		 +		Date expioredateupdate = new Date(now - authDataTimeOutUpdated); +		 +		List<AuthenticatedSessionStore> results; +		Session session = MOASessionDBUtils.getCurrentSession(); +		 +		synchronized (session) {			 +			session.beginTransaction(); +			Query query = session.getNamedQuery("getMOAISessionsWithTimeOut"); +			query.setTimestamp("timeoutcreate", expioredatecreate); +			query.setTimestamp("timeoutupdate", expioredateupdate); +			results = query.list(); +			session.getTransaction().commit(); +		} +		 +		if (results.size() != 0) { +			for(AuthenticatedSessionStore result : results) { +				try {  +					cleanDelete(result); +					Logger.info("Authenticated session with sessionID=" + result.getSessionid()  +							+ " after session timeout."); +				 +				} catch (HibernateException e){ +					Logger.warn("Authenticated session with sessionID=" + result.getSessionid()  +							+ " not removed after timeout! (Error during Database communication)", e); +				} +			}	 +		}	 +	} +	 +	private static void encryptSession(AuthenticationSession session, AuthenticatedSessionStore dbsession) throws BuildException { +		byte[] serialized = SerializationUtils.serialize(session); +		 +		EncryptedData encdata = SessionEncrytionUtil.encrypt(serialized); +		dbsession.setSession(encdata.getEncData()); +		dbsession.setIv(encdata.getIv()); +	} +	 +	private static AuthenticationSession decryptSession(AuthenticatedSessionStore dbsession) throws BuildException { +		EncryptedData encdata = new EncryptedData(dbsession.getSession(), +				dbsession.getIv()); +		byte[] decrypted = SessionEncrytionUtil.decrypt(encdata); +				 +		return (AuthenticationSession) SerializationUtils.deserialize(decrypted); +		 +	} +	 +	private static void cleanDelete(AuthenticatedSessionStore result) {		 +		try { +			result.setSession(new byte[] {}); +			MOASessionDBUtils.saveOrUpdate(result); +			 +		} catch (MOADatabaseException e) { +			Logger.warn("Blank authenticated session with sessionID=" + result.getSessionid() + " FAILED.", e); +			 +		} finally { +			if (!MOASessionDBUtils.delete(result)) +				Logger.error("Authenticated session with sessionID=" + result.getSessionid()  +							+ " not removed! (Error during Database communication)"); +			 +		} +	} +	 +	@SuppressWarnings("rawtypes") +	private static AuthenticatedSessionStore searchInDatabase(String sessionID) throws MOADatabaseException { +		  MiscUtil.assertNotNull(sessionID, "moasessionID");	   +		  Logger.trace("Get authenticated session with sessionID " + sessionID + " from database."); +		  Session session = MOASessionDBUtils.getCurrentSession(); +		   +		  List result; +		   +		  synchronized (session) { +			  session.beginTransaction(); +			  Query query = session.getNamedQuery("getSessionWithID"); +			  query.setParameter("sessionid", sessionID); +			  result = query.list(); +			   +			  //send transaction +			  session.getTransaction().commit(); +		  } +		   +		  Logger.trace("Found entries: " + result.size()); +		   +		  //Assertion requires an unique artifact +		  if (result.size() != 1) { +			 Logger.trace("No entries found."); +		   	throw new MOADatabaseException("No session found with this sessionID"); +		  } +		   +		  return (AuthenticatedSessionStore) result.get(0); +	}  } 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 0a228c318..72fb8cf27 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 @@ -234,6 +234,8 @@ pvp2.14=SAML Anfrage verweigert  pvp2.15=Keine Metadateninformation gefunden
  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 wurde wegen eines unkorregierbaren Fehler abgebrochen. 
  oauth20.01=Fehlerhafte redirect url
  oauth20.02=Fehlender Parameter "{0}"
 | 
