Beispiel #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;
        }
        /// <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);
        }
        /// <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 = RetrieveIDPConfiguration(StateService.Get<string>(IdpLoginSessionKey));
            var destination = DetermineEndpointConfiguration(BindingType.Redirect, idp.Endpoints.LogoutEndpoint, idp.Metadata.IDPSLOEndpoints);

            // Fetch config object
            var config = Saml2Config.GetConfig();

            // 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);
                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 = Saml2Config.GetConfig().ServiceProvider.SigningCertificate.GetCertificate().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);
                builder.Response = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                builder.GetPage().ProcessRequest(context);
            }
        }