Security/test/Microsoft.Owin.Security.Int.../CookieInteropTests.cs

333 строки
15 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Testing;
using Owin;
using Xunit;
namespace Microsoft.Owin.Security.Interop
{
public class CookiesInteropTests
{
[Fact]
public async Task AspNetCoreWithInteropCookieContainsIdentity()
{
var identity = new ClaimsIdentity("Cookies");
identity.AddClaim(new Claim(ClaimTypes.Name, "Alice"));
var dataProtection = DataProtectionProvider.Create(new DirectoryInfo("..\\..\\artifacts"));
var dataProtector = dataProtection.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", // full name of the ASP.NET Core type
Cookies.CookieAuthenticationDefaults.AuthenticationType, "v2");
var interopServer = TestServer.Create(app =>
{
app.Properties["host.AppName"] = "Microsoft.Owin.Security.Tests";
app.UseCookieAuthentication(new Cookies.CookieAuthenticationOptions
{
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(dataProtector)),
CookieName = AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.CookiePrefix
+ AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme,
});
app.Run(context =>
{
context.Authentication.SignIn(identity);
return Task.FromResult(0);
});
});
var transaction = await SendAsync(interopServer, "http://example.com");
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseAuthentication();
app.Run(async context =>
{
var result = await context.AuthenticateAsync("Cookies");
await context.Response.WriteAsync(result.Ticket.Principal.Identity.Name);
});
})
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var request = new HttpRequestMessage(HttpMethod.Get, "http://example.com/login");
foreach (var cookie in SetCookieHeaderValue.ParseList(transaction.SetCookie))
{
request.Headers.Add("Cookie", cookie.Name + "=" + cookie.Value);
}
var response = await newServer.CreateClient().SendAsync(request);
Assert.Equal("Alice", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task AspNetCoreWithLargeInteropCookieContainsIdentity()
{
var identity = new ClaimsIdentity("Cookies");
identity.AddClaim(new Claim(ClaimTypes.Name, new string('a', 1024 * 5)));
var dataProtection = DataProtectionProvider.Create(new DirectoryInfo("..\\..\\artifacts"));
var dataProtector = dataProtection.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", // full name of the ASP.NET Core type
Cookies.CookieAuthenticationDefaults.AuthenticationType, "v2");
var interopServer = TestServer.Create(app =>
{
app.Properties["host.AppName"] = "Microsoft.Owin.Security.Tests";
app.UseCookieAuthentication(new Cookies.CookieAuthenticationOptions
{
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(dataProtector)),
CookieName = AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.CookiePrefix
+ AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme,
CookieManager = new ChunkingCookieManager(),
});
app.Run(context =>
{
context.Authentication.SignIn(identity);
return Task.FromResult(0);
});
});
var transaction = await SendAsync(interopServer, "http://example.com");
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseAuthentication();
app.Run(async context =>
{
var result = await context.AuthenticateAsync("Cookies");
await context.Response.WriteAsync(result.Ticket.Principal.Identity.Name);
});
})
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var request = new HttpRequestMessage(HttpMethod.Get, "http://example.com/login");
foreach (var cookie in SetCookieHeaderValue.ParseList(transaction.SetCookie))
{
request.Headers.Add("Cookie", cookie.Name + "=" + cookie.Value);
}
var response = await newServer.CreateClient().SendAsync(request);
Assert.Equal(1024 * 5, (await response.Content.ReadAsStringAsync()).Length);
}
[Fact]
public async Task InteropWithNewCookieContainsIdentity()
{
var user = new ClaimsPrincipal();
var identity = new ClaimsIdentity("scheme");
identity.AddClaim(new Claim(ClaimTypes.Name, "Alice"));
user.AddIdentity(identity);
var dataProtection = DataProtectionProvider.Create(new DirectoryInfo("..\\..\\artifacts"));
var dataProtector = dataProtection.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", // full name of the ASP.NET Core type
Cookies.CookieAuthenticationDefaults.AuthenticationType, "v2");
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseAuthentication();
app.Run(context => context.SignInAsync("Cookies", user));
})
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var cookies = await SendAndGetCookies(newServer, "http://example.com/login");
var server = TestServer.Create(app =>
{
app.Properties["host.AppName"] = "Microsoft.Owin.Security.Tests";
app.UseCookieAuthentication(new Cookies.CookieAuthenticationOptions
{
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(dataProtector)),
CookieName = AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.CookiePrefix
+ AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme,
});
app.Run(async context =>
{
var result = await context.Authentication.AuthenticateAsync("Cookies");
Describe(context.Response, result);
});
});
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", cookies);
Assert.Equal("Alice", FindClaimValue(transaction2, ClaimTypes.Name));
}
[Fact]
public async Task InteropWithLargeNewCookieContainsIdentity()
{
var user = new ClaimsPrincipal();
var identity = new ClaimsIdentity("scheme");
identity.AddClaim(new Claim(ClaimTypes.Name, new string('a', 1024 * 5)));
user.AddIdentity(identity);
var dataProtection = DataProtectionProvider.Create(new DirectoryInfo("..\\..\\artifacts"));
var dataProtector = dataProtection.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", // full name of the ASP.NET Core type
Cookies.CookieAuthenticationDefaults.AuthenticationType, "v2");
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseAuthentication();
app.Run(context => context.SignInAsync("Cookies", user));
})
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var cookies = await SendAndGetCookies(newServer, "http://example.com/login");
var server = TestServer.Create(app =>
{
app.Properties["host.AppName"] = "Microsoft.Owin.Security.Tests";
app.UseCookieAuthentication(new Cookies.CookieAuthenticationOptions
{
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(dataProtector)),
CookieName = AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.CookiePrefix
+ AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme,
CookieManager = new ChunkingCookieManager(),
});
app.Run(async context =>
{
var result = await context.Authentication.AuthenticateAsync("Cookies");
Describe(context.Response, result);
});
});
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", cookies);
Assert.Equal(1024 * 5, FindClaimValue(transaction2, ClaimTypes.Name).Length);
}
private static async Task<IList<string>> SendAndGetCookies(AspNetCore.TestHost.TestServer server, string uri)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
var response = await server.CreateClient().SendAsync(request);
if (response.Headers.Contains("Set-Cookie"))
{
IList<string> cookieHeaders = new List<string>();
foreach (var cookie in SetCookieHeaderValue.ParseList(response.Headers.GetValues("Set-Cookie").ToList()))
{
cookieHeaders.Add(cookie.Name + "=" + cookie.Value);
}
return cookieHeaders;
}
return null;
}
private static string FindClaimValue(Transaction transaction, string claimType)
{
XElement claim = transaction.ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType);
if (claim == null)
{
return null;
}
return claim.Attribute("value").Value;
}
private static void Describe(IOwinResponse res, AuthenticateResult result)
{
res.StatusCode = 200;
res.ContentType = "text/xml";
var xml = new XElement("xml");
if (result != null && result.Identity != null)
{
xml.Add(result.Identity.Claims.Select(claim => new XElement("claim", new XAttribute("type", claim.Type), new XAttribute("value", claim.Value))));
}
if (result != null && result.Properties != null)
{
xml.Add(result.Properties.Dictionary.Select(extra => new XElement("extra", new XAttribute("type", extra.Key), new XAttribute("value", extra.Value))));
}
using (var memory = new MemoryStream())
{
using (var writer = new XmlTextWriter(memory, Encoding.UTF8))
{
xml.WriteTo(writer);
}
res.Body.Write(memory.ToArray(), 0, memory.ToArray().Length);
}
}
private static async Task<Transaction> SendAsync(TestServer server, string uri, IList<string> cookieHeaders = null, bool ajaxRequest = false)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (cookieHeaders != null)
{
request.Headers.Add("Cookie", cookieHeaders);
}
if (ajaxRequest)
{
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
}
var transaction = new Transaction
{
Request = request,
Response = await server.HttpClient.SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
if (transaction.SetCookie != null && transaction.SetCookie.Any())
{
transaction.CookieNameValue = transaction.SetCookie.First().Split(new[] { ';' }, 2).First();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
if (transaction.Response.Content != null &&
transaction.Response.Content.Headers.ContentType != null &&
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
{
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
}
return transaction;
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string CookieNameValue { get; set; }
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
}
}
}