Пример #1
0
        public void Saml2Response_Validate_FalseOnReplayedInResponseTo()
        {
            var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value;

            var request = idp.CreateAuthenticateRequest();

            var responseXML =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            InResponseTo = """ + request.Id + @""">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" />
                </saml2p:Status>
            </saml2p:Response>";

            responseXML = SignedXmlHelper.SignXml(responseXML);

            var response = Saml2Response.Read(responseXML);

            response.Validate(SignedXmlHelper.TestCert).Should().BeTrue();

            response = Saml2Response.Read(responseXML);
            response.Validate(SignedXmlHelper.TestCert).Should().BeFalse();
        }
Пример #2
0
        public void Saml2Response_Read_ThrowsWrongRootNamespace()
        {
            Action a = () => Saml2Response.Read("<saml2p:Response xmlns:saml2p=\"something\" /> ");

            a.ShouldThrow <XmlException>()
            .WithMessage("Expected a SAML2 assertion document");
        }
Пример #3
0
        public void Saml2Response_GetClaims_ThrowsOnNotValidated()
        {
            var response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_GetClaims_ThrowsOnNotValidated"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion
                Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnNotValidated_Assertion""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                </saml2:Assertion>
            </saml2p:Response>";

            Action a = () => Saml2Response.Read(response).GetClaims();

            a.ShouldThrow <InvalidOperationException>()
            .WithMessage("The Saml2Response must be validated first.");
        }
Пример #4
0
        public void Saml2Response_Read_BasicParams()
        {
            string response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
                <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            ID = ""Saml2Response_Read_BasicParams"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            InResponseTo = ""InResponseToId""
            Destination=""http://destination.example.com"">
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" />
                </saml2p:Status>
            </saml2p:Response>";

            var expected = new
            {
                Id             = new Saml2Id("Saml2Response_Read_BasicParams"),
                IssueInstant   = new DateTime(2013, 01, 01, 0, 0, 0, DateTimeKind.Utc),
                Status         = Saml2StatusCode.Requester,
                Issuer         = (string)null,
                DestinationUri = new Uri("http://destination.example.com"),
                MessageName    = "SAMLResponse",
                InResponseTo   = new Saml2Id("InResponseToId"),
            };

            Saml2Response.Read(response).ShouldBeEquivalentTo(expected,
                                                              opt => opt.Excluding(s => s.XmlDocument));
        }
Пример #5
0
        public void Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature()
        {
            var response =
                @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                {0}
                {1}
            </saml2p:Response>";

            var assertion1 = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature_Assertion1""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>";

            var assertionToInject = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature_Assertion2""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser2</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>";

            var signedAssertion1 = SignedXmlHelper.SignXml(assertion1);

            var signedAssertion1Doc = new XmlDocument {
                PreserveWhitespace = true
            };

            signedAssertion1Doc.LoadXml(signedAssertion1);

            var signatureToCopy = signedAssertion1Doc.DocumentElement["Signature", SignedXml.XmlDsigNamespaceUrl];

            var assertionToInjectDoc = new XmlDocument {
                PreserveWhitespace = true
            };

            assertionToInjectDoc.LoadXml(assertionToInject);

            assertionToInjectDoc.DocumentElement.AppendChild(assertionToInjectDoc.ImportNode(signatureToCopy, true));

            var signedAssertionToInject = assertionToInjectDoc.OuterXml;

            var signedResponse = string.Format(response, signedAssertion1, signedAssertionToInject);

            Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeFalse();
        }
Пример #6
0
        public void Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature()
        {
            var response =
                @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature_Assertion1""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>
            </saml2p:Response>";

            var signedResponse = SignedXmlHelper.SignXml(response).Replace("SomeUser", "SomeOtherUser");

            Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeFalse();
        }
Пример #7
0
        public void Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessage()
        {
            var response =
                @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessage"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                {0}
            </saml2p:Response>";

            var assertion =
                @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessagee_Assertion1""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>";


            var signedAssertion = SignedXmlHelper.SignXml(assertion);
            var signedResponse  = string.Format(response, signedAssertion);

            Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeTrue();
        }
Пример #8
0
        public void Saml2Response_Validate_FalseOnMissingSignatureInResponseAndAnyAssertion()
        {
            var response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion_Assertion1""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>
                <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion_Assertion2""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>
            </saml2p:Response>";

            Saml2Response.Read(response).Validate(null).Should().BeFalse();
        }
Пример #9
0
        public void Saml2Response_Validate_TrueOnMissingInResponseTo_IfAllowed()
        {
            KentorAuthServicesSection.Current.IdentityProviders.First().AllowConfigEdit(true);
            KentorAuthServicesSection.Current.IdentityProviders.First().AllowUnsolicitedAuthnResponse = true;
            KentorAuthServicesSection.Current.IdentityProviders.First().AllowConfigEdit(false);
            var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value;

            var request = idp.CreateAuthenticateRequest();

            var responseXML =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" />
                </saml2p:Status>
            </saml2p:Response>";

            responseXML = SignedXmlHelper.SignXml(responseXML);

            var response = Saml2Response.Read(responseXML);

            response.Validate(SignedXmlHelper.TestCert).Should().BeTrue();
        }
Пример #10
0
        public void Saml2Response_Validate_FalseOnReplyFromWrongIdp()
        {
            // A valid response is received, but it is not from the idp that we
            // did send the AuthnRequest to.
            var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value;

            var request = idp.CreateAuthenticateRequest();

            var responseXML =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            InResponseTo = """ + request.Id + @""">
                <saml2p:Issuer>https://idp.anotheridp.com</saml2p:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" />
                </saml2p:Status>
            </saml2p:Response>";

            responseXML = SignedXmlHelper.SignXml(responseXML);

            var response = Saml2Response.Read(responseXML);

            response.Validate(SignedXmlHelper.TestCert).Should().BeFalse();
        }
Пример #11
0
        public void Saml2Response_GetClaims_ThrowsOnExpired()
        {
            var response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            ID = ""Saml2Response_GetClaims_ThrowsOnExpired"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            Issuer = ""https://some.issuer.example.com"">
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnExpired_Assertion""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2013-06-30T08:00:00Z"" />
                </saml2:Assertion>
            </saml2p:Response>";

            response = SignedXmlHelper.SignXml(response);
            var r = Saml2Response.Read(response);

            r.Validate(SignedXmlHelper.TestCert);

            Action a = () => r.GetClaims();

            a.ShouldThrow <SecurityTokenExpiredException>();
        }
Пример #12
0
        public void Saml2Response_Read_ThrowsOnNonXml()
        {
            Action a = () => Saml2Response.Read("not xml");

            a.ShouldThrow <XmlException>()
            .WithMessage("Data at the root level is invalid. Line 1, position 1.");
        }
Пример #13
0
        public void Saml2Response_Read_ThrowsWrongRootNodeName()
        {
            Action a = () => Saml2Response.Read("<saml2p:NotResponse xmlns:saml2p=\"urn:oasis:names:tc:SAML:2.0:protocol\" />");

            a.ShouldThrow <XmlException>()
            .WithMessage("Expected a SAML2 assertion document");
        }
Пример #14
0
        public void Saml2Response_GetClaims_ThrowsOnResponseNotValid()
        {
            var response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            ID = ""Saml2Response_GetClaims_ThrowsOnResponseNotValid"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            Issuer = ""https://some.issuer.example.com"">
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnResponseNotValid_Assertion""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                </saml2:Assertion>
            </saml2p:Response>";

            response = SignedXmlHelper.SignXml(response);
            response = response.Replace("2013-09-25", "2013-09-26");

            var r = Saml2Response.Read(response);

            r.Validate(SignedXmlHelper.TestCert);
            Action a = () => r.GetClaims();

            a.ShouldThrow <InvalidOperationException>()
            .WithMessage("The Saml2Response didn't pass validation");
        }
Пример #15
0
        private static CommandResult ProcessResponse(
            IOptions options,
            Saml2Response samlResponse,
            StoredRequestState storedRequestState)
        {
            var principal = new ClaimsPrincipal(samlResponse.GetClaims(options));

            principal = options.SPOptions.SystemIdentityModelIdentityConfiguration
                        .ClaimsAuthenticationManager.Authenticate(null, principal);

            if (options.SPOptions.ReturnUrl == null)
            {
                if (storedRequestState == null)
                {
                    throw new ConfigurationErrorsException(UnsolicitedMissingReturnUrlMessage);
                }
                if (storedRequestState.ReturnUrl == null)
                {
                    throw new ConfigurationErrorsException(SpInitiatedMissingReturnUrl);
                }
            }

            return(new CommandResult()
            {
                HttpStatusCode = HttpStatusCode.SeeOther,
                Location = storedRequestState == null?null:storedRequestState.ReturnUrl ?? options.SPOptions.ReturnUrl,
                Principal = principal,
                RelayData = storedRequestState == null?null:storedRequestState.RelayData
            });
        }
Пример #16
0
        public void Saml2Response_Xml_FromData_ContainsBasicData()
        {
            var issuer      = "http://idp.example.com";
            var nameId      = "JohnDoe";
            var destination = "http://destination.example.com/";

            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, nameId)
            });

            // Grab current time both before and after generating the response
            // to avoid heisenbugs if the second counter is updated while creating
            // the response.
            string before   = DateTime.UtcNow.ToSaml2DateTimeString();
            var    response = new Saml2Response(issuer, SignedXmlHelper.TestCert,
                                                new Uri(destination), identity);
            string after = DateTime.UtcNow.ToSaml2DateTimeString();

            var xml = response.XmlDocument;

            xml.FirstChild.OuterXml.Should().StartWith("<?xml version=\"1.0\"");
            xml.DocumentElement["Issuer", Saml2Namespaces.Saml2Name].InnerText.Should().Be(issuer);
            xml.DocumentElement["Assertion", Saml2Namespaces.Saml2Name]
            ["Subject", Saml2Namespaces.Saml2Name]["NameID", Saml2Namespaces.Saml2Name]
            .InnerText.Should().Be(nameId);
            xml.DocumentElement.GetAttribute("Destination").Should().Be(destination);
            xml.DocumentElement.GetAttribute("ID").Should().NotBeBlank();
            xml.DocumentElement.GetAttribute("Version").Should().Be("2.0");
            xml.DocumentElement.GetAttribute("IssueInstant").Should().Match(
                i => i == before || i == after);
        }
Пример #17
0
        private static CommandResult ProcessResponse(
            IOptions options,
            Saml2Response samlResponse,
            StoredRequestState storedRequestState)
        {
            var principal = new ClaimsPrincipal(samlResponse.GetClaims(options, storedRequestState?.RelayData));

            if (options.SPOptions.ReturnUrl == null)
            {
                if (storedRequestState == null)
                {
                    throw new ConfigurationErrorsException(UnsolicitedMissingReturnUrlMessage);
                }
                if (storedRequestState.ReturnUrl == null)
                {
                    throw new ConfigurationErrorsException(SpInitiatedMissingReturnUrl);
                }
            }

            options.SPOptions.Logger.WriteInformation("Successfully processed SAML response " + samlResponse.Id
                                                      + " and authenticated " + principal.FindFirst(ClaimTypes.NameIdentifier)?.Value);

            return(new CommandResult()
            {
                HttpStatusCode = HttpStatusCode.SeeOther,
                Location = storedRequestState?.ReturnUrl ?? options.SPOptions.ReturnUrl,
                Principal = principal,
                RelayData = storedRequestState?.RelayData,
                SessionNotOnOrAfter = samlResponse.SessionNotOnOrAfter
            });
        }
Пример #18
0
        public CommandResult Run(HttpRequestData request, IOptions options)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var binding = Saml2Binding.Get(request);

            if (binding != null)
            {
                UnbindResult unbindResult = null;
                try
                {
                    unbindResult = binding.Unbind(request, options);
                    var samlResponse = new Saml2Response(unbindResult.Data, request.StoredRequestState?.MessageId);

                    var result = ProcessResponse(options, samlResponse, request.StoredRequestState);
                    if (unbindResult.RelayState != null)
                    {
                        result.ClearCookieName = "Kentor." + unbindResult.RelayState;
                    }
                    return(result);
                }
                catch (FormatException ex)
                {
                    throw new BadFormatSamlResponseException(
                              "The SAML Response did not contain valid BASE64 encoded data.", ex);
                }
                catch (XmlException ex)
                {
                    var newEx = new BadFormatSamlResponseException(
                        "The SAML response contains incorrect XML", ex);

                    // Add the payload to the exception
                    if (unbindResult != null)
                    {
                        newEx.Data["Saml2Response"] = unbindResult.Data.OuterXml;
                    }
                    throw newEx;
                }
                catch (Exception ex)
                {
                    if (unbindResult != null)
                    {
                        // Add the payload to the existing exception
                        ex.Data["Saml2Response"] = unbindResult.Data.OuterXml;
                    }
                    throw;
                }
            }

            throw new NoSamlResponseFoundException();
        }
Пример #19
0
        private User GetUserByName(Saml2Response samlResponse)
        {
            var user = _entities.Get <User>()
                       .EagerLoad(_entities, _loadUser)
                       .ByName(samlResponse.EduPersonPrincipalName);

            return(user);
        }
Пример #20
0
        public void Saml2Response_ToXml()
        {
            string response = @"<?xml version=""1.0"" encoding=""UTF-8""?><saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID=""Saml2Response_ToXml"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""><saml2p:Status><saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /></saml2p:Status></saml2p:Response>";

            var subject = Saml2Response.Read(response).ToXml();

            subject.Should().Be(response);
        }
Пример #21
0
        private User GetUserByEduPersonTargetedId(Saml2Response samlResponse)
        {
            var user = _entities.Get <User>()
                       .EagerLoad(_entities, _loadUser)
                       .ByEduPersonTargetedId(samlResponse.EduPersonTargetedId);

            return(user);
        }
Пример #22
0
        public void Saml2Response_Read_ThrowsOnWrongVersion()
        {
            Action a = () => Saml2Response.Read("<saml2p:Response xmlns:saml2p=\""
                                                + Saml2Namespaces.Saml2P + "\" Version=\"wrong\" />");

            a.ShouldThrow <XmlException>()
            .WithMessage("Wrong or unsupported SAML2 version");
        }
Пример #23
0
 private static void VerifySignature(Saml2Response response)
 {
     if (response.IsSigned && !response.VerifySignature())
     {
         throw new InvalidOperationException(string.Format(
                                                 "SAML 2 response signature for '{0}' failed to verify.",
                                                 response.IssuerNameIdentifier));
     }
 }
 /// <summary>
 /// Delete the current Federated Authentication Session.
 /// </summary>
 public static bool DeleteSession(this Saml2Response saml2Response)
 {
     if (saml2Response.Status == Saml2StatusCodes.Success)
     {
         FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
         FederatedAuthentication.SessionAuthenticationModule.SignOut();
         return(true);
     }
     return(false);
 }
Пример #25
0
        public static Saml2AuthResponse Create(string samlResponse,
                                               Saml2Id responseToId,
                                               EntityId issuer,
                                               X509Certificate2 idpCert,
                                               X509Certificate2 serviceCertificate,
                                               EntityId serviceId)
        {
            var decoded = DecodeBase64(samlResponse);
            var xmlDoc  = new XmlDocument();

            xmlDoc.PreserveWhitespace = true;
            xmlDoc.LoadXml(decoded);

            var response = new Saml2Response(xmlDoc.DocumentElement, responseToId);

            if (response.Status != Saml2StatusCode.Success)
            {
                log.LogWarning("SAML authentication error: " + response.Status + " (" + response.StatusMessage + ")");
                return(new Saml2AuthResponse(false)
                {
                    Status = response.Status
                });
            }

            var spOptions = new SPOptions();

            spOptions.EntityId = serviceId;
            spOptions.ServiceCertificates.Add(serviceCertificate);
            var options = new Options(spOptions);
            var idp     = new IdentityProvider(issuer, spOptions);

            idp.SigningKeys.AddConfiguredKey(idpCert);
            options.IdentityProviders.Add(idp);


            var identities = response.GetClaims(options)?.ToArray();

            if (identities == null || identities.Length == 0)
            {
                return(new Saml2AuthResponse(false));
            }

            var identity  = identities.First();
            var firstName = identity.FindFirstValue(AttributeNames.GivenName);
            var lastName  = identity.FindFirstValue(AttributeNames.Sn);
            var ssn       = identity.FindFirstValue(AttributeNames.NationalIdentificationNumber);
            var nameId    = identity.FindFirstValue(AttributeNames.NameIdentifier);
            var sessionId = identity.FindFirstValue(AttributeNames.SessionIndex);

            return(new Saml2AuthResponse(true)
            {
                FirstName = firstName, LastName = lastName, SSN = ssn, RelayState = response.RelayState, NameIdentifier = nameId, SessionIndex = sessionId
            });
        }
        public void Saml2Response_Ctor_FromData()
        {
            var issuer = "http://idp.example.com";
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "JohnDoe")
            });
            var response = new Saml2Response(issuer, null, null, identity);

            response.Issuer.Should().Be(issuer);
            response.GetClaims().Single().ShouldBeEquivalentTo(identity);
        }
Пример #27
0
        public void Saml2Response_Ctor_FromData()
        {
            var issuer   = "http://idp.example.com";
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "JohnDoe")
            });
            var response = new Saml2Response(issuer, null, null, identity);

            response.Issuer.Should().Be(issuer);
            response.GetClaims().Single().ShouldBeEquivalentTo(identity);
        }
 public static IEnumerable <ClaimsIdentity> GetClaimsIdentities(Saml2Response token)
 {
     try
     {
         return(token.GetClaims(samlOptions));
     }
     catch (Saml2ResponseFailedValidationException exception)
     {
         Debug.WriteLine(exception.Message);
         throw new HttpException(401, exception.Message);
     }
 }
        public XmlDocument GetDecodedSamlResponse(Saml2Response saml2Response)
        {
            var doc = new XmlDocument
            {
                XmlResolver        = null,
                PreserveWhitespace = true
            };
            var base64SamlResponse = saml2Response.Response;
            var samlResponse       = Encoding.UTF8.GetString(Convert.FromBase64String(base64SamlResponse));

            doc.LoadXml(samlResponse);
            return(doc);
        }
Пример #30
0
        private Person GetPerson(Saml2Response samlResponse)
        {
            Person person = null;

            // first, look up person by mail attribute (if present)
            var mails = samlResponse.Mails;

            if (mails != null && mails.Any())
            {
                foreach (var mail in mails)
                {
                    person = GetPersonByEmail(mail);
                    if (person != null)
                    {
                        break;
                    }
                }
            }

            // next, look for person by person principal name
            if (person == null)
            {
                person = GetPersonByEmail(samlResponse.EduPersonPrincipalName);
            }

            // need to create person if they do not exist
            if (person == null)
            {
                person = new Person
                {
                    DisplayName = samlResponse.CommonName ??
                                  samlResponse.DisplayName ??
                                  samlResponse.EduPersonPrincipalName,
                    FirstName = samlResponse.GivenName,
                    LastName  = samlResponse.SurName,
                };
            }

            // make sure there is not a user with person principal name
            var user = GetUserByName(samlResponse);

            if (user != null && user.Person != person)
            {
                throw new InvalidOperationException(string.Format(
                                                        "The user account '{0}' does not match expected person '{1}'.",
                                                        user.Name, person.DisplayName));
            }

            return(person);
        }
Пример #31
0
        public void Saml2Response_Validate_FalseOnMissingSignature()
        {
            var response =
                @"<?xml version=""1.0"" encoding=""UTF-8""?>
            <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            ID = ""Saml2Response_Validates_FalseOnMissingSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
            Issuer = ""https://some.issuer.example.com"">
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" />
                </saml2p:Status>
            </saml2p:Response>";

            Saml2Response.Read(response).Validate(null).Should().BeFalse();
        }
        public void Saml2Response_MessageName()
        {
            var subject = new Saml2Response("issuer", null, null);

            subject.MessageName.Should().Be("SAMLResponse");
        }
        public void Saml2Response_Xml_FromData_IsSigned()
        {
            var issuer = "http://idp.example.com";
            var nameId = "JohnDoe";
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, nameId)
            });

            var response = new Saml2Response(issuer, SignedXmlHelper.TestCert,
                null, claimsIdentities: identity);

            var xml = response.XmlDocument;

            var signedXml = new SignedXml(xml);
            var signature = xml.DocumentElement["Signature", SignedXml.XmlDsigNamespaceUrl];
            signedXml.LoadXml(signature);

            signature.Should().NotBeNull();

            signedXml.CheckSignature(SignedXmlHelper.TestCert, true).Should().BeTrue();
        }
        public void Saml2Response_Xml_FromData_ContainsStatus_Success()
        {
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "JohnDoe")
            });

            var response = new Saml2Response("issuer", SignedXmlHelper.TestCert,
                new Uri("http://destination.example.com"), identity);

            var xml = response.XmlDocument;

            var subject = xml.DocumentElement["Status", Saml2Namespaces.Saml2PName];

            subject["StatusCode", Saml2Namespaces.Saml2PName].GetAttribute("Value")
                .Should().Be("urn:oasis:names:tc:SAML:2.0:status:Success");
        }
        public void Saml2Response_Xml_FromData_ContainsBasicData()
        {
            var issuer = "http://idp.example.com";
            var nameId = "JohnDoe";
            var destination = "http://destination.example.com/";

            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, nameId)
            });

            // Grab current time both before and after generating the response
            // to avoid heisenbugs if the second counter is updated while creating
            // the response.
            string before = DateTime.UtcNow.ToSaml2DateTimeString();
            var response = new Saml2Response(issuer, SignedXmlHelper.TestCert,
                new Uri(destination), identity);
            string after = DateTime.UtcNow.ToSaml2DateTimeString();

            var xml = response.XmlDocument;

            xml.FirstChild.OuterXml.Should().StartWith("<?xml version=\"1.0\"");
            xml.DocumentElement["Issuer", Saml2Namespaces.Saml2Name].InnerText.Should().Be(issuer);
            xml.DocumentElement["Assertion", Saml2Namespaces.Saml2Name]
                ["Subject", Saml2Namespaces.Saml2Name]["NameID", Saml2Namespaces.Saml2Name]
                .InnerText.Should().Be(nameId);
            xml.DocumentElement.GetAttribute("Destination").Should().Be(destination);
            xml.DocumentElement.GetAttribute("ID").Should().NotBeBlank();
            xml.DocumentElement.GetAttribute("Version").Should().Be("2.0");
            xml.DocumentElement.GetAttribute("IssueInstant").Should().Match(
                i => i == before || i == after);
        }
Пример #36
0
 public Saml2PostBinding Bind(Saml2Response saml2Response, X509Certificate2 signingCertificate = null)
 {
     return BindInternal(saml2Response as Saml2Request, Saml2Constants.Message.SamlResponse, signingCertificate);
 }
Пример #37
0
 public Saml2Response Unbind(HttpRequestBase request, Saml2Response saml2Response, X509Certificate2 signatureValidationCertificate)
 {
     return UnbindInternal(request, saml2Response as Saml2Request, Saml2Constants.Message.SamlResponse, signatureValidationCertificate) as Saml2Response;
 }
Пример #38
0
        public void Saml2Response_Xml_FromData_ContainsInResponseTo()
        {
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "JohnDoe")
            });

            var response = new Saml2Response("issuer", SignedXmlHelper.TestCert,
                new Uri("http://destination.example.com"), "InResponseToID", identity);

            var xml = response.XmlDocument;

            xml.DocumentElement.GetAttribute("InResponseTo").Should().Be("InResponseToID");
        }