Base solution for your next web application
Open Closed

CircularDependencyException on OpenIdConnectOptions after upgrading to Abp.AspNetZeroCore 6.0 (Castle.Windsor.MsDependencyInjection 5.0.0) with Microsoft.Identity.Web #12668


User avatar
0
ShareVision created

Summary

After a NuGet upgrade — Abp.* 11.2.0 → 11.3.0 and Abp.AspNetZeroCore(.Web) 5.1.0 → 6.0.0 — the app throws Castle.MicroKernel.CircularDependencyException while resolving the OpenID Connect authentication handler's options. It happens on every request, so every page returns HTTP 500.

We use Microsoft.Identity.Web for a Microsoft Graph integration (calendar / documents), registered in Startup.ConfigureServices:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(options => { _appConfiguration.Bind("AzureAd", options); options.Events ??= new OpenIdConnectEvents(); options.Events.OnTokenValidated += OnTokenValidatedFunc; }) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(_appConfiguration.GetSection("DownstreamApi")) .AddIntegratedUserTokenCache();

Exception

Castle.MicroKernel.CircularDependencyException: Dependency cycle has been detected when trying to resolve component 'Microsoft.Extensions.Options.IConfigureOptions`1[[Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions, ...]]'. The resolution tree that resulted in the cycle is the following: Component 'IConfigureOptions

Thrown from AuthenticationMiddleware.Invoke → IAuthenticationHandlerProvider.GetHandlerAsync. Because OpenIdConnectHandler is an IAuthenticationRequestHandler, the auth middleware resolves it on every request (to check for its /signin-oidc callback), so this isn't tied to the default scheme.

The single package that flips the behaviour is Castle.Windsor.MsDependencyInjection:

| Version | Comes with | Result | | --- | --- | --- | | 4.1.0 | Abp.* 11.2.0 / AspNetZeroCore 5.1.0 | ✅ works | | 5.0.0| Abp.* 11.3.0 / AspNetZeroCore 6.0.0 | ❌ cycles | Updating every other package to the new versions but keeping Abp/AspNetZeroCore at 11.2.0 / 5.1.0 (which pins Castle.Windsor.MsDependencyInjection to 4.1.0) makes it run again.

Already ruled out (all verified by running):

Microsoft.Identity.Web version — cycles on 4.9.0, 4.11.0 and 4.12.0. Microsoft.AspNetCore.Authentication.OpenIdConnect — cycles on both 10.0.7 and 10.0.9. Microsoft.IdentityModel.* (8.18 vs 8.19). Removing OIDC as the default scheme (AddAuthentication() with no scheme) — still cycles (handler is resolved per request as an IAuthenticationRequestHandler). Replacing Castle's default PropertiesDependenciesModelInspector with AbpPropertiesDependenciesModelInspector — no effect; this is a constructor-level cycle, not property injection. Note: Microsoft.Identity.Web works fine in a plain ASP.NET Core app (native MS DI). The cycle only appears once ABP bridges the options components into Castle Windsor via Castle.Windsor.MsDependencyInjection, and only with the 5.0.0 bridge.

Is there a supported way to use Microsoft.Identity.Web (AddMicrosoftIdentityWebApp + token acquisition for Microsoft Graph) with ASP.NET Zero on the 6.0 / Castle.Windsor.MsDependencyInjection 5.0.0 stack — or a known fix / recommended registration to avoid the OpenIdConnectOptions resolution cycle under Windsor? We've stayed on Abp 11.2.0 / AspNetZeroCore 5.1.0 to keep the feature working, but we'd like to finish the upgrade.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

6 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ShareVision

    Thank you for the detailed investigation and for isolating the failing package.

    Based on your findings, this does not look like a Microsoft.Identity.Web version issue or an OpenIdConnect package issue. The important signal is that the same Microsoft.Identity.Web registration works with the previous ASP.NET Zero / ABP package set and starts failing only when the dependency bridge changes to Castle.Windsor.MsDependencyInjection 5.0.0.

    ASP.NET Zero / ASP.NET Boilerplate uses Castle Windsor as the main IoC container and bridges ASP.NET Core service registrations through Castle.Windsor.MsDependencyInjection. Microsoft.Identity.Web registers several authentication/options services around OpenIdConnectOptions, token acquisition and Graph integration. In this case, Windsor appears to be resolving the options chain differently from the native Microsoft DI container, which results in a constructor-level circular dependency while resolving IConfigureOptions<OpenIdConnectOptions>.

    The practical options are:

    1. Keep the previous ABP / ASP.NET Zero package set for now if this Microsoft Graph integration is production-critical.

    2. Avoid registering the full Microsoft.Identity.Web OIDC handler chain through the Windsor bridge, and instead implement the Microsoft Graph integration more explicitly, for example by using MSAL / Graph client registration separately from the ASP.NET Zero authentication pipeline.

    3. If you want to continue testing the upgrade, please share a minimal reproducible project or the full Castle resolution tree. We can then check whether the cycle is caused by a specific Microsoft.Identity.Web options registration and whether it can be excluded, replaced, or registered differently. You can send your project to [email protected] if you wish. This will allow us to test it faster and provide a more specific solution.

    We would not recommend relying on package downgrades or forced transitive dependency overrides as a long-term fix unless the full application is regression-tested, because the newer ASP.NET Zero / ABP package set is expected to run with its corresponding dependency graph.

    For now, this looks like a compatibility issue between Microsoft.Identity.Web’s options registration model and the Castle Windsor MS DI adapter behavior in 5.0.0. We need to reproduce it on our side and evaluate whether it should be fixed in the adapter layer or documented with a supported workaround.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ShareVision created

    I emailed support a minimal reproducible project and the full Castle resolution tree.

    thanks

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ShareVision

    Thank you for sharing your project and question in detail. We will review it thoroughly and provide feedback through this ticket regarding the solution steps.

    Best Regards

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ShareVision

    Thanks again for the minimal repro and the full resolution tree. We reproduced the issue and confirmed your finding: the failure is in Castle.Windsor.MsDependencyInjection 5.0.0, not in ASP.NET Zero registration code, ABP interception, Microsoft.Identity.Web versioning, or the selected authentication scheme.

    The regression is caused by the collection resolution changes added in adapter 5.0.0 for .NET keyed-service support. In 5.0.0, non-keyed IEnumerable<T> dependencies are also resolved through a manual handler-enumeration path. With Microsoft.Identity.Web's factory-based IConfigureOptions<OpenIdConnectOptions> registrations, that path re-enters the ASP.NET Core options monitor/factory graph and Castle reports a circular dependency.

    We have prepared a patched adapter build for you to test:

    Castle.Windsor.MsDependencyInjection.5.0.1-miwfix.1.nupkg

    This build keeps the new keyed-service behavior, but preserves the previous Windsor collection resolution path when the collection contains no keyed handlers. We validated it against your minimal repro and also against the UseCastleWindsor / WindsorServiceProviderFactory startup path used by the newer ASP.NET Zero template. In both cases, IOptionsMonitor<OpenIdConnectOptions>.Get(...) resolves successfully with the patched package.

    To test it in your application:

    1. Add the attached .nupkg to a local/package source accessible by your build.
    2. Add or update the direct package reference so the application resolves this build:
    <PackageReference Include="Castle.Windsor.MsDependencyInjection" Version="5.0.1-miwfix.1" />
    

    If your solution does not currently reference this package directly, add the reference to the executable web project(s) that host the ASP.NET Zero application, for example the MVC host and/or API host. If you already pin Castle.Windsor.MsDependencyInjection elsewhere, update that reference instead.

    Then restore without using stale cache and verify the resolved version:

    dotnet restore --no-cache
    dotnet list package --include-transitive
    

    After that, run the application with the ABP 11.3 / Abp.AspNetZeroCore.Web 6.0 package set and your normal Microsoft.Identity.Web / Graph registration.

    Please treat this package as a validation build, not the final public NuGet release. If it resolves the issue in the full ShareVision application, we will move the same fix into the official adapter package flow and align the ASP.NET Zero package set accordingly.

    Castle.Windsor.MsDependencyInjection.5.0.1-miwfix.1.nupkg

    Best regards

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ShareVision created

    I tested it against our full solution and it resolves the issue.

    thanks

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ShareVision

    Thank you for verifying. We're glad this fix resolved your issue.

    Thank you for your feedback.

    We will address this issue when we release a new Castle.Windsor.MsDependencyInjection.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)