/* * 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.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.lang.SerializationUtils; import org.joda.time.DateTime; import org.opensaml.Configuration; 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.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.ws.soap.common.SOAPException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.x509.X509Credential; import org.opensaml.xml.signature.Signature; import org.opensaml.xml.signature.SignatureConstants; import org.opensaml.xml.signature.Signer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.w3c.dom.Document; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; import at.gv.egiz.eaaf.core.api.idp.slo.ISLOInformationContainer; import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.impl.data.SLOInformationImpl; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; import at.gv.egiz.eaaf.modules.pvp2.exception.BindingNotSupportedException; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException; import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.StringRedirectDeflateEncoder; import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.frontend.builder.DefaultGUIFormBuilderConfiguration; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; 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; import at.gv.egovernment.moa.id.commons.utils.MOAIDMessageProvider; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngineSP; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; /** * @author tlenz * */ @Service("PVP_SingleLogOutBuilder") public class SingleLogOutBuilder { @Autowired(required=true) private MOAMetadataProvider metadataProvider; @Autowired(required=true) ApplicationContext springContext; @Autowired private IDPCredentialProvider credentialProvider; @Autowired private SAMLVerificationEngineSP samlVerificationEngine; @Autowired private IGUIFormBuilder guiBuilder; @Autowired(required=true) protected IRevisionLogger revisionsLogger; @Autowired private ITransactionStorage transactionStorage; @Autowired(required=true) IPVP2BasicConfiguration pvpBasicConfiguration; public static final int SLOTIMEOUT = 30 * 1000; //30 sec public void toTechnicalLogout(ISLOInformationContainer sloContainer, HttpServletRequest httpReq, HttpServletResponse httpResp, String authUrl) throws EAAFException { Logger.trace("Starting Service-Provider logout process ... "); revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), MOAIDEventConstants.AUTHPROCESS_SLO_STARTED); //start service provider back channel logout process Iterator nextOAInterator = sloContainer.getNextBackChannelOA(); while (nextOAInterator.hasNext()) { SLOInformationInterface sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); LogoutRequest sloReq = buildSLORequestMessage(sloDescr); try { Logger.trace("Send backchannel SLO Request to " + sloDescr.getSpEntityID()); List 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 " + sloDescr.getSpEntityID() + " FAILED. NO LogOut response received."); sloContainer.putFailedOA(sloDescr.getSpEntityID()); } else { samlVerificationEngine.verifySLOResponse(sloResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); } checkStatusCode(sloContainer, sloResp); } catch (SOAPException e) { Logger.warn("Single LogOut for OA " + sloDescr.getSpEntityID() + " FAILED.", e); sloContainer.putFailedOA(sloDescr.getSpEntityID()); } catch (SecurityException | InvalidProtocolRequestException e) { Logger.warn("Single LogOut for OA " + sloDescr.getSpEntityID() + " FAILED.", e); sloContainer.putFailedOA(sloDescr.getSpEntityID()); } } IRequest pendingReq = null; PVPSProfilePendingRequest pvpReq = null; //start service provider front channel logout process try { if (sloContainer.hasFrontChannelOA()) { String relayState = Random.nextRandom(); Collection> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); List sloReqList = new ArrayList(); for (Entry el : sloDescr) { Logger.trace("Build frontChannel SLO Request for " + el.getValue().getSpEntityID()); LogoutRequest sloReq = buildSLORequestMessage(el.getValue()); try { sloReqList.add(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()); } } //put SLO process-information into transaction storage AssertionStore rawContainer = new AssertionStore(); rawContainer.setArtifact(relayState); rawContainer.setDatatime(new Date()); rawContainer.setAssertion(SerializationUtils.serialize(sloContainer)); rawContainer.setType(sloContainer.getClass().getName()); transactionStorage.putRaw(relayState, rawContainer); if (MiscUtil.isEmpty(authUrl)) authUrl = sloContainer.getSloRequest().getAuthURL(); String timeOutURL = authUrl + "/idpSingleLogout" + "?restart=" + relayState; DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authUrl, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); config.putCustomParameterWithOutEscaption(null, "redirectURLs", sloReqList); config.putCustomParameterWithOutEscaption(null, "timeoutURL", timeOutURL); config.putCustomParameter(null, "timeout", String.valueOf(SLOTIMEOUT)); guiBuilder.build(httpReq, httpResp, config, "Single-LogOut GUI"); } else { pendingReq = sloContainer.getSloRequest(); if (pendingReq != null && pendingReq instanceof PVPSProfilePendingRequest) { //send SLO response to SLO request issuer pvpReq = (PVPSProfilePendingRequest)pendingReq; SingleLogoutService sloService = getResponseSLODescriptor(pvpReq); LogoutResponse message = buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, pvpReq.getRequest().getRelayState(), pvpReq); } else { //print SLO information directly DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authUrl, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); if (sloContainer.getSloFailedOAs() == null || sloContainer.getSloFailedOAs().size() == 0) { revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), MOAIDEventConstants.AUTHPROCESS_SLO_ALL_VALID); config.putCustomParameter(null, "successMsg", MOAIDMessageProvider.getInstance().getMessage("slo.00", null)); } else { revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), MOAIDEventConstants.AUTHPROCESS_SLO_NOT_ALL_VALID); config.putCustomParameterWithOutEscaption(null, "errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); } guiBuilder.build(httpReq, httpResp, config, "Single-LogOut GUI"); } } } catch (GUIBuildException e) { Logger.warn("Can not build GUI:'Single-LogOut'. Msg:" + e.getMessage()); throw new MOAIDException("builder.09", new Object[]{e.getMessage()}, e); } catch (MOADatabaseException e) { Logger.error("MOA AssertionDatabase ERROR", e); if (pvpReq != null) { SingleLogoutService sloService = getResponseSLODescriptor(pvpReq); LogoutResponse message = buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, pvpReq.getRequest().getRelayState(), pvpReq); revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), MOAIDEventConstants.AUTHPROCESS_SLO_NOT_ALL_VALID); }else { //print SLO information directly DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authUrl, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); revisionsLogger.logEvent(sloContainer.getSessionID(), sloContainer.getTransactionID(), MOAIDEventConstants.AUTHPROCESS_SLO_NOT_ALL_VALID); config.putCustomParameterWithOutEscaption(null, "errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); try { guiBuilder.build(httpReq, httpResp, config, "Single-LogOut GUI"); } catch (GUIBuildException e1) { Logger.warn("Can not build GUI:'Single-LogOut'. Msg:" + e.getMessage()); throw new MOAIDException("builder.09", new Object[]{e.getMessage()}, e); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void checkStatusCode(ISLOInformationContainer 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 * @throws CredentialsNotAvailableException */ public String getFrontChannelSLOMessageURL(String serviceURL, String bindingType, RequestAbstractType sloReq, HttpServletRequest httpReq, HttpServletResponse httpResp, String relayState) throws MOAIDException, CredentialsNotAvailableException { try { X509Credential credentials = credentialProvider .getIDPAssertionSigningCredential(); Logger.debug("create SAML RedirectBinding response"); StringRedirectDeflateEncoder encoder = new StringRedirectDeflateEncoder(); BasicSAMLMessageContext context = new BasicSAMLMessageContext(); 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 String getFrontChannelSLOMessageURL(SingleLogoutService service, StatusResponseType sloResp, HttpServletRequest httpReq, HttpServletResponse httpResp, String relayState) throws MOAIDException, CredentialsNotAvailableException { try { X509Credential credentials = credentialProvider .getIDPAssertionSigningCredential(); Logger.debug("create SAML RedirectBinding response"); StringRedirectDeflateEncoder encoder = new StringRedirectDeflateEncoder(); BasicSAMLMessageContext context = new BasicSAMLMessageContext(); 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 void sendFrontChannelSLOMessage(SingleLogoutService consumerService, LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp, String relayState, PVPSProfilePendingRequest pvpReq) throws MOAIDException, PVP2Exception, CredentialsNotAvailableException { IEncoder binding = null; if (consumerService.getBinding().equals( SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); } else if (consumerService.getBinding().equals( SAMLConstants.SAML2_POST_BINDING_URI)) { binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); } if (binding == null) { throw new BindingNotSupportedException(consumerService.getBinding()); } try { binding.encodeRespone(req, resp, sloResp, consumerService.getLocation(), relayState, credentialProvider.getIDPAssertionSigningCredential(), pvpReq); } 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 LogoutRequest buildSLORequestMessage(SLOInformationInterface sloDescr) throws EAAFException { 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[]{}); } DateTime now = new DateTime(); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); issuer.setValue(pvpBasicConfiguration.getIDPEntityId(sloDescr.getAuthURL())); issuer.setFormat(NameID.ENTITY); sloReq.setIssuer(issuer); sloReq.setIssueInstant(now); sloReq.setNotOnOrAfter(now.plusMinutes(5)); sloReq.setDestination(sloDescr.getServiceURL()); NameID nameID = SAML2Utils.createSAMLObject(NameID.class); nameID.setFormat(sloDescr.getUserNameIDFormat()); nameID.setValue(sloDescr.getUserNameIdentifier()); sloReq.setNameID(nameID ); //sign message try { X509Credential idpSigningCredential = credentialProvider.getIDPAssertionSigningCredential(); Signature signer = SAML2Utils.createSAMLObject(Signature.class); signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); signer.setSigningCredential(idpSigningCredential); sloReq.setSignature(signer); DocumentBuilder builder; DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); Marshaller out = Configuration.getMarshallerFactory() .getMarshaller(sloReq); out.marshall(sloReq, document); Signer.signObject(signer); } catch (Exception e) { Logger.error("Single LogOut request signing FAILED!", e); throw new MOAIDException("pvp2.19", null); } return sloReq; } public LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPSProfilePendingRequest spRequest, String firstLevelStatusCode) throws EAAFException { LogoutResponse sloResp = buildBasicResponse(sloService, spRequest); Status status = SAML2Utils.createSAMLObject(Status.class); StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); statusCode.setValue(firstLevelStatusCode); statusMessage.setMessage(MOAIDMessageProvider.getInstance().getMessage("pvp2.18", null)); StatusCode secondLevelCode = SAML2Utils.createSAMLObject(StatusCode.class); secondLevelCode.setValue(StatusCode.PARTIAL_LOGOUT_URI); statusCode.setStatusCode(secondLevelCode); status.setStatusCode(statusCode); status.setStatusMessage(statusMessage); sloResp.setStatus(status); return sloResp; } public LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPSProfilePendingRequest spRequest, List failedOAs) throws EAAFException { LogoutResponse sloResp = buildBasicResponse(sloService, spRequest); 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.SUCCESS_URI); statusMessage.setMessage(MOAIDMessageProvider.getInstance().getMessage("pvp2.18", null)); StatusCode secondLevelCode = SAML2Utils.createSAMLObject(StatusCode.class); secondLevelCode.setValue(StatusCode.PARTIAL_LOGOUT_URI); statusCode.setStatusCode(secondLevelCode); status.setStatusCode(statusCode); status.setStatusMessage(statusMessage); } sloResp.setStatus(status); return sloResp; } private LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPSProfilePendingRequest spRequest) throws EAAFException { LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); issuer.setValue(pvpBasicConfiguration.getIDPEntityId(spRequest.getAuthURLWithOutSlash())); 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 PVPSProfileRequest && ((PVPSProfileRequest)spRequest.getRequest()).getSamlRequest() instanceof LogoutRequest) { LogoutRequest sloReq = (LogoutRequest) ((PVPSProfileRequest)spRequest.getRequest()).getSamlRequest(); sloResp.setInResponseTo(sloReq.getID()); } return sloResp; } public SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException { try { EntityDescriptor entity = metadataProvider.getEntityDescriptor(entityID); SSODescriptor 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 valid SLO ServiceDescriptor in Metadata"); throw new NOSLOServiceDescriptorException("NO valid SLO ServiceDescriptor", null); } return sloService; } catch (MetadataProviderException e) { Logger.error("Found no SLO ServiceDescriptor in Metadata"); throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); } } public SingleLogoutService getResponseSLODescriptor(PVPSProfilePendingRequest spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException { PVPSProfileRequest moaReq = (PVPSProfileRequest) spRequest.getRequest(); EntityDescriptor metadata = moaReq.getEntityMetadata(metadataProvider); SSODescriptor ssodesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); if (ssodesc == null) { Logger.debug("No PVP SPSSO descriptor found --> search IDPSSO descriptor"); ssodesc = metadata.getIDPSSODescriptor(SAMLConstants.SAML20P_NS); } if (ssodesc == null) { Logger.error("Found no SLO ServiceDescriptor in Metadata"); throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); } SingleLogoutService sloService = null; for (SingleLogoutService el : ssodesc.getSingleLogoutServices()) { if (el.getBinding().equals(spRequest.getBinding())) sloService = el; } if (sloService == null) { if (ssodesc.getSingleLogoutServices().size() != 0) sloService = ssodesc.getSingleLogoutServices().get(0); else { Logger.error("Found no SLO ServiceDescriptor in Metadata"); throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); } } return sloService; } public void parseActiveOAs(SLOInformationContainer container, List dbOAs, String removeOAID) { if (container.getActiveBackChannelOAs() == null) container.setActiveBackChannelOAs(new LinkedHashMap()); if (container.getActiveFrontChannalOAs() == null) container.setActiveFrontChannalOAs(new LinkedHashMap()); if (dbOAs != null) { for (OASessionStore oa : dbOAs) { if (!oa.getOaurlprefix().equals(removeOAID)) { //Actually only PVP 2.1 support Single LogOut if (PVP2XProtocol.NAME.equals(oa.getProtocolType())) { SingleLogoutService sloDesc; try { sloDesc = getRequestSLODescriptor(oa.getOaurlprefix()); if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) container.getActiveBackChannelOAs().put(oa.getOaurlprefix(), new SLOInformationImpl( oa.getAuthURL(), oa.getOaurlprefix(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), oa.getProtocolType(), sloDesc.getBinding(), sloDesc.getLocation())); else container.getActiveFrontChannalOAs().put(oa.getOaurlprefix(), new SLOInformationImpl( oa.getAuthURL(), oa.getOaurlprefix(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), oa.getProtocolType(), sloDesc.getBinding(), sloDesc.getLocation())); } catch (NOSLOServiceDescriptorException e) { container.putFailedOA(oa.getOaurlprefix()); } } else container.putFailedOA(oa.getOaurlprefix()); } } } } /** * @param dbIDPs * @param value */ public void parseActiveIDPs(SLOInformationContainer container, List dbIDPs, String removeIDP) { if (container.getActiveBackChannelOAs() == null) container.setActiveBackChannelOAs(new LinkedHashMap()); if (container.getActiveFrontChannalOAs() == null) container.setActiveFrontChannalOAs(new LinkedHashMap()); if (dbIDPs != null) { for (InterfederationSessionStore el : dbIDPs) { if (!el.getIdpurlprefix().equals(removeIDP)) { SingleLogoutService sloDesc; try { sloDesc = getRequestSLODescriptor(el.getIdpurlprefix()); container.getActiveFrontChannalOAs().put(el.getIdpurlprefix(), new SLOInformationImpl( el.getAuthURL(), el.getIdpurlprefix(), el.getSessionIndex(), el.getUserNameID(), NameID.TRANSIENT, PVP2XProtocol.NAME, sloDesc.getBinding(), sloDesc.getLocation())); } catch (NOSLOServiceDescriptorException e) { container.putFailedOA(el.getIdpurlprefix()); } } } } } }