Browse Source

Add unit and integration tests for CIMD support

Add a new OpenIddict.Server.SystemNetHttp.Tests project with 23 unit tests
covering the CIMD application manager, context, and handler filter. Add 8
integration tests in the base server integration tests for ValidateClientId
CIMD branching and discovery metadata advertisement.
pull/2416/head
Thor Arne Johansen 6 days ago
parent
commit
a40673a4ae
  1. 1
      OpenIddict.slnx
  2. 250
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Cimd.cs
  3. 28
      test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddict.Server.SystemNetHttp.Tests.csproj
  4. 468
      test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpApplicationManagerTests.cs
  5. 45
      test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpCimdContextTests.cs
  6. 64
      test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpHandlerFilterTests.cs

1
OpenIddict.slnx

@ -97,6 +97,7 @@
<Project Path="test/OpenIddict.Server.DataProtection.Tests/OpenIddict.Server.DataProtection.Tests.csproj" />
<Project Path="test/OpenIddict.Server.IntegrationTests/OpenIddict.Server.IntegrationTests.csproj" />
<Project Path="test/OpenIddict.Server.Owin.IntegrationTests/OpenIddict.Server.Owin.IntegrationTests.csproj" />
<Project Path="test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddict.Server.SystemNetHttp.Tests.csproj" />
<Project Path="test/OpenIddict.Server.Tests/OpenIddict.Server.Tests.csproj" />
<Project Path="test/OpenIddict.Validation.AspNetCore.IntegrationTests/OpenIddict.Validation.AspNetCore.IntegrationTests.csproj" />
<Project Path="test/OpenIddict.Validation.IntegrationTests/OpenIddict.Validation.IntegrationTests.csproj" />

250
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Cimd.cs

@ -0,0 +1,250 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlers;
namespace OpenIddict.Server.IntegrationTests;
public abstract partial class OpenIddictServerIntegrationTests
{
[Fact]
public async Task HandleConfigurationRequest_AdvertisesCimdSupport_WhenEnabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.GetAsync("/.well-known/openid-configuration");
// Assert
Assert.True((bool?) response[Metadata.ClientIdMetadataDocumentSupported]);
}
[Fact]
public async Task HandleConfigurationRequest_DoesNotAdvertiseCimdSupport_WhenDisabled()
{
// Arrange
await using var server = await CreateServerAsync();
await using var client = await server.CreateClientAsync();
// Act
var response = await client.GetAsync("/.well-known/openid-configuration");
// Assert
Assert.Null(response[Metadata.ClientIdMetadataDocumentSupported]);
}
[Fact]
public async Task ValidateAuthorizationRequest_RejectsUrlClientId_WhenCimdDisabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "https://example.com/client",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert — CIMD is disabled, so URL client_id is just treated as unknown client
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
}
[Fact]
public async Task ValidateAuthorizationRequest_SetsTransactionFlag_WhenCimdEnabledAndClientIdIsHttpsUrl()
{
// Arrange
var flagWasSet = false;
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
// Add an inline handler that runs after ValidateClientId to inspect the transaction flag.
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
if (context.Transaction.Properties.TryGetValue(
".ClientIdMetadataDocumentFetchRequired", out var value) &&
value is true)
{
flagWasSet = true;
}
// Reject to stop further processing (we don't have CIMD HTTP infrastructure here).
context.Reject(
error: Errors.InvalidClient,
description: "Test completed.");
return ValueTask.CompletedTask;
});
builder.SetOrder(ValidateClientId.Descriptor.Order + 1);
});
});
await using var client = await server.CreateClientAsync();
// Act
await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "https://example.com/client",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert
Assert.True(flagWasSet);
}
[Fact]
public async Task ValidateAuthorizationRequest_RejectsHttpUrl_WhenCimdEnabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("http://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "http://example.com/client",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert — HTTP URL should be rejected even with CIMD enabled (requires HTTPS)
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
}
[Fact]
public async Task ValidateAuthorizationRequest_RejectsUrlWithFragment_WhenCimdEnabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("https://example.com/client#fragment", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "https://example.com/client#fragment",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert — URL with fragment should be rejected
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
}
[Fact]
public async Task ValidateAuthorizationRequest_RejectsUrlWithUserInfo_WhenCimdEnabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("https://user:pass@example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "https://user:pass@example.com/client",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert — URL with userinfo should be rejected
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
}
[Fact]
public async Task ValidateAuthorizationRequest_RejectsRootPathUrl_WhenCimdEnabled()
{
// Arrange
await using var server = await CreateServerAsync(options =>
{
options.EnableClientIdMetadataDocumentSupport();
options.Services.AddSingleton(CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("https://example.com/", It.IsAny<CancellationToken>()))
.ReturnsAsync((OpenIddictApplication?) null);
}));
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "https://example.com/",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert — Root path URL should be rejected
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
}
}

28
test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddict.Server.SystemNetHttp.Tests.csproj

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net48;$(NetCoreTargetFrameworks)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MartinCostello.Logging.XUnit" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Moq" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenIddict.Core\OpenIddict.Core.csproj" />
<ProjectReference Include="..\..\src\OpenIddict.Server.SystemNetHttp\OpenIddict.Server.SystemNetHttp.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' ">
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Using Include="OpenIddict.Abstractions" />
<Using Include="OpenIddict.Abstractions.OpenIddictConstants" Static="true" />
<Using Include="OpenIddict.Abstractions.OpenIddictResources" Alias="SR" />
</ItemGroup>
</Project>

468
test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpApplicationManagerTests.cs

@ -0,0 +1,468 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System.Collections.Immutable;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using OpenIddict.Core;
using OpenIddict.Server.SystemNetHttp;
using Xunit;
namespace OpenIddict.Server.SystemNetHttp.Tests;
public class OpenIddictServerSystemNetHttpApplicationManagerTests
{
[Fact]
public async Task FindByClientIdAsync_ReturnsBaseResult_WhenPreRegisteredClientExists()
{
// Arrange
var application = new TestApplication();
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext();
var manager = CreateManager(store, cimdContext);
// Act
var result = await manager.FindByClientIdAsync("Fabrikam");
// Assert
Assert.Same(application, result);
}
[Fact]
public async Task FindByClientIdAsync_ReturnsNull_WhenNoCimdContext()
{
// Arrange
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((TestApplication?) null);
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext();
var manager = CreateManager(store, cimdContext);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.Null(result);
}
[Fact]
public async Task FindByClientIdAsync_ReturnsNull_WhenCimdClientIdDoesNotMatch()
{
// Arrange
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("https://example.com/client-a", It.IsAny<CancellationToken>()))
.ReturnsAsync((TestApplication?) null);
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext
{
ClientId = "https://example.com/client-b",
MetadataDocument = CreateMetadataDocument()
};
var manager = CreateManager(store, cimdContext);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client-a");
// Assert
Assert.Null(result);
}
[Fact]
public async Task FindByClientIdAsync_SynthesizesVirtualApp_WhenCimdContextPopulated()
{
// Arrange
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((TestApplication?) null);
using var document = CreateMetadataDocument("""
{
"client_id": "https://example.com/client",
"client_name": "Test Client"
}
""");
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext
{
ClientId = "https://example.com/client",
MetadataDocument = document
};
var manager = CreateManager(store, cimdContext);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetClientIdAsync(result, "https://example.com/client", It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_ReturnsCachedVirtualApp_OnSecondCall()
{
// Arrange
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((TestApplication?) null);
using var document = CreateMetadataDocument();
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext
{
ClientId = "https://example.com/client",
MetadataDocument = document
};
var manager = CreateManager(store, cimdContext);
// Act
var first = await manager.FindByClientIdAsync("https://example.com/client");
var second = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(first);
Assert.Same(first, second);
store.Verify(s => s.InstantiateAsync(It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectClientType()
{
// Arrange
var (manager, store, _) = CreateManagerWithCimdContext();
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetClientTypeAsync(result, ClientTypes.Public, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectApplicationType()
{
// Arrange
using var document = CreateMetadataDocument("""
{
"application_type": "native"
}
""");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetApplicationTypeAsync(result, "native", It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_DefaultsToWebApplicationType()
{
// Arrange
using var document = CreateMetadataDocument("{}");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetApplicationTypeAsync(result, ApplicationTypes.Web, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectDisplayName()
{
// Arrange
using var document = CreateMetadataDocument("""
{
"client_name": "My Cool App"
}
""");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetDisplayNameAsync(result, "My Cool App", It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectRedirectUris()
{
// Arrange
using var document = CreateMetadataDocument("""
{
"redirect_uris": ["https://example.com/callback", "https://example.com/callback2"]
}
""");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetRedirectUrisAsync(
result,
It.Is<ImmutableArray<string>>(uris =>
uris.Length == 2 &&
uris[0] == "https://example.com/callback" &&
uris[1] == "https://example.com/callback2"),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectGrantTypePermissions()
{
// Arrange
using var document = CreateMetadataDocument("""
{
"grant_types": ["authorization_code", "refresh_token"]
}
""");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.GrantTypes.AuthorizationCode) &&
perms.Contains(Permissions.GrantTypes.RefreshToken)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_DefaultsToAuthorizationCodeGrant()
{
// Arrange — no grant_types in metadata
using var document = CreateMetadataDocument("{}");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.GrantTypes.AuthorizationCode)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasCorrectResponseTypePermissions()
{
// Arrange
using var document = CreateMetadataDocument("""
{
"response_types": ["code", "code id_token"]
}
""");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.ResponseTypes.Code) &&
perms.Contains(Permissions.ResponseTypes.CodeIdToken)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_DefaultsToCodeResponseType()
{
// Arrange — no response_types in metadata
using var document = CreateMetadataDocument("{}");
var (manager, store, _) = CreateManagerWithCimdContext(document);
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.ResponseTypes.Code)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_RequiresPkce()
{
// Arrange
var (manager, store, _) = CreateManagerWithCimdContext();
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetRequirementsAsync(
result,
It.Is<ImmutableArray<string>>(reqs =>
reqs.Contains(Requirements.Features.ProofKeyForCodeExchange)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task GetIdAsync_ReturnsNull_ForVirtualApplication()
{
// Arrange
var (manager, _, cimdContext) = CreateManagerWithCimdContext();
var virtualApp = await manager.FindByClientIdAsync("https://example.com/client");
Assert.NotNull(virtualApp);
// Act
var id = await manager.GetIdAsync(virtualApp);
// Assert
Assert.Null(id);
}
[Fact]
public async Task GetIdAsync_DelegatesToBase_ForNonVirtualApplication()
{
// Arrange
var regularApp = new TestApplication();
var store = CreateStore();
store.Setup(s => s.GetIdAsync(regularApp, It.IsAny<CancellationToken>()))
.ReturnsAsync("some-id");
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext();
var manager = CreateManager(store, cimdContext);
// Act
var id = await manager.GetIdAsync(regularApp);
// Assert
Assert.Equal("some-id", id);
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasEndpointPermissions()
{
// Arrange
var (manager, store, _) = CreateManagerWithCimdContext();
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.Endpoints.Authorization) &&
perms.Contains(Permissions.Endpoints.Token)),
It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task FindByClientIdAsync_SynthesizedApp_HasScopePermissions()
{
// Arrange
var (manager, store, _) = CreateManagerWithCimdContext();
// Act
var result = await manager.FindByClientIdAsync("https://example.com/client");
// Assert
Assert.NotNull(result);
store.Verify(s => s.SetPermissionsAsync(
result,
It.Is<ImmutableArray<string>>(perms =>
perms.Contains(Permissions.Scopes.Email) &&
perms.Contains(Permissions.Scopes.Profile) &&
perms.Contains(Permissions.Scopes.Address) &&
perms.Contains(Permissions.Scopes.Phone) &&
perms.Contains(Permissions.Scopes.Roles)),
It.IsAny<CancellationToken>()), Times.Once());
}
private static Mock<IOpenIddictApplicationStore<TestApplication>> CreateStore()
{
var store = new Mock<IOpenIddictApplicationStore<TestApplication>>();
store.Setup(s => s.InstantiateAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(() => new TestApplication());
return store;
}
private static OpenIddictServerSystemNetHttpApplicationManager<TestApplication> CreateManager(
Mock<IOpenIddictApplicationStore<TestApplication>> store,
OpenIddictServerSystemNetHttpCimdContext cimdContext)
{
var cache = Mock.Of<IOpenIddictApplicationCache<TestApplication>>();
var logger = NullLogger<OpenIddictApplicationManager<TestApplication>>.Instance;
var coreOptions = new OpenIddictCoreOptions
{
DisableEntityCaching = true,
DisableAdditionalFiltering = true
};
var optionsMonitor = Mock.Of<IOptionsMonitor<OpenIddictCoreOptions>>(
m => m.CurrentValue == coreOptions);
return new OpenIddictServerSystemNetHttpApplicationManager<TestApplication>(
cache, logger, optionsMonitor, store.Object, cimdContext);
}
private static (OpenIddictServerSystemNetHttpApplicationManager<TestApplication> Manager,
Mock<IOpenIddictApplicationStore<TestApplication>> Store,
OpenIddictServerSystemNetHttpCimdContext CimdContext)
CreateManagerWithCimdContext(JsonDocument? document = null)
{
var store = CreateStore();
store.Setup(s => s.FindByClientIdAsync("https://example.com/client", It.IsAny<CancellationToken>()))
.ReturnsAsync((TestApplication?) null);
var cimdContext = new OpenIddictServerSystemNetHttpCimdContext
{
ClientId = "https://example.com/client",
MetadataDocument = document ?? CreateMetadataDocument()
};
var manager = CreateManager(store, cimdContext);
return (manager, store, cimdContext);
}
private static JsonDocument CreateMetadataDocument(string? json = null)
=> JsonDocument.Parse(json ?? """{"client_id": "https://example.com/client"}""");
public class TestApplication { }
}

45
test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpCimdContextTests.cs

@ -0,0 +1,45 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System.Text.Json;
using OpenIddict.Server.SystemNetHttp;
using Xunit;
namespace OpenIddict.Server.SystemNetHttp.Tests;
public class OpenIddictServerSystemNetHttpCimdContextTests
{
[Fact]
public void Properties_DefaultToNull()
{
// Arrange
var context = new OpenIddictServerSystemNetHttpCimdContext();
// Assert
Assert.Null(context.ClientId);
Assert.Null(context.MetadataDocument);
Assert.Null(context.VirtualApplication);
}
[Fact]
public void Properties_CanBeSetAndRead()
{
// Arrange
var context = new OpenIddictServerSystemNetHttpCimdContext();
using var document = JsonDocument.Parse("""{"client_name": "Test"}""");
var virtualApp = new object();
// Act
context.ClientId = "https://example.com/client";
context.MetadataDocument = document;
context.VirtualApplication = virtualApp;
// Assert
Assert.Equal("https://example.com/client", context.ClientId);
Assert.Same(document, context.MetadataDocument);
Assert.Same(virtualApp, context.VirtualApplication);
}
}

64
test/OpenIddict.Server.SystemNetHttp.Tests/OpenIddictServerSystemNetHttpHandlerFilterTests.cs

@ -0,0 +1,64 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using Microsoft.Extensions.Logging;
using Moq;
using OpenIddict.Server.SystemNetHttp;
using Xunit;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.SystemNetHttp.OpenIddictServerSystemNetHttpHandlerFilters;
namespace OpenIddict.Server.SystemNetHttp.Tests;
public class OpenIddictServerSystemNetHttpHandlerFilterTests
{
[Fact]
public async Task IsActiveAsync_ReturnsTrue_WhenCimdEnabled()
{
// Arrange
var filter = new RequireClientIdMetadataDocumentSupportEnabled();
var context = CreateBaseContext(enableCimd: true);
// Act
var result = await filter.IsActiveAsync(context);
// Assert
Assert.True(result);
}
[Fact]
public async Task IsActiveAsync_ReturnsFalse_WhenCimdDisabled()
{
// Arrange
var filter = new RequireClientIdMetadataDocumentSupportEnabled();
var context = CreateBaseContext(enableCimd: false);
// Act
var result = await filter.IsActiveAsync(context);
// Assert
Assert.False(result);
}
private static HandleConfigurationRequestContext CreateBaseContext(bool enableCimd)
{
var options = new OpenIddictServerOptions
{
EnableClientIdMetadataDocumentSupport = enableCimd
};
var transaction = new OpenIddictServerTransaction
{
Options = options,
Logger = Mock.Of<ILogger>()
};
return new HandleConfigurationRequestContext(transaction)
{
Issuer = new Uri("https://localhost/")
};
}
}
Loading…
Cancel
Save