Beispiel #1
0
        public void Saml2LogoutRequest_FromXml()
        {
            var xmlData =
                @"<saml2p:LogoutRequest xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
 ID=""d2b7c388cec36fa7c39c28fd298644a8"" Version=""2.0"" IssueInstant=""2004-01-21T19:00:49Z""
 Destination=""http://idp.example.com/logout"">
 <saml2:Issuer>http://sp.example.com/</saml2:Issuer>
 <saml2:NameID Format=""urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"">005a06e0-ad82-110d-a556-004005b13a2b</saml2:NameID>
 <saml2p:SessionIndex>SessionId</saml2p:SessionIndex>
</saml2p:LogoutRequest>";

            var xmlDoc = XmlHelpers.XmlDocumentFromString(xmlData);

            var subject = Saml2LogoutRequest.FromXml(xmlDoc.DocumentElement);

            var expected = new Saml2LogoutRequest(new Saml2Id("d2b7c388cec36fa7c39c28fd298644a8"))
            {
                DestinationUrl = new Uri("http://idp.example.com/logout"),
                Issuer         = new EntityId("http://sp.example.com/"),
                NameId         = new Saml2NameIdentifier(
                    "005a06e0-ad82-110d-a556-004005b13a2b",
                    new Uri(NameIdFormat.Persistent.GetUri().AbsoluteUri)),
                SessionIndex = "SessionId",
            };

            subject.ShouldBeEquivalentTo(expected);
        }
Beispiel #2
0
        private async Task <IActionResult> LogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding)
        {
            var samlConfig = await saml2ConfigurationLogic.GetSamlDownConfigAsync(party);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            binding.ReadSamlRequest(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
            logger.ScopeTrace(() => $"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);

            try
            {
                ValidateLogoutRequest(party, saml2LogoutRequest);

                try
                {
                    binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
                    logger.ScopeTrace(() => "Down, SAML Logout request accepted.", triggerEvent: true);
                }
                catch (Exception ex)
                {
                    var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex);
                    if (isex != null)
                    {
                        throw isex;
                    }
                    throw;
                }

                await sequenceLogic.SaveSequenceDataAsync(new SamlDownSequenceData
                {
                    Id         = saml2LogoutRequest.Id.Value,
                    RelayState = binding.RelayState
                });

                var type = RouteBinding.ToUpParties.First().Type;
                logger.ScopeTrace(() => $"Request, Up type '{type}'.");
                switch (type)
                {
                case PartyTypes.Login:
                    return(await serviceProvider.GetService <LogoutUpLogic>().LogoutRedirect(RouteBinding.ToUpParties.First(), GetLogoutRequest(party, saml2LogoutRequest)));

                case PartyTypes.OAuth2:
                    throw new NotImplementedException();

                case PartyTypes.Oidc:
                    return(await serviceProvider.GetService <OidcRpInitiatedLogoutUpLogic <OidcUpParty, OidcUpClient> >().EndSessionRequestRedirectAsync(RouteBinding.ToUpParties.First(), GetLogoutRequest(party, saml2LogoutRequest)));

                case PartyTypes.Saml2:
                    return(await serviceProvider.GetService <SamlLogoutUpLogic>().LogoutRequestRedirectAsync(RouteBinding.ToUpParties.First(), GetSamlLogoutRequest(party, saml2LogoutRequest)));

                default:
                    throw new NotSupportedException($"Party type '{type}' not supported.");
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await LogoutResponseAsync(party, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState, ex.Status));
            }
        }
        public async Task <IActionResult> SingleLogout()
        {
            var loginType = await GetSelectedLoginType();

            Saml2StatusCodes status;
            var requestBinding = new Saml2PostBinding();
            var logoutRequest  = new Saml2LogoutRequest(saml2Config, User);

            try
            {
                requestBinding.Unbind(Request.ToGenericHttpRequest(), logoutRequest);
                status = Saml2StatusCodes.Success;
                await idPSelectionCookieRepository.DeleteAsync();

                await logoutRequest.DeleteSession(HttpContext);
            }
            catch (Exception exc)
            {
                // log exception
                Debug.WriteLine("SingleLogout error: " + exc.ToString());
                status = Saml2StatusCodes.RequestDenied;
            }

            var responsebinding = new Saml2PostBinding();

            responsebinding.RelayState = requestBinding.RelayState;
            var saml2LogoutResponse = new Saml2LogoutResponse(saml2Config)
            {
                InResponseToAsString = logoutRequest.IdAsString,
                Status = status,
            };

            saml2LogoutResponse.Destination = AddUpParty(saml2LogoutResponse.Destination, loginType);
            return(responsebinding.Bind(saml2LogoutResponse).ToActionResult());
        }
Beispiel #4
0
        public ActionResult SingleLogout()
        {
            Saml2StatusCodes status;
            var requestBinding = new Saml2PostBinding();
            var logoutRequest  = new Saml2LogoutRequest(config, ClaimsPrincipal.Current);

            try
            {
                requestBinding.Unbind(Request.ToGenericHttpRequest(), logoutRequest);
                status = Saml2StatusCodes.Success;
                logoutRequest.DeleteSession();
            }
            catch (Exception exc)
            {
                // log exception
                Debug.WriteLine("SingleLogout error: " + exc.ToString());
                status = Saml2StatusCodes.RequestDenied;
            }

            var responsebinding = new Saml2PostBinding();

            responsebinding.RelayState = requestBinding.RelayState;
            var saml2LogoutResponse = new Saml2LogoutResponse(config)
            {
                InResponseToAsString = logoutRequest.IdAsString,
                Status = status,
            };

            return(responsebinding.Bind(saml2LogoutResponse).ToActionResult());
        }
Beispiel #5
0
        public string BuildLogoutRequestUrl(Saml2LogoutRequest saml2LogoutRequest, AsymmetricAlgorithm signingKey,
                                            string hashingAlgorithm, string relayState)
        {
            var request = saml2LogoutRequest.GetXml().OuterXml;

            return(BuildRequestUrl(signingKey, hashingAlgorithm, relayState, request, saml2LogoutRequest.Destination));
        }
        public void Saml2LogoutRequest_ToXml_PreservesCustomChanges()
        {
            var subject = new Saml2LogoutRequest()
            {
                DestinationUrl = new Uri("http://idp.example.com/logout"),
                Issuer         = new EntityId("http://sp.example.com/"),
                NameId         = new Saml2NameIdentifier("005a06e0-ad82-110d-a556-004005b13a2b")
                {
                    Format          = new Uri(NameIdFormat.Persistent.GetUri().AbsoluteUri),
                    NameQualifier   = "qualifier",
                    SPNameQualifier = "spQualifier",
                    SPProvidedId    = "spId"
                },
                SessionIndex = "SessionId"
            };

            subject.XmlCreated += (s, e) =>
            {
                e.Add(new XAttribute("CustomAttribute", "CustomValue"));
            };

            var xml = subject.ToXml();

            xml.Should().Contain("CustomAttribute=\"CustomValue\"");
        }
        public Saml2LogoutRequest CreateLogoutRequest(string providerName, string logoutRequestId, string sessionIndex, string subject)
        {
            var identityProviderConfiguration = _configurationProvider.GetIdentityProviderConfiguration(providerName);
            var request = new Saml2LogoutRequest
            {
                Issuer          = ServiceProviderConfiguration.EntityId,
                Destination     = identityProviderConfiguration.SingleSignOutService,
                Reason          = Saml2Constants.Reasons.User,
                SubjectToLogOut = new NameID()
            };

            request.Request.ID = logoutRequestId;

            if (sessionIndex.IsNotNullOrEmpty())
            {
                request.SessionIndex = sessionIndex;
            }

            if (subject.IsNotNullOrEmpty())
            {
                request.SubjectToLogOut.Value = subject;
            }

            return(request);
        }
Beispiel #8
0
        public void Saml2LogoutRequest_ToXml()
        {
            var subject = new Saml2LogoutRequest()
            {
                DestinationUrl = new Uri("http://idp.example.com/logout"),
                Issuer         = new EntityId("http://sp.example.com/"),
                NameId         = new Saml2NameIdentifier(
                    "005a06e0-ad82-110d-a556-004005b13a2b",
                    new Uri(NameIdFormat.Persistent.GetString())),
                SessionIndex = "SessionId"
            };

            var actual = XElement.Parse(subject.ToXml());

            var expected = XElement.Parse(
                @"<saml2p:LogoutRequest xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
 ID=""d2b7c388cec36fa7c39c28fd298644a8"" Version=""2.0"" IssueInstant=""2004-01-21T19:00:49Z""
 Destination=""http://idp.example.com/logout"">
 <saml2:Issuer>http://sp.example.com/</saml2:Issuer>
 <saml2:NameID Format=""urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"">005a06e0-ad82-110d-a556-004005b13a2b</saml2:NameID>
 <saml2p:SessionIndex>SessionId</saml2p:SessionIndex>
</saml2p:LogoutRequest>");

            // Set generated expected values to the actual.
            expected.Attribute("ID").Value           = actual.Attribute("ID").Value;
            expected.Attribute("IssueInstant").Value = actual.Attribute("IssueInstant").Value;

            actual.Should().BeEquivalentTo(expected);
        }
Beispiel #9
0
        private async Task <IActionResult> SingleLogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding, IEnumerable <Claim> claims)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party, true);

            claims = await claimTransformationsLogic.Transform(party.ClaimTransforms?.ConvertAll(t => (ClaimTransform)t), claims);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig)
            {
                NameId       = samlClaimsDownLogic.GetNameId(claims),
                Destination  = new Uri(party.SingleLogoutUrl),
                SessionIndex = samlClaimsDownLogic.GetSessionIndex(claims)
            };

            binding.RelayState = SequenceString;
            binding.Bind(saml2LogoutRequest);
            logger.ScopeTrace($"SAML Single Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Single logged out URL '{party.SingleLogoutUrl}'.");
            logger.ScopeTrace("Down, SAML Single Logout request.", triggerEvent: true);

            securityHeaderLogic.AddFormAction(party.SingleLogoutUrl);
            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Beispiel #10
0
        public void Saml2LogoutRequest_FromXml_Nullcheck()
        {
            Action a = () => Saml2LogoutRequest.FromXml(null);

            a.ShouldThrow <ArgumentNullException>()
            .And.ParamName.Should().Be("xml");
        }
Beispiel #11
0
        private static CommandResult HandleRequest(UnbindResult unbindResult, IOptions options)
        {
            var request = Saml2LogoutRequest.FromXml(unbindResult.Data);

            var idp = options.IdentityProviders[request.Issuer];

            if (options.SPOptions.SigningServiceCertificate == null)
            {
                throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture,
                                                                     "Received a LogoutRequest from \"{0}\" but cannot reply because single logout responses must be signed and there is no signing certificate configured. Looks like the idp is configured for Single Logout despite AuthServices not exposing that functionality in the metadata.",
                                                                     request.Issuer.Id));
            }

            var response = new Saml2LogoutResponse(Saml2StatusCode.Success)
            {
                DestinationUrl     = idp.SingleLogoutServiceResponseUrl,
                SigningCertificate = options.SPOptions.SigningServiceCertificate,
                InResponseTo       = request.Id,
                Issuer             = options.SPOptions.EntityId,
                RelayState         = unbindResult.RelayState
            };

            var result = Saml2Binding.Get(idp.SingleLogoutServiceBinding).Bind(response);

            result.TerminateLocalSession = true;
            return(result);
        }
Beispiel #12
0
        private async Task CreateLogoutResponse(IOwinContext context)
        {
            var requestData = await context.ToHttpRequestData(Options.DataProtector.Unprotect);

            var binding = Saml2Binding.Get(requestData);

            if (binding == null)
            {
                context.Response.StatusCode = 400;
                return;
            }

            var unbindResult  = binding.Unbind(requestData, null);
            var logoutRequest = Saml2LogoutRequest.FromXml(unbindResult.Data);

            context.Authentication.SignOut();

            var logoutResponse = new Saml2LogoutResponse(Saml2StatusCode.Success)
            {
                DestinationUrl     = new Uri(new Uri(logoutRequest.Issuer.Id + "/"), "Logout"),
                SigningCertificate = Options.SigningCertificate,
                InResponseTo       = new Saml2Id(logoutRequest.Id.Value),
                Issuer             = new EntityId(GetAbsoluteUri(context.Request, MetadataPath).AbsoluteUri),
                RelayState         = unbindResult.RelayState
            };

            Saml2Binding.Get(Saml2BindingType.HttpRedirect)
            .Bind(logoutResponse)
            .Apply(context, Options.DataProtector);
        }
        public void LogoutCommand_Run_IncomingRequest_ThrowsOnNoConfiguredLogoutEndPointOnIdp()
        {
            var request = new Saml2LogoutRequest()
            {
                DestinationUrl     = new Uri("http://sp.example.com/path/Saml2/logout"),
                Issuer             = new EntityId("https://idp2.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert,
                SigningAlgorithm   = SecurityAlgorithms.RsaSha256Signature,
                NameId             = new Saml2NameIdentifier("NameId"),
                SessionIndex       = "SessionID"
            };

            var bindResult = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                             .Bind(request);

            var httpRequest = new HttpRequestData("GET", bindResult.Location);

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);

            CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
            .Invoking(c => c.Run(httpRequest, options))
            .Should().Throw <InvalidOperationException>()
            .WithMessage("*LogoutRequest*\"https://idp2.example.com\"*cannot reply*logout endpoint*idp*");
        }
Beispiel #14
0
        public async Task <IActionResult> SingleLogout()
        {
            var requestBinding = new Saml2PostBinding();
            var request        = new Saml2LogoutRequest(_configuration);
            Saml2StatusCodes status;

            try
            {
                requestBinding.Unbind(Request.ToGenericHttpRequest(), request);
                await request.DeleteSession(HttpContext);

                status = Saml2StatusCodes.Success;
            }
            catch (Exception)
            {
                status = Saml2StatusCodes.RequestDenied;
            }

            var responseBinding = new Saml2PostBinding();

            responseBinding.RelayState = requestBinding.RelayState;

            var response = new Saml2LogoutResponse(_configuration)
            {
                InResponseToAsString = request.IdAsString,
                Status = status
            };

            return(responseBinding.Bind(response)
                   .ToActionResult());
        }
        public ActionResult SingleLogout()
        {
            Saml2StatusCodes status;
            var requestBinding = new Saml2RedirectBinding();
            var logoutRequest  = new Saml2LogoutRequest();

            try
            {
                requestBinding.Unbind(Request, logoutRequest, CertificateUtil.Load("~/App_Data/signing-adfs.test_Certificate.crt"));
                status = Saml2StatusCodes.Success;
            }
            catch (Exception exc)
            {
                // log exception
                Debug.WriteLine("SingleLogout error: " + exc.ToString());
                status = Saml2StatusCodes.RequestDenied;
            }

            var responsebinding = new Saml2RedirectBinding();

            responsebinding.RelayState = requestBinding.RelayState;
            var saml2LogoutResponse = new Saml2LogoutResponse
            {
                InResponseTo = logoutRequest.Id,
                Status       = status,
                Issuer       = new EndpointReference("http://udv.itfoxtec.com/webapptest"),
                Destination  = new EndpointAddress("https://udv.itfoxtec.com/adfs/ls/")
            };

            saml2LogoutResponse.DeleteSession();
            return(responsebinding.Bind(saml2LogoutResponse, CertificateUtil.Load("~/App_Data/webapptest_certificate.pfx")).ToActionResult());
        }
Beispiel #16
0
        public async Task KentorAuthServicesAuthenticationMiddleware_LogoutsOnLogoutRequest()
        {
            var options = new KentorAuthServicesAuthenticationOptions(true);
            var subject = new KentorAuthServicesAuthenticationMiddleware(null, CreateAppBuilder(), options);

            var context = OwinTestHelpers.CreateOwinContext();

            var request = new Saml2LogoutRequest()
            {
                SessionIndex       = "SessionId",
                DestinationUrl     = new Uri("http://sp.example.com/AuthServices/Logout"),
                NameId             = new Saml2NameIdentifier("NameId"),
                Issuer             = new EntityId("https://idp.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert
            };

            var url = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                      .Bind(request).Location;

            context.Request.Path        = new PathString(url.AbsolutePath);
            context.Request.QueryString = new QueryString(url.Query.TrimStart('?'));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(303);
            context.Response.Headers["Location"].Should().StartWith("https://idp.example.com/logout?SAMLResponse");

            context.Authentication.AuthenticationResponseRevoke.Should().NotBeNull();
            context.Authentication.AuthenticationResponseRevoke.AuthenticationTypes
            .Should().BeEmpty();
        }
Beispiel #17
0
        private async Task <IActionResult> LogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            binding.ReadSamlRequest(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
            logger.ScopeTrace($"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");

            try
            {
                ValidateLogoutRequest(party, saml2LogoutRequest);
                binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
                logger.ScopeTrace("Down, SAML Logout request accepted.", triggerEvent: true);

                await sequenceLogic.SaveSequenceDataAsync(new SamlDownSequenceData
                {
                    Id          = saml2LogoutRequest.Id.Value,
                    RelayState  = binding.RelayState,
                    ResponseUrl = party.LoggedOutUrl,
                });

                await formActionLogic.CreateFormActionByUrlAsync(party.LoggedOutUrl);

                var type = RouteBinding.ToUpParties.First().Type;
                logger.ScopeTrace($"Request, Up type '{type}'.");
                switch (type)
                {
                case PartyTypes.Login:
                    return(await serviceProvider.GetService <LogoutUpLogic>().LogoutRedirect(RouteBinding.ToUpParties.First(), new LogoutRequest
                    {
                        DownParty = party,
                        SessionId = saml2LogoutRequest.SessionIndex,
                        RequireLogoutConsent = false,
                        PostLogoutRedirect = true,
                    }));

                case PartyTypes.OAuth2:
                    throw new NotImplementedException();

                case PartyTypes.Oidc:
                    throw new NotImplementedException();

                case PartyTypes.Saml2:
                    return(await serviceProvider.GetService <SamlLogoutUpLogic>().LogoutAsync(RouteBinding.ToUpParties.First(), GetSamlUpLogoutRequest(saml2LogoutRequest, party)));

                default:
                    throw new NotSupportedException($"Party type '{type}' not supported.");
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await LogoutResponseAsync(party.Id, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState, saml2LogoutRequest.Destination?.OriginalString, party.AuthnBinding.ResponseBinding, ex.Status));
            }
        }
        public ActionResult Logout()
        {
            if (!User.Identity.IsAuthenticated)
            {
                return(Redirect(Url.Content("~/")));
            }

            var binding       = new Saml2PostBinding();
            var logoutRequest = new Saml2LogoutRequest(config, ClaimsPrincipal.Current).DeleteSession();

            return(binding.Bind(logoutRequest).ToActionResult());
        }
Beispiel #19
0
 private LogoutRequest GetLogoutRequest(SamlDownParty party, Saml2LogoutRequest saml2LogoutRequest)
 {
     return(new LogoutRequest
     {
         DownPartyLink = new DownPartySessionLink {
             SupportSingleLogout = !string.IsNullOrWhiteSpace(party.SingleLogoutUrl), Id = party.Id, Type = party.Type
         },
         SessionId = saml2LogoutRequest.SessionIndex,
         RequireLogoutConsent = false,
         PostLogoutRedirect = true,
     });
 }
Beispiel #20
0
        private async Task <IActionResult> SingleLogoutRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            binding.ReadSamlRequest(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);

            try
            {
                logger.ScopeTrace($"SAML Single Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");
                logger.ScopeTrace("Up, SAML Single Logout request.", triggerEvent: true);

                binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
                logger.ScopeTrace("Up, Successful SAML Single Logout request.", triggerEvent: true);

                var session = await sessionUpPartyLogic.DeleteSessionAsync();

                await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(session.SessionId);

                await sequenceLogic.SaveSequenceDataAsync(new SamlUpSequenceData
                {
                    ExternalInitiatedSingleLogout = true,
                    Id         = saml2LogoutRequest.IdAsString,
                    UpPartyId  = party.Id,
                    RelayState = binding.RelayState,
                    SessionId  = saml2LogoutRequest.SessionIndex
                });

                if (party.DisableSingleLogout)
                {
                    return(await SingleLogoutResponseAsync(party, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState));
                }
                else
                {
                    (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, null, session.DownPartyLinks, session.Claims);

                    if (doSingleLogout)
                    {
                        return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                    }
                    else
                    {
                        return(await SingleLogoutResponseAsync(party, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState));
                    }
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await SingleLogoutResponseAsync(party, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState, ex.Status));
            }
        }
Beispiel #21
0
        private async Task <IActionResult> SingleLogoutRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding)
        {
            var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            binding.ReadSamlRequest(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);

            try
            {
                logger.ScopeTrace(() => $"SAML Single Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);
                logger.ScopeTrace(() => "Up, SAML Single Logout request.", triggerEvent: true);

                try
                {
                    binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
                    logger.ScopeTrace(() => "Up, Successful SAML Single Logout request.", triggerEvent: true);
                }
                catch (Exception ex)
                {
                    var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex);
                    if (isex != null)
                    {
                        throw isex;
                    }
                    throw;
                }

                var sequenceData = await sequenceLogic.SaveSequenceDataAsync(new SamlUpSequenceData
                {
                    ExternalInitiatedSingleLogout = true,
                    Id         = saml2LogoutRequest.IdAsString,
                    UpPartyId  = party.Id,
                    RelayState = binding.RelayState,
                    SessionId  = saml2LogoutRequest.SessionIndex
                });

                if (binding is Saml2Binding <Saml2PostBinding> )
                {
                    return(HttpContext.GetUpPartyUrl(party.Name, Constants.Routes.SamlController, Constants.Endpoints.UpJump.SingleLogoutRequestJump, includeSequence: true, partyBindingPattern: party.PartyBindingPattern).ToRedirectResult());
                }
                else
                {
                    return(await SingleLogoutRequestAsync(party, sequenceData));
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await SingleLogoutResponseAsync(party, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState, ex.Status));
            }
        }
Beispiel #22
0
        private void ValidateLogoutRequest(SamlDownParty party, Saml2LogoutRequest saml2LogoutRequest)
        {
            var requestIssuer = saml2LogoutRequest.Issuer;

            logger.SetScopeProperty("Issuer", requestIssuer);

            if (!party.Issuer.Equals(requestIssuer))
            {
                throw new SamlRequestException($"Invalid issuer '{requestIssuer}'.")
                      {
                          RouteBinding = RouteBinding, Status = Saml2StatusCodes.Responder
                      };
            }
        }
Beispiel #23
0
        public ActionResult Index()
        {
            var requestData = Request.ToHttpRequestData(true);

            var binding = Saml2Binding.Get(requestData);

            if (binding != null)
            {
                var unbindResult = binding.Unbind(requestData, null);
                switch (unbindResult.Data.LocalName)
                {
                case "LogoutRequest":
                {
                    var logoutRequest = Saml2LogoutRequest.FromXml(unbindResult.Data);

                    var model = new RespondToLogoutRequestModel()
                    {
                        LogoutRequestXml = unbindResult.Data.PrettyPrint(),
                        InResponseTo     = logoutRequest.Id.Value,
                        DestinationUrl   = new Uri(new Uri(logoutRequest.Issuer.Id + "/"), "Logout"),
                        RelayState       = Request.QueryString["RelayState"]
                    };
                    return(View("RespondToLogout", model));
                }

                case "LogoutResponse":
                {
                    var model = new ResponseModel
                    {
                        Status = unbindResult.Data["Status", Saml2Namespaces.Saml2PName]
                                 ["StatusCode", Saml2Namespaces.Saml2PName].GetAttribute("Value"),
                        ResponseXml = unbindResult.Data.PrettyPrint()
                    };
                    return(View("ReceivedLogoutResponse", model));
                }

                default:
                    throw new InvalidOperationException();
                }
            }
            {
                var model = new InitiateLogoutModel();

                if (Request.QueryString.AllKeys.Any())
                {
                    TryUpdateModel(model);
                }
                return(View("InitiateLogout", model));
            }
        }
Beispiel #24
0
        public async Task <IActionResult> LogOut()
        {
            if (User.Identity.IsAuthenticated)
            {
                var binding = new Saml2PostBinding();
                var request = new Saml2LogoutRequest(_configuration);
                await request.DeleteSession(HttpContext);

                return(binding.Bind(request)
                       .ToActionResult());
            }

            return(Redirect(Url.Action("Index", "Home")));
        }
        /// <summary>
        /// Starts Suomi.fi logout request.
        /// </summary>
        /// <returns>Redirect URL</returns>
        public string Logout(string sessionId, string sessionIndex)
        {
            var logoutRequest    = new Saml2LogoutRequest();
            var logoutRequestXml = logoutRequest.ToXml(config.Saml2EntityId, config.Saml2IdpEntityId, config.Saml2SLOUrl, sessionId, sessionIndex);

            authStateAccessor.Id = logoutRequest.Id;

            var binding = new Saml2HttpRedirect(string.Empty, crypto);

            binding.Run(logoutRequestXml);

            var redirectUrl = config.Saml2SLOUrl + "?" + binding.RedirectUrl;

            return(redirectUrl);
        }
Beispiel #26
0
        public async Task <IActionResult> SingleLogout()
        {
            var session = await idPSessionCookieRepository.GetAsync();

            var relyingParty = ValidateRelyingParty(session.RelyingPartyIssuer);

            var binding            = new Saml2PostBinding();
            var saml2LogoutRequest = new Saml2LogoutRequest(saml2Config, User)
            {
                Destination = relyingParty.SingleLogoutDestination
            };

            await idPSessionCookieRepository.DeleteAsync();

            return(binding.Bind(saml2LogoutRequest).ToActionResult());
        }
        public ActionResult Logout()
        {
            if (!User.Identity.IsAuthenticated)
            {
                return(RedirectToAction("Index"));
            }

            var logoutRequest = new Saml2LogoutRequest
            {
                Issuer      = new EndpointReference(Configuration.ISSUER),
                Destination = new EndpointAddress(Configuration.CFS_ENDPOINT)
            };

            var binding = new Saml2PostBinding();

            return(binding.Bind(logoutRequest).ToActionResult());
        }
Beispiel #28
0
        private static CommandResult HandleRequest(UnbindResult unbindResult, HttpRequestData httpRequest, IOptions options)
        {
            var request = Saml2LogoutRequest.FromXml(unbindResult.Data);

            var idp = options.IdentityProviders[request.Issuer];

            if (options.SPOptions.SigningServiceCertificate == null)
            {
                throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture,
                                                                     "Received a LogoutRequest from \"{0}\" but cannot reply because single logout responses " +
                                                                     "must be signed and there is no signing certificate configured. Looks like the idp is " +
                                                                     "configured for Single Logout despite Saml2 not exposing that functionality in the metadata.",
                                                                     request.Issuer.Id));
            }

            if (idp.SingleLogoutServiceResponseUrl == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                  "Received a LogoutRequest from \"{0}\" but cannot reply because on logout endpoint is " +
                                                                  "configured on the idp. Set a SingleLogoutServiceUrl if the idp is configured manually, " +
                                                                  "or check that the idp metadata contains a SingleLogoutService endpoint.",
                                                                  idp.EntityId.Id));
            }

            var response = new Saml2LogoutResponse(Saml2StatusCode.Success)
            {
                DestinationUrl     = idp.SingleLogoutServiceResponseUrl,
                SigningCertificate = options.SPOptions.SigningServiceCertificate,
                SigningAlgorithm   = idp.OutboundSigningAlgorithm,
                InResponseTo       = request.Id,
                Issuer             = options.SPOptions.EntityId,
                RelayState         = unbindResult.RelayState
            };

            options.Notifications.LogoutResponseCreated(response, request, httpRequest.User, idp);

            options.SPOptions.Logger.WriteInformation("Got a logout request " + request.Id
                                                      + ", responding with logout response " + response.Id);

            var result = Saml2Binding.Get(idp.SingleLogoutServiceBinding).Bind(
                response, options.SPOptions.Logger, options.Notifications.LogoutResponseXmlCreated);

            result.TerminateLocalSession = true;
            return(result);
        }
Beispiel #29
0
        public ValueTask <IdentityHttpResponse> Logout(string state)
        {
            var id = SamlIDManager.Generate(serviceProvider);

            var requestDocument = new Saml2LogoutRequest(
                id: id,
                issuer: serviceProvider,
                destination: redirectUrlPostLogout
                );

            var requestBinding = Saml2Binding.GetBindingForDocument(requestDocument, BindingType.Query, XmlSignatureAlgorithmType.RsaSha256, null, null);

            requestBinding.Sign(serviceProviderCert, requiredSignature);
            requestBinding.GetResponse(logoutUrl);
            var response = requestBinding.GetResponse(logoutUrl);

            return(new ValueTask <IdentityHttpResponse>(response));
        }
Beispiel #30
0
        private async Task <IActionResult> LogoutAsync <T>(SamlUpParty party, Saml2Binding <T> binding, LogoutRequest logoutRequest)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party, includeSigningCertificate: true);
            await formActionLogic.AddFormActionByUrlAsync(samlConfig.SingleLogoutDestination.OriginalString);

            binding.RelayState = SequenceString;

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            saml2LogoutRequest.SessionIndex = logoutRequest.SessionId;

            var nameID       = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameId).Select(c => c.Value).FirstOrDefault();
            var nameIdFormat = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameIdFormat).Select(c => c.Value).FirstOrDefault();

            if (!nameID.IsNullOrEmpty())
            {
                if (nameIdFormat.IsNullOrEmpty())
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID);
                }
                else
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID, new Uri(nameIdFormat));
                }
            }

            binding.Bind(saml2LogoutRequest);
            logger.ScopeTrace($"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Logout url '{samlConfig.SingleLogoutDestination?.OriginalString}'.");
            logger.ScopeTrace("Up, SAML Logout request.", triggerEvent: true);

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult()));
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult()));
            }
            else
            {
                throw new NotSupportedException();
            }
        }