public async Task CommandResultExtensions_Apply()
        {
            var context = TestHelpers.CreateHttpContext();

            var state = new StoredRequestState(
                new EntityId("https://idp.example.com"),
                new Uri("https://sp.example.com/ReturnUrl"),
                new Saml2Id(),
                new Dictionary <string, string>()
            {
                { "Key1", "Value1" },
                { "Key2", "value2" }
            });

            var redirectLocation = "https://destination.com";
            var commandResult    = new CommandResult()
            {
                HttpStatusCode  = System.Net.HttpStatusCode.Redirect,
                Location        = new Uri(redirectLocation),
                SetCookieName   = "Saml2.123",
                RelayState      = "123",
                RequestState    = state,
                ContentType     = "application/json",
                Content         = "{ value: 42 }",
                ClearCookieName = "Clear-Cookie",
                Principal       = new ClaimsPrincipal(new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.NameIdentifier, "SomerUser")
                }, "authType")),
                RelayData = new Dictionary <string, string>()
                {
                    { "Relayed", "Value" }
                }
            };

            ClaimsPrincipal          principal = null;
            AuthenticationProperties authProps = null;
            var authService = Substitute.For <IAuthenticationService>();

            context.RequestServices.GetService(typeof(IAuthenticationService))
            .Returns(authService);
            await authService.SignInAsync(
                context,
                "TestSignInScheme",
                Arg.Do <ClaimsPrincipal>(p => principal           = p),
                Arg.Do <AuthenticationProperties>(ap => authProps = ap));

            commandResult.Apply(context, new StubDataProtector(), "TestSignInScheme");

            var expectedCookieData = HttpRequestData.ConvertBinaryData(
                StubDataProtector.Protect(commandResult.GetSerializedRequestState()));

            context.Response.StatusCode.Should().Be(302);
            context.Response.Headers["Location"].SingleOrDefault()
            .Should().Be("https://destination.com/", "location header should be set");
            context.Response.Cookies.Received().Append(
                "Saml2.123", expectedCookieData, Arg.Is <CookieOptions>(co => co.HttpOnly));

            context.Response.Cookies.Received().Delete("Clear-Cookie");

            context.Response.ContentType
            .Should().Be("application/json", "content type should be set");

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            new StreamReader(context.Response.Body).ReadToEnd()
            .Should().Be("{ value: 42 }", "content should be set");

            principal.HasClaim(ClaimTypes.NameIdentifier, "SomerUser").Should().BeTrue();
            authProps.Items["Relayed"].Should().Be("Value");
            authProps.RedirectUri.Should().Be(redirectLocation);
        }
示例#2
0
        public async Task Saml2Handler_Acs_Works()
        {
            var context = new Saml2HandlerTestContext();

            context.HttpContext.Request.Method = "POST";
            context.HttpContext.Request.Path   = "/Saml2/Acs";

            var authProps = new AuthenticationProperties()
            {
                IssuedUtc = new DateTimeOffset(DateTime.UtcNow)
            };

            authProps.Items["Test"] = "TestValue";

            var state = new StoredRequestState(
                new EntityId("https://idp.example.com"),
                new Uri("https://localhost/LoggedIn"),
                new Saml2Id("InResponseToId"),
                authProps.Items);

            var relayState = SecureKeyGenerator.CreateRelayState();

            var cookieData = HttpRequestData.ConvertBinaryData(
                StubDataProtector.Protect(state.Serialize()));

            var cookieName = $"{StoredRequestState.CookieNameBase}{relayState}";

            context.HttpContext.Request.Cookies = new StubCookieCollection(
                Enumerable.Repeat(new KeyValuePair <string, string>(
                                      cookieName, cookieData), 1));

            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 = """ + MethodBase.GetCurrentMethod().Name + @""" Version=""2.0""
                IssueInstant=""2013-01-01T00:00:00Z"" InResponseTo=""InResponseToId"" >
                <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=""" + MethodBase.GetCurrentMethod().Name + @"_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:AudienceRestriction>
                            <saml2:Audience>http://sp.example.com/saml2</saml2:Audience>
                        </saml2:AudienceRestriction>
                    </saml2:Conditions>
                </saml2:Assertion>
            </saml2p:Response>";

            var form = Substitute.For <IFormCollection>();

            IEnumerator <KeyValuePair <string, StringValues> > formCollectionEnumerator =
                new KeyValuePair <string, StringValues>[]
            {
                new KeyValuePair <string, StringValues>(
                    "SAMLResponse", new StringValues(
                        Convert.ToBase64String(
                            Encoding.UTF8.GetBytes(SignedXmlHelper.SignXml(response))))),
                new KeyValuePair <string, StringValues>(
                    "RelayState", new StringValues(relayState))
            }.AsEnumerable().GetEnumerator();

            form.GetEnumerator().Returns(formCollectionEnumerator);

            context.HttpContext.Request.Form.Returns(form);

            var authService = Substitute.For <IAuthenticationService>();

            context.HttpContext.RequestServices.GetService(typeof(IAuthenticationService))
            .Returns(authService);

            ClaimsPrincipal          principal       = null;
            AuthenticationProperties actualAuthProps = null;

            await authService.SignInAsync(
                context.HttpContext,
                TestHelpers.defaultSignInScheme,
                Arg.Do <ClaimsPrincipal>(p => principal = p),
                Arg.Do <AuthenticationProperties>(ap => actualAuthProps = ap));

            await context.Subject.HandleRequestAsync();

            principal.HasClaim(ClaimTypes.NameIdentifier, "SomeUser").Should().BeTrue();
            actualAuthProps.IssuedUtc.Should().Be(authProps.IssuedUtc);
            actualAuthProps.Items["Test"].Should().Be("TestValue");

            context.HttpContext.Response.Headers["Location"].Single().Should().Be(
                state.ReturnUrl.OriginalString);
            context.HttpContext.Response.StatusCode.Should().Be(303);
        }