Esempio n. 1
0
        private void ValidateLogoutViaPost(System.Collections.Specialized.NameValueCollection requestParams, out string message, out LogoutResponse response)
        {
            var parser = new HttpPostBindingParser(requestParams);

            logger.DebugFormat(TraceMessages.LogoutResponsePostBindingParse, parser.Message);

            response = Serialization.DeserializeFromXmlString <LogoutResponse>(parser.Message);

            var idp = IdpSelectionUtil.RetrieveIDPConfiguration(response.Issuer.Value, config);

            if (idp.Metadata == null)
            {
                logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id);
                throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id));
            }

            if (!parser.IsSigned)
            {
                logger.Error(ErrorMessages.ResponseSignatureMissing);
                throw new Saml20Exception(ErrorMessages.ResponseSignatureMissing);
            }

            // signature on final message in logout
            if (!parser.CheckSignature(idp.Metadata.Keys))
            {
                logger.Error(ErrorMessages.ResponseSignatureInvalid);
                throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid);
            }

            message = parser.Message;
        }
Esempio n. 2
0
        private void HandleRequest(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleRequest()");

            //Fetch config object
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            LogoutRequest logoutRequest = null;
            IDPEndPoint endpoint = null;
            string message = string.Empty;

            //Build the response object
            var response = new Saml20LogoutResponse();
            response.Issuer = config.ServiceProvider.ID;
            response.StatusCode = Saml20Constants.StatusCodes.Success; // Default success. Is overwritten if something fails.
            
            if(context.Request.RequestType == "GET") // HTTP Redirect binding
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      string.Format("Binding: redirect, Signature algorithm: {0}  Signature:  {1}, Message: {2}", parser.SignatureAlgorithm, parser.Signature, parser.Message));

                if (!parser.IsSigned)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint = config.FindEndPoint(logoutRequest.Issuer.Value);

                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP: " + logoutRequest.Issuer.Value);
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature redirect-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST") // HTTP Post binding
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      "Binding: POST, Message: " + parser.Message);

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint = config.FindEndPoint(logoutRequest.Issuer.Value);
                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP");
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                // handle a logout-request
                if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature post-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }else
            {
                //Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS
                // Not able to return a response as we do not understand the request.
                HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType));
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, message);
            
            // Check that idp in session and request matches.
            string idpRequest = logoutRequest.Issuer.Value;
            if (!context.Session.IsNewSession)
            {
                object idpSession = context.Session[IDPLoginSessionKey];
            
                if (idpSession != null && idpSession.ToString() != idpRequest)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, Resources.IdPMismatchBetweenRequestAndSessionFormat(idpSession, idpRequest), message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }
            }
            else
            {
                // All other status codes than Success results in the IdP throwing an error page. Therefore we return default Success even if we do not have a session.
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Session does not exist. Continues the redirect logout procedure with status code success." + idpRequest, message);
            }

            //  Only logout if request is valid and we are working on an existing Session.
            if (Saml20Constants.StatusCodes.Success == response.StatusCode && !context.Session.IsNewSession)
            {
                // Execute all actions that the service provider has configured
                DoLogout(context, true);
            }

            // Update the response object with informations that first is available when request has been parsed.
            IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());
            response.Destination = destination.Url;
            response.InResponseTo = logoutRequest.ID;

            //Respond using redirect binding
            if(destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.RelayState = context.Request.Params["RelayState"];
                builder.Response = response.GetXml().OuterXml;
                builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                string s = destination.Url + "?" + builder.ToQuery();
                context.Response.Redirect(s, true);
                return;
            }

            //Respond using post binding
            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                builder.Action = SAMLAction.SAMLResponse;                                
                XmlDocument responseDocument = response.GetXml();
                XmlSignatureUtils.SignDocument(responseDocument, response.ID);
                builder.Response = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                builder.GetPage().ProcessRequest(context);
                return;
            }
        }
Esempio n. 3
0
        private void HandleResponse(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleResponse()");


            string message = string.Empty;

            if(context.Request.RequestType == "GET")
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                LogoutResponse response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message);

                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Binding: redirect, Signature algorithm: {0}  Signature:  {1}, Message: {2}", parser.SignatureAlgorithm, parser.Signature, parser.Message));

                IDPEndPoint idp = RetrieveIDPConfiguration(response.Issuer.Value);
                
                AuditLogging.IdpId = idp.Id;
                AuditLogging.AssertionId = response.ID;
                
                if (idp.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("No IDP metadata, unknown IDP, response: {0}", parser.Message));
                    HandleError(context, Resources.UnknownIDP);
                    return;
                }

                if (!parser.VerifySignature(idp.metadata.Keys))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Invalid signature in redirect-binding, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureInvalid);
                    return;
                }

                message = parser.Message;
            }else if(context.Request.RequestType == "POST")
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      "Binding: POST, Message: " + parser.Message);


                LogoutResponse response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message);

                IDPEndPoint idp = RetrieveIDPConfiguration(response.Issuer.Value);

                if (idp.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("No IDP metadata, unknown IDP, response: {0}", parser.Message));
                    HandleError(context, Resources.UnknownIDP);
                    return;
                }

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Signature not present, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureNotPresent);
                }

                // signature on final message in logout
                if (!parser.CheckSignature(idp.metadata.Keys))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Invalid signature in post-binding, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureInvalid);
                }

                message = parser.Message;
            }else
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Unsupported request type format, type: {0}", context.Request.RequestType));
                HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType));
            }

            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.LoadXml(message);

            XmlElement statElem =
                (XmlElement)doc.GetElementsByTagName(Status.ELEMENT_NAME, Saml20Constants.PROTOCOL)[0];

            Status status = Serialization.DeserializeFromXmlString<Status>(statElem.OuterXml);

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Unexpected status code: {0}, msg: {1}", status.StatusCode.Value, message));
                HandleError(context, status);
                return;
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                     "Assertion validated succesfully");

            //Log the user out locally
            DoLogout(context);
        }
Esempio n. 4
0
        /// <summary>
        /// Handles the request.
        /// </summary>
        /// <param name="context">The context.</param>
        private void HandleRequest(HttpContext context)
        {
            Logger.DebugFormat(TraceMessages.LogoutRequestReceived);

            // Fetch the endpoint configuration
            var idp         = IdpSelectionUtil.RetrieveIDPConfiguration((string)context.Session[IdpLoginSessionKey], ConfigurationFactory.Instance.Configuration);
            var destination = IdpSelectionUtil.DetermineEndpointConfiguration(BindingType.Redirect, idp.Endpoints.DefaultLogoutEndpoint, idp.Metadata.IDPSLOEndpoints);

            // Fetch config object
            var config = ConfigurationFactory.Instance.Configuration;

            // Build the response object
            var response = new Saml20LogoutResponse
            {
                Issuer      = config.ServiceProvider.Id,
                Destination = destination.Url,
                StatusCode  = Saml20Constants.StatusCodes.Success
            };

            string message;

            if (context.Request.RequestType == "GET")
            {
                // HTTP Redirect binding
                var parser = new HttpRedirectBindingParser(context.Request.Url);
                Logger.DebugFormat(TraceMessages.LogoutRequestRedirectBindingParse, parser.Message, parser.SignatureAlgorithm, parser.Signature);

                var endpoint = config.IdentityProviders.FirstOrDefault(x => x.Id == idp.Id);
                if (endpoint == null || endpoint.Metadata == null)
                {
                    Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id);
                    throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id));
                }

                var metadata = endpoint.Metadata;
                if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.Signing)))
                {
                    Logger.Error(ErrorMessages.RequestSignatureInvalid);
                    throw new Saml20Exception(ErrorMessages.RequestSignatureInvalid);
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST")
            {
                // HTTP Post binding
                var parser = new HttpPostBindingParser(context.Request.Params);
                Logger.DebugFormat(TraceMessages.LogoutRequestPostBindingParse, parser.Message);

                if (!parser.IsSigned)
                {
                    Logger.Error(ErrorMessages.RequestSignatureMissing);
                    throw new Saml20Exception(ErrorMessages.RequestSignatureMissing);
                }

                var endpoint = config.IdentityProviders.FirstOrDefault(x => x.Id == idp.Id);
                if (endpoint == null || endpoint.Metadata == null)
                {
                    Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id);
                    throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id));
                }

                var metadata = endpoint.Metadata;

                // Check signature
                if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.Signing)))
                {
                    Logger.Error(ErrorMessages.RequestSignatureInvalid);
                    throw new Saml20Exception(ErrorMessages.RequestSignatureInvalid);
                }

                message = parser.Message;
            }
            else
            {
                // Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS
                Logger.ErrorFormat(ErrorMessages.UnsupportedRequestType, context.Request.RequestType);
                throw new Saml20Exception(string.Format(ErrorMessages.UnsupportedRequestType, context.Request.RequestType));
            }

            Logger.DebugFormat(TraceMessages.LogoutRequestParsed, message);

            // Log the user out locally
            DoLogout(context, true);

            var req = Serialization.DeserializeFromXmlString <LogoutRequest>(message);

            response.InResponseTo = req.Id;

            // Respond using redirect binding
            if (destination.Binding == BindingType.Redirect)
            {
                var builder = new HttpRedirectBindingBuilder
                {
                    RelayState = context.Request.Params["RelayState"],
                    Response   = response.GetXml().OuterXml,
                    SigningKey = config.ServiceProvider.SigningCertificate.PrivateKey
                };

                Logger.DebugFormat(TraceMessages.LogoutResponseSent, builder.Response);

                context.Response.Redirect(destination.Url + "?" + builder.ToQuery(), true);
                return;
            }

            // Respond using post binding
            if (destination.Binding == BindingType.Post)
            {
                var builder = new HttpPostBindingBuilder(destination)
                {
                    Action = SamlActionType.SAMLResponse
                };

                var responseDocument = response.GetXml();

                Logger.DebugFormat(TraceMessages.LogoutResponseSent, responseDocument.OuterXml);

                XmlSignatureUtils.SignDocument(responseDocument, response.Id, config);
                builder.Response   = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                context.Response.Write(builder.GetPage());
            }
        }
        private void HandleRequest(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleRequest()");

            //Fetch the endpoint configuration
            IDPEndPoint idpEndpoint = RetrieveIDPConfiguration(context.Session[IDPLoginSessionKey].ToString());

            IDPEndPointElement destination =
                DetermineEndpointConfiguration(SAMLBinding.REDIRECT, idpEndpoint.SLOEndpoint, idpEndpoint.metadata.SLOEndpoints());

            //Fetch config object
            SAML20FederationConfig config = ConfigurationReader.GetConfig <SAML20FederationConfig>();

            //Build the response object
            Saml20LogoutResponse response = new Saml20LogoutResponse();

            response.Issuer      = config.ServiceProvider.ID;
            response.Destination = destination.Url;
            response.StatusCode  = Saml20Constants.StatusCodes.Success;

            string message = string.Empty;

            if (context.Request.RequestType == "GET") // HTTP Redirect binding
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                IDPEndPoint endpoint             = config.FindEndPoint(idpEndpoint.Id);

                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP");
                    HandleError(context, "Cannot find metadata for IdP " + idpEndpoint.Id);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Invalid signature redirect-binding, msg: " + parser.Message);
                    HandleError(context, Resources.SignatureInvalid);
                    return;
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST") // HTTP Post binding
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    HandleError(context, Resources.SignatureNotPresent);
                }

                IDPEndPoint endpoint = config.FindEndPoint(idpEndpoint.Id);
                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP");
                    HandleError(context, "Cannot find metadata for IdP " + idpEndpoint.Id);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                // handle a logout-request
                if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Invalid signature post-binding, msg: " + parser.Message);
                    HandleError(context, Resources.SignatureInvalid);
                }

                message = parser.Message;
            }
            else
            {
                //Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS
                HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType));
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, message);

            //Log the user out locally
            DoLogout(context, true);

            LogoutRequest req = Serialization.DeserializeFromXmlString <LogoutRequest>(message);

            response.InResponseTo = req.ID;

            //Respond using redirect binding
            if (destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.RelayState = context.Request.Params["RelayState"];
                builder.Response   = response.GetXml().OuterXml;
                builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                string s = destination.Url + "?" + builder.ToQuery();
                context.Response.Redirect(s, true);
                return;
            }

            //Respond using post binding
            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                builder.Action = SAMLAction.SAMLResponse;
                XmlDocument responseDocument = response.GetXml();
                XmlSignatureUtils.SignDocument(responseDocument, response.ID);
                builder.Response   = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                builder.GetPage().ProcessRequest(context);
                return;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Handles the response.
        /// </summary>
        /// <param name="context">The context.</param>
        private void HandleResponse(HttpContext context)
        {
            Logger.DebugFormat(TraceMessages.LogoutResponseReceived);

            var            message  = string.Empty;
            LogoutResponse response = null;

            if (context.Request.RequestType == "GET")
            {
                var parser = new HttpRedirectBindingParser(context.Request.Url);
                response = Serialization.DeserializeFromXmlString <LogoutResponse>(parser.Message);

                Logger.DebugFormat(TraceMessages.LogoutResponseRedirectBindingParse, parser.Message, parser.SignatureAlgorithm, parser.Signature);

                var idp = RetrieveIDPConfiguration(response.Issuer.Value);
                if (idp.Metadata == null)
                {
                    Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id);
                    throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id));
                }

                if (!parser.VerifySignature(idp.Metadata.Keys))
                {
                    Logger.Error(ErrorMessages.ResponseSignatureInvalid);
                    throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid);
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST")
            {
                var parser = new HttpPostBindingParser(context);
                Logger.DebugFormat(TraceMessages.LogoutResponsePostBindingParse, parser.Message);

                response = Serialization.DeserializeFromXmlString <LogoutResponse>(parser.Message);

                var idp = RetrieveIDPConfiguration(response.Issuer.Value);
                if (idp.Metadata == null)
                {
                    Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id);
                    throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id));
                }

                if (!parser.IsSigned)
                {
                    Logger.Error(ErrorMessages.ResponseSignatureMissing);
                    throw new Saml20Exception(ErrorMessages.ResponseSignatureMissing);
                }

                // signature on final message in logout
                if (!parser.CheckSignature(idp.Metadata.Keys))
                {
                    Logger.Error(ErrorMessages.ResponseSignatureInvalid);
                    throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid);
                }

                message = parser.Message;
            }

            if (response == null)
            {
                Logger.ErrorFormat(ErrorMessages.UnsupportedRequestType, context.Request.RequestType);
                throw new Saml20Exception(string.Format(ErrorMessages.UnsupportedRequestType, context.Request.RequestType));
            }

            Logger.DebugFormat(TraceMessages.LogoutResponseParsed, message);

            if (response.Status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Logger.ErrorFormat(ErrorMessages.ResponseStatusNotSuccessful, response.Status.StatusCode.Value);
                throw new Saml20Exception(string.Format(ErrorMessages.ResponseStatusNotSuccessful, response.Status.StatusCode.Value));
            }

            // Log the user out locally
            DoLogout(context);
        }
        private void HandleRequest(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleRequest()");

            //Fetch config object
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            LogoutRequest logoutRequest = null;
            IDPEndPoint   endpoint      = null;
            string        message       = string.Empty;

            //Build the response object
            var response = new Saml20LogoutResponse();

            response.Issuer     = config.ServiceProvider.ID;
            response.StatusCode = Saml20Constants.StatusCodes.Success; // Default success. Is overwritten if something fails.

            if (context.Request.RequestType == "GET")                  // HTTP Redirect binding
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      string.Format("Binding: redirect, Signature algorithm: {0}  Signature:  {1}, Message: {2}", parser.SignatureAlgorithm, parser.Signature, parser.Message));

                if (!parser.IsSigned)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint      = config.FindEndPoint(logoutRequest.Issuer.Value);

                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP: " + logoutRequest.Issuer.Value);
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature redirect-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST") // HTTP Post binding
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      "Binding: POST, Message: " + parser.Message);

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint      = config.FindEndPoint(logoutRequest.Issuer.Value);
                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP");
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                if (logoutRequest.NotOnOrAfter.HasValue)
                {
                    var allowedClockSkewTime = DateTime.UtcNow.AddMinutes(FederationConfig.GetConfig().AllowedClockSkewMinutes);

                    if (logoutRequest.NotOnOrAfter >= allowedClockSkewTime)
                    {
                        var errormessage =
                            $"Logout request NotOnOrAfter ({logoutRequest.NotOnOrAfter}) is after allowed time ({allowedClockSkewTime})";
                        AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, errormessage);
                        HandleError(context, errormessage);
                        return;
                    }
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                // handle a logout-request
                if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature post-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }
            else
            {
                //Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS
                // Not able to return a response as we do not understand the request.
                HandleError(context, string.Format(Resources.UnsupportedRequestType, context.Request.RequestType));
                return;
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, message);

            // Check that idp in session and request matches.
            string idpRequest = logoutRequest.Issuer.Value;

            // SessionFactory.SessionContext.Current.New is never the first call to Current due to the logic in Application_AuthenticateRequest() ... Saml20Identity.IsInitialized()
            // Hence we need to check on Saml20Identity.IsInitialized() instead of using SessionFactory.SessionContext.Current.New.
            bool isOioSamlSessionActive = Saml20Identity.IsInitialized();

            if (isOioSamlSessionActive)
            {
                object idpId = Saml20PrincipalCache.GetSaml20AssertionLite().Issuer;

                if (idpId != null && idpId.ToString() != idpRequest)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, string.Format(Resources.IdPMismatchBetweenRequestAndSession, idpId, idpRequest), message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }
            }
            else
            {
                // All other status codes than Success results in the IdP throwing an error page. Therefore we return default Success even if we do not have a session.
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Session does not exist. Continues the redirect logout procedure with status code success." + idpRequest, message);
            }

            //  Only logout if request is valid and we are working on an existing Session.
            if (Saml20Constants.StatusCodes.Success == response.StatusCode && isOioSamlSessionActive)
            {
                // Execute all actions that the service provider has configured
                DoLogout(context, true);
            }

            // Update the response object with informations that first is available when request has been parsed.
            IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());

            response.Destination  = destination.Url;
            response.InResponseTo = logoutRequest.ID;

            //Respond using redirect binding
            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endpoint.ShaHashingAlgorithm);

            if (destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.RelayState          = context.Request.Params["RelayState"];
                builder.Response            = response.GetXml().OuterXml;
                builder.signingKey          = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                builder.ShaHashingAlgorithm = shaHashingAlgorithm;
                string s = destination.Url + "?" + builder.ToQuery();
                context.Response.Redirect(s, true);
                return;
            }

            //Respond using post binding
            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                builder.Action = SAMLAction.SAMLResponse;
                XmlDocument responseDocument   = response.GetXml();
                var         signingCertificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
                var         signatureProvider  = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);
                signatureProvider.SignAssertion(responseDocument, response.ID, signingCertificate);
                builder.Response   = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                builder.GetPage().ProcessRequest(context);
                return;
            }
        }