Files
VolcanicCore/tests/VolcanicCore.Tests/ForwardedHeadersTests.cs

65 lines
2.6 KiB
C#

using System.Net;
using System.Net.Http.Json;
using Xunit;
namespace VolcanicCore.Tests;
public class ForwardedHeadersTests : IClassFixture<WebFactory>
{
private readonly WebFactory _f;
public ForwardedHeadersTests(WebFactory f) { _f = f; }
[Fact]
public async Task Login_with_XForwardedProto_https_returns_Secure_cookie()
{
// AllowAutoRedirect false so we can inspect the raw Set-Cookie header.
var client = _f.CreateClient(new Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});
// Simulate Traefik terminating TLS: it forwards over plain HTTP with the
// scheme and client IP in headers.
client.DefaultRequestHeaders.Add("X-Forwarded-Proto", "https");
client.DefaultRequestHeaders.Add("X-Forwarded-For", "203.0.113.7");
var req = new HttpRequestMessage(HttpMethod.Post, "/api/session")
{
Content = JsonContent.Create(new { password = _f.AdminPassword }),
};
var res = await client.SendAsync(req);
Assert.Equal(HttpStatusCode.NoContent, res.StatusCode);
// Cookie should be marked Secure because the middleware saw https.
var setCookies = res.Headers.GetValues("Set-Cookie").ToList();
var sid = setCookies.FirstOrDefault(c => c.StartsWith("volcaniccore.sid=", StringComparison.Ordinal));
Assert.NotNull(sid);
Assert.Contains("secure", sid!, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task Login_without_XForwardedProto_returns_cookie_without_Secure()
{
// Same request WITHOUT the forwarded header — Request.Scheme stays http,
// so CookieSecurePolicy.SameAsRequest omits the Secure flag. This proves
// the middleware is doing the work; without it the "https" test above
// would still pass because both requests would look like http.
var client = _f.CreateClient(new Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});
var req = new HttpRequestMessage(HttpMethod.Post, "/api/session")
{
Content = JsonContent.Create(new { password = _f.AdminPassword }),
};
var res = await client.SendAsync(req);
Assert.Equal(HttpStatusCode.NoContent, res.StatusCode);
var setCookies = res.Headers.GetValues("Set-Cookie").ToList();
var sid = setCookies.FirstOrDefault(c => c.StartsWith("volcaniccore.sid=", StringComparison.Ordinal));
Assert.NotNull(sid);
Assert.DoesNotContain("secure", sid!, StringComparison.OrdinalIgnoreCase);
}
}