package org.atricore.idbus.capabilities.sso.main.idp.producers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.atricore.idbus.capabilities.sso.main.SSOException;
import org.atricore.idbus.capabilities.sso.main.common.producers.SSOProducer;
import org.atricore.idbus.capabilities.sso.main.idp.IdPSecurityContext;
import org.atricore.idbus.capabilities.sso.main.idp.SSOIDPMediator;
import org.atricore.idbus.capabilities.sso.support.binding.SSOBinding;
import org.atricore.idbus.capabilities.sso.support.metadata.SSOService;
import org.atricore.idbus.common.sso._1_0.protocol.IDPInitiatedLogoutRequestType;
import org.atricore.idbus.common.sso._1_0.protocol.SSORequestAbstractType;
import org.atricore.idbus.common.sso._1_0.protocol.SSOResponseType;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptorImpl;
import org.atricore.idbus.kernel.main.mediation.*;
import org.atricore.idbus.kernel.main.mediation.camel.AbstractCamelEndpoint;
import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationExchange;
import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationMessage;
import org.atricore.idbus.kernel.main.mediation.channel.SPChannel;
import org.atricore.idbus.kernel.main.mediation.endpoint.IdentityMediationEndpoint;
import org.atricore.idbus.kernel.main.mediation.provider.IdentityProvider;
import org.atricore.idbus.kernel.main.util.UUIDGenerator;
/**
*
*/
public class IdPInitiatedSingleLogoutProducer extends SSOProducer {
private UUIDGenerator uuidGenerator = new UUIDGenerator();
private static Log logger = LogFactory.getLog(IdPInitiatedSingleLogoutProducer.class);
public IdPInitiatedSingleLogoutProducer(AbstractCamelEndpoint<CamelMediationExchange> endpoint) {
super(endpoint);
}
@Override
protected void doProcess(CamelMediationExchange exchange) throws Exception {
if (logger.isDebugEnabled())
logger.debug("Processing IDP Initiated Single SingOn on " + endpoint.getBinding());
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
doProcessIdPInitiatedSLO(exchange);
}
protected void doProcessIdPInitiatedSLO(CamelMediationExchange exchange) throws IdentityMediationException {
try {
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
MediationState mediationState = in.getMessage().getState();
String varName = getProvider().getName().toUpperCase() + "_SECURITY_CTX";
IdPSecurityContext secCtx = (IdPSecurityContext) mediationState.getLocalVariable(varName);
if (secCtx != null && secCtx.getSessionIndex() != null) {
IdentityProvider idp = (IdentityProvider) ((SPChannel)channel).getFederatedProvider();
triggerIdPInitiatedSLO(idp, secCtx);
}
// We'll send the user to the dashboard URL
String destinationLocation = ((SSOIDPMediator) channel.getIdentityMediator()).getDashboardUrl();
EndpointDescriptor destination =
new EndpointDescriptorImpl("EmbeddedSPAcs",
"SingleLogoutService",
SSOBinding.SSO_REDIRECT.getValue(),
destinationLocation, null);
if (logger.isDebugEnabled())
logger.debug("Sending IdP-init SLO Response to " + destination);
CamelMediationMessage out = (CamelMediationMessage) exchange.getOut();
out.setMessage(new MediationMessageImpl(uuidGenerator.generateId(),
null, "IdPLogoutResponse", null, destination, in.getMessage().getState()));
exchange.setOut(out);
} catch (Exception e) {
throw new IdentityMediationException(e.getMessage(), e);
}
}
protected void triggerIdPInitiatedSLO(IdentityProvider identityProvider, IdPSecurityContext secCtx) throws SSOException, IdentityMediationException {
if (logger.isTraceEnabled())
logger.trace("Triggering IDP Initiated SLO from IDP for Security Context " + secCtx);
EndpointDescriptor ed = resolveIdpInitiatedSloEndpoint(identityProvider);
if (logger.isDebugEnabled())
logger.debug("Using IDP Initiated SLO endpoint " + ed);
IDPInitiatedLogoutRequestType sloRequest = new IDPInitiatedLogoutRequestType();
sloRequest.setID(uuidGenerator.generateId());
sloRequest.setSsoSessionId(secCtx.getSessionIndex());
if (logger.isTraceEnabled())
logger.trace("Sending SLO Request " + sloRequest.getID() +
" to IDP " + identityProvider.getName() +
" using endpoint " + ed.getLocation());
IdentityMediator mediator = identityProvider.getChannel().getIdentityMediator();
// Response from SP
SSOResponseType sloResponse =
(SSOResponseType) mediator.sendMessage(sloRequest, ed, identityProvider.getChannel());
if (logger.isTraceEnabled())
logger.trace("Recevied SLO Response " + sloResponse.getID() +
" from IDP " + identityProvider.getName() +
" using endpoint " + ed.getLocation());
}
protected EndpointDescriptor resolveIdpInitiatedSloEndpoint(IdentityProvider idp) throws SSOException {
// User default channel to signal SLO
Channel defaultChannel = idp.getChannel();
IdentityMediationEndpoint e = null;
for (IdentityMediationEndpoint endpoint : defaultChannel.getEndpoints()) {
if (endpoint.getType().equals(SSOService.SingleLogoutService.toString())) {
if (endpoint.getBinding().equals(SSOBinding.SSO_LOCAL.getValue())) {
// We need to build an endpoint descriptor descriptor now ...
String location = endpoint.getLocation().startsWith("/") ?
defaultChannel.getLocation() + endpoint.getLocation() :
endpoint.getLocation();
return new EndpointDescriptorImpl(idp.getName() + "-sso-slo-local",
SSOService.SingleLogoutService.toString(),
SSOBinding.SSO_LOCAL.toString(),
location,
null);
} else if (endpoint.getBinding().equals(SSOBinding.SSO_SOAP.getValue())) {
e = endpoint;
}
}
}
if (e != null) {
String location = e.getLocation().startsWith("/") ?
defaultChannel.getLocation() + e.getLocation() :
e.getLocation();
return new EndpointDescriptorImpl(idp.getName() + "-sso-slo-soap",
SSOService.SingleLogoutService.toString(),
e.getBinding(),
location,
null);
}
throw new SSOException("No IDP SLO endpoint using LOCAL/SOAP binding found!");
}
}