65 lines
2.6 KiB
C#
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);
|
|
}
|
|
}
|