Heimdall sign-in: pin the public base URL path, the nonce shape and the Discord role requirement; drop a redundant key re-check
The key lookup's second cache check after taking the gate changed nothing the refetch throttle did not already decide, so it is removed. Mutation testing of the diff found the three behaviours above unpinned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ad06e2ffd5
commit
f5432f7a42
3 changed files with 44 additions and 7 deletions
|
|
@ -643,6 +643,32 @@ public sealed class HeimdallCompletionTests
|
|||
Assert.Null(host.Heimdall.StartSecrets[0]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("https://localhost", "https://localhost/auth/heimdall/complete?attempt=")]
|
||||
[InlineData("https://localhost/", "https://localhost/auth/heimdall/complete?attempt=")]
|
||||
[InlineData("https://localhost/sub", "https://localhost/sub/auth/heimdall/complete?attempt=")]
|
||||
[InlineData("https://localhost/sub/", "https://localhost/sub/auth/heimdall/complete?attempt=")]
|
||||
public async Task The_return_target_Heimdall_gets_is_under_the_public_base_url(string publicBaseUrl, string prefix)
|
||||
{
|
||||
using var host = new HeimdallHost(publicBaseUrl: publicBaseUrl);
|
||||
var attempt = await host.StartAsync();
|
||||
|
||||
Assert.Equal(prefix + attempt.Nonce, attempt.ReturnTo);
|
||||
Assert.True((await Genuine(host, attempt, HeimdallShapes.NewAccountId())).SignedIn);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_member_start_with_no_allowed_discord_roles_is_refused_before_Heimdall_is_called()
|
||||
{
|
||||
using var host = new HeimdallHost(discordRoles: false);
|
||||
|
||||
var member = await host.StartAsync(member: true);
|
||||
|
||||
Assert.Equal(ErrorRedirect, member.Response.Headers.Location!.OriginalString);
|
||||
Assert.Empty(host.Heimdall.StartBodies);
|
||||
Assert.NotNull((await host.StartAsync()).Cookie);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Every_completion_refusal_looks_the_same()
|
||||
{
|
||||
|
|
@ -674,6 +700,9 @@ public sealed class HeimdallCompletionTests
|
|||
"Heimdall did not grant Bifrost member access.")
|
||||
};
|
||||
|
||||
var illFormed = await host.CompleteAsync(new string('A', 42) + "!", "code", "x");
|
||||
results.Add(("ill-formed nonce", illFormed, "Heimdall completion has no attempt for this browser."));
|
||||
|
||||
using var client = host.NewClient();
|
||||
using var json = await client.PostAsync(
|
||||
"/auth/heimdall/complete",
|
||||
|
|
@ -694,6 +723,7 @@ public sealed class HeimdallCompletionTests
|
|||
}
|
||||
|
||||
Assert.Null(await host.Account(accountId));
|
||||
Assert.False(illFormed.Response.Headers.Contains("Set-Cookie"));
|
||||
|
||||
foreach (var url in new[] { "/auth/heimdall/bogus", "/auth/heimdall/twitch?access=member" })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -348,6 +348,8 @@ public sealed class HeimdallHost : TestWebApplicationFactory
|
|||
|
||||
private readonly string _appSecret;
|
||||
private readonly string _baseUrl;
|
||||
private readonly string _publicBaseUrl;
|
||||
private readonly bool _discordRoles;
|
||||
|
||||
public TestClock Clock { get; } = new();
|
||||
|
||||
|
|
@ -357,10 +359,16 @@ public sealed class HeimdallHost : TestWebApplicationFactory
|
|||
|
||||
public HeimdallKey Key { get; } = HeimdallKey.Generate();
|
||||
|
||||
public HeimdallHost(string appSecret = AppSecret, string baseUrl = HeimdallShapes.Issuer)
|
||||
public HeimdallHost(
|
||||
string appSecret = AppSecret,
|
||||
string baseUrl = HeimdallShapes.Issuer,
|
||||
string publicBaseUrl = "https://localhost",
|
||||
bool discordRoles = true)
|
||||
{
|
||||
_appSecret = appSecret;
|
||||
_baseUrl = baseUrl;
|
||||
_publicBaseUrl = publicBaseUrl;
|
||||
_discordRoles = discordRoles;
|
||||
Heimdall.Published.Add(Key);
|
||||
Heimdall.RequiredAppSecret = AppSecret;
|
||||
}
|
||||
|
|
@ -378,8 +386,12 @@ public sealed class HeimdallHost : TestWebApplicationFactory
|
|||
["Heimdall:BaseUrl"] = _baseUrl,
|
||||
["Heimdall:AppSecret"] = _appSecret,
|
||||
["Heimdall:DiscordGuildId"] = "guild-1",
|
||||
["Heimdall:DiscordAllowedRoleIds:0"] = "role-1"
|
||||
["Host:PublicBaseUrl"] = _publicBaseUrl
|
||||
});
|
||||
if (_discordRoles)
|
||||
{
|
||||
configuration.AddInMemoryCollection(new Dictionary<string, string?> { ["Heimdall:DiscordAllowedRoleIds:0"] = "role-1" });
|
||||
}
|
||||
});
|
||||
builder.ConfigureLogging(logging => logging.AddProvider(Logs));
|
||||
builder.ConfigureServices(services =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue