Merge branch 'releases/7.1.x' into main

This commit is contained in:
Joe DeCock 2025-01-08 15:59:53 -06:00
commit ff314622f6
5 changed files with 80 additions and 15 deletions

View file

@ -38,12 +38,19 @@ try
.ConfigureServices()
.ConfigurePipeline();
var usage = app.Services.GetRequiredService<LicenseUsageSummary>();
if (app.Environment.IsDevelopment())
{
app.Lifetime.ApplicationStopping.Register(() =>
{
var usage = app.Services.GetRequiredService<LicenseUsageSummary>();
Console.Write(Summary(usage));
{
Console.ReadKey();
}
});
}
app.Run();
Console.Write(Summary(usage));
Console.ReadKey();
}
catch (Exception ex)
{
@ -55,7 +62,7 @@ finally
Log.CloseAndFlush();
}
string Summary(LicenseUsageSummary usage)
static string Summary(LicenseUsageSummary usage)
{
var sb = new StringBuilder();
sb.AppendLine("IdentityServer Usage Summary:");
@ -67,4 +74,3 @@ string Summary(LicenseUsageSummary usage)
return sb.ToString();
}

View file

@ -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>
@ -38,7 +37,6 @@ public class PostConfigureApplicationCookieTicketStore : IPostConfigureOptions<C
ILogger<PostConfigureApplicationCookieTicketStore> logger)
{
_httpContextAccessor = httpContextAccessor;
_licenseUsage = httpContextAccessor.HttpContext?.RequestServices.GetRequiredService<LicenseUsageTracker>();
_logger = logger;
_scheme = identityServerOptions.Authentication.CookieAuthenticationScheme ??
@ -69,7 +67,8 @@ public class PostConfigureApplicationCookieTicketStore : IPostConfigureOptions<C
}
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)

View file

@ -8,12 +8,12 @@ using System.Collections.Generic;
namespace Duende.IdentityServer.Licensing;
/// <summary>
/// Usage summary for the current license.
/// Usage summary for the current IdentityServer instance intended for auditing purposes.
/// </summary>
/// <param name="LicenseEdition"></param>
/// <param name="ClientsUsed"></param>
/// <param name="IssuersUsed"></param>
/// <param name="FeaturesUsed"></param>
/// <param name="LicenseEdition">License edition retrieved from license key.</param>
/// <param name="ClientsUsed">Clients used in the current IdentityServer instance.</param>
/// <param name="IssuersUsed">Issuers used in the current IdentityServer instance.</param>
/// <param name="FeaturesUsed">Features used in the current IdentityServer instance.</param>
public record LicenseUsageSummary(
string LicenseEdition,
IReadOnlyCollection<string> ClientsUsed,

View file

@ -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;
@ -24,7 +25,8 @@ internal class MockHttpContextAccessor : IHttpContextAccessor
IdentityServerOptions options = null,
IUserSession userSession = null,
IMessageStore<LogoutNotificationContext> endSessionStore = null,
IServerUrls urls = null)
IServerUrls urls = null,
Action<ServiceCollection> configureServices = null)
{
options = options ?? TestIdentityServerOptions.Create();
@ -63,6 +65,11 @@ internal class MockHttpContextAccessor : IHttpContextAccessor
services.AddSingleton<IServerUrls>(urls);
}
if (configureServices != null)
{
configureServices(services);
}
_context.RequestServices = services.BuildServiceProvider();
}

View file

@ -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>();
}
}