public LogoutResponseFactoryTests()
 {
     _logoutResponseFactory = new LogoutResponseFactory();
 }
        /// <summary>
        /// SAML2 Logout.
        ///
        /// The SAML2 logout is complicated as there are two main scenarios.
        ///
        /// Scenario 1.
        ///
        /// It's this application that triggers the logout.
        /// The application sends the LogoutRequest to the server
        /// and the server is supposed to answer with the LogoutResponse,
        /// sent to this endpoint (assuming the /account/logout is
        /// registered as the logout endpoint in the IdP).
        ///
        /// In this app the LogoutRequest sending is handled in the HomeController
        /// (home/logout)
        ///
        /// Scenario 2.
        ///
        /// Another application triggers the logout. The server
        /// gets the LogoutRequest from this another app and
        /// sends LogoutRequest here. This app is supposed to
        /// answer with the LogoutResponse.
        ///
        /// Both scenarios means that to handle logouts correctly,
        /// the app has to be able to both send and receive
        /// both LogoutRequest and LogoutResponse
        /// </summary>
        public ActionResult Logout()
        {
            var sam2           = new Saml2AuthenticationModule();
            var idpCertificate = new ClientCertificateProvider().GetIdPCertificate();

            if (sam2.IsLogoutRequest(this.Request) ||
                sam2.IsLogoutResponse(this.Request)
                )
            {
                // first check if this is a LogoutResponse from the IdP
                var logoutResponse = new LogoutResponseFactory().From(this.Request);
                if (logoutResponse != null)
                {
                    var result = sam2.MessageSigner.Validate(logoutResponse, idpCertificate);
                    if (!result)
                    {
                        throw new ValidationException("The LogoutResponse is not correctly signed with the IdP certificate");
                    }
                }

                // then check if this is a LogoutRequest from the IdP
                var logoutRequest = new LogoutRequestFactory().From(this.Request);
                if (logoutRequest != null)
                {
                    var result = sam2.MessageSigner.Validate(logoutRequest, idpCertificate);
                    if (!result)
                    {
                        throw new ValidationException("The LogoutResponse is not correctly signed with the IdP certificate");
                    }
                }

                // both possibilities were validated
                // signout can be performed
                FormsAuthentication.SignOut();

                // create the response in case of the LogoutRequest
                if (logoutRequest != null)
                {
                    var assertionIssuer  = ConfigurationManager.AppSettings["AssertionIssuer"];
                    var identityProvider = ConfigurationManager.AppSettings["IdentityProvider"];

                    var x509Configuration = new X509Configuration()
                    {
                        SignatureCertificate = new ClientCertificateProvider().GetClientCertificate(),
                        IncludeKeyInfo       = true,
                        SignatureAlgorithm   = Signature.SignatureAlgorithm.SHA256
                    };

                    var requestBinding = Binding.POST;

                    var logoutResponseFactory = new LogoutResponseFactory();

                    logoutResponseFactory.Issuer      = assertionIssuer;
                    logoutResponseFactory.Destination = identityProvider;

                    logoutResponseFactory.RequestBinding    = requestBinding;
                    logoutResponseFactory.X509Configuration = x509Configuration;

                    // mark the response
                    logoutResponseFactory.InResponseTo = logoutRequest.SessionIndex;

                    switch (logoutResponseFactory.RequestBinding)
                    {
                    case Constants.Binding.POST:
                        return(Content(logoutResponseFactory.CreatePostBindingContent()));

                    default:
                        throw new ArgumentException(string.Format("The {0} logout response binding is not supported", logoutResponseFactory.RequestBinding));
                    }
                }
            }

            // go back to the main page (possibly with logout
            return(Redirect(FormsAuthentication.DefaultUrl));
        }
Example #3
0
 public IdpInitiatedLogoutResponseHandler(LogoutResponseFactory messageFactory, IEnumerable <ISamlBindingStrategy> bindings) : base(messageFactory, bindings)
 {
 }