Skip to content

Commit

Permalink
Add test coverage for ServerSideTokenStore
Browse files Browse the repository at this point in the history
  • Loading branch information
josephdecock committed Aug 28, 2024
1 parent fa5d101 commit 1b7dbac
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="Shouldly" Version="4.2.1" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
Expand All @@ -20,4 +22,8 @@
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Duende.Bff.Blazor\Duende.Bff.Blazor.csproj" />
</ItemGroup>

</Project>
84 changes: 84 additions & 0 deletions test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Security.Claims;
using Duende.AccessTokenManagement.OpenIdConnect;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NSubstitute;
using Shouldly;

namespace Duende.Bff.Blazor.UnitTests;

public class ServerSideTokenStoreTests
{
private ClaimsPrincipal CreatePrincipal(string sub, string sid)
{
return new ClaimsPrincipal(new ClaimsIdentity([
new Claim("sub", sub),
new Claim("sid", sid)
], "pwd", "name", "role"));
}

[Fact]
public async Task Can_add_retrieve_and_remove_tokens()
{
var user = CreatePrincipal("sub", "sid");
var props = new AuthenticationProperties();
var expectedToken = new UserToken()
{
AccessToken = "expected-access-token"
};

// Create shared dependencies
var sessionStore = new InMemoryUserSessionStore();
var dataProtection = new EphemeralDataProtectionProvider();

// Use the ticket store to save the user's initial session
// Note that we don't yet have tokens in the session
var sessionService = new ServerSideTicketStore(sessionStore, dataProtection, Substitute.For<ILogger<ServerSideTicketStore>>());
sessionService.StoreAsync(new AuthenticationTicket(

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / macOS-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / macOS-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / ubuntu-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / ubuntu-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 40 in test/Duende.Bff.Blazor.UnitTests/ServerSideTokenStoreTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
user,
props,
"test"
));

var tokensInProps = MockStoreTokensInAuthProps();
var sut = new ServerSideTokenStore(
tokensInProps,
sessionStore,
dataProtection,
Substitute.For<ILogger<ServerSideTokenStore>>());

await sut.StoreTokenAsync(user, expectedToken);
var actualToken = await sut.GetTokenAsync(user);

actualToken.ShouldNotBe(null);
actualToken.AccessToken.ShouldBe(expectedToken.AccessToken);

await sut.ClearTokenAsync(user);

var resultAfterClearing = await sut.GetTokenAsync(user);
resultAfterClearing.AccessToken.ShouldBeNull();
}

private static StoreTokensInAuthenticationProperties MockStoreTokensInAuthProps()
{
var tokenManagementOptionsMonitor = Substitute.For<IOptionsMonitor<UserTokenManagementOptions>>();
var tokenManagementOptions = new UserTokenManagementOptions { UseChallengeSchemeScopedTokens = false };
tokenManagementOptionsMonitor.CurrentValue.Returns(tokenManagementOptions);

var cookieOptionsMonitor = Substitute.For<IOptionsMonitor<CookieAuthenticationOptions>>();
var cookieAuthenticationOptions = new CookieAuthenticationOptions();
cookieOptionsMonitor.CurrentValue.Returns(cookieAuthenticationOptions);

var schemeProvider = Substitute.For<IAuthenticationSchemeProvider>();
schemeProvider.GetDefaultSignInSchemeAsync().Returns(new AuthenticationScheme("TestScheme", null, typeof(IAuthenticationHandler)));

return new StoreTokensInAuthenticationProperties(
tokenManagementOptionsMonitor,
cookieOptionsMonitor,
schemeProvider,
Substitute.For<ILogger<StoreTokensInAuthenticationProperties>>());
}
}

0 comments on commit 1b7dbac

Please sign in to comment.