Skip to content

Commit

Permalink
Merge pull request #1690 from DuendeSoftware/7.1.0-httpcontext-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
josephdecock authored Jan 5, 2025
2 parents 5c68cf3 + 2f0596a commit 1756170
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class PostConfigureApplicationCookieTicketStore : IPostConfigureOptions<C
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly string _scheme;
private readonly LicenseUsageTracker _licenseUsage;
private readonly ILogger<PostConfigureApplicationCookieTicketStore> _logger;

/// <summary>
Expand All @@ -38,7 +37,6 @@ public PostConfigureApplicationCookieTicketStore(
ILogger<PostConfigureApplicationCookieTicketStore> logger)
{
_httpContextAccessor = httpContextAccessor;
_licenseUsage = httpContextAccessor.HttpContext?.RequestServices.GetRequiredService<LicenseUsageTracker>();
_logger = logger;

_scheme = identityServerOptions.Authentication.CookieAuthenticationScheme ??
Expand Down Expand Up @@ -69,7 +67,8 @@ public void PostConfigure(string name, CookieAuthenticationOptions options)
}

IdentityServerLicenseValidator.Instance.ValidateServerSideSessions();
_licenseUsage.FeatureUsed(LicenseFeature.ServerSideSessions);
var licenseUsage = _httpContextAccessor.HttpContext?.RequestServices.GetRequiredService<LicenseUsageTracker>();
licenseUsage.FeatureUsed(LicenseFeature.ServerSideSessions);

var sessionStore = _httpContextAccessor.HttpContext!.RequestServices.GetService<IServerSideSessionStore>();
if (sessionStore is InMemoryServerSideSessionStore)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See LICENSE in the project root for license information.


using System;
using Duende.IdentityServer;
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.Models;
Expand All @@ -24,7 +25,8 @@ public MockHttpContextAccessor(
IdentityServerOptions options = null,
IUserSession userSession = null,
IMessageStore<LogoutNotificationContext> endSessionStore = null,
IServerUrls urls = null)
IServerUrls urls = null,
Action<ServiceCollection> configureServices = null)
{
options = options ?? TestIdentityServerOptions.Create();

Expand Down Expand Up @@ -63,6 +65,11 @@ public MockHttpContextAccessor(
services.AddSingleton<IServerUrls>(urls);
}

if (configureServices != null)
{
configureServices(services);
}

_context.RequestServices = services.BuildServiceProvider();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.Licensing.V2;
using FluentAssertions;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using UnitTests.Common;
using Xunit;

namespace UnitTests.Configuration.DependencyInjection;

public class PostConfigureApplicationCookieTicketStoreTests
{

[Fact]
public void can_be_constructed_without_httpcontext_and_used_later_with_httpcontext()
{
// Register the dependencies of the usage tracker so that we can resolve it in PostConfigure
var httpContextAccessor = new MockHttpContextAccessor(configureServices: sp =>
{
sp.AddSingleton(TestLogger.Create<LicenseAccessor>());
sp.AddSingleton<LicenseAccessor>();
sp.AddSingleton<LicenseUsageTracker>();
});

// The mock http context accessor has a convenient HttpContext, but
// initially we simulate not having it by stashing it away and setting
// the accessor's context to null.
var savedContext = httpContextAccessor.HttpContext;
httpContextAccessor.HttpContext = null;

var sut = new PostConfigureApplicationCookieTicketStore(
httpContextAccessor,
new IdentityServerOptions
{
Authentication = new AuthenticationOptions
{
// This is needed so that we operate on the correct scheme
CookieAuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme
}
},
Options.Create<Microsoft.AspNetCore.Authentication.AuthenticationOptions>(new()),
TestLogger.Create<PostConfigureApplicationCookieTicketStore>()
);

// Now that we've constructed, we can bring back the http context and run PostConfigure
httpContextAccessor.HttpContext = savedContext;
var cookieOpts = new CookieAuthenticationOptions();
sut.PostConfigure(CookieAuthenticationDefaults.AuthenticationScheme, cookieOpts);

cookieOpts.SessionStore.Should().BeOfType<TicketStoreShim>();
}
}

0 comments on commit 1756170

Please sign in to comment.