IdentityModel / IdentityModel.AspNetCore.OAuth2Introspection

ASP.NET Core authentication handler for OAuth 2.0 token introspection
Apache License 2.0
147 stars 66 forks source link

fix: fix PostConfigureOAuth2IntrospectionOptions with named options #166

Open NatMarchand opened 2 years ago

NatMarchand commented 2 years ago

Hi there! We are currently encountering a weird issue described as follow: Given I bind OAuth2IntrospectionOptions with an IConfiguration section and using a IOptionsMonitor somewhere When a configuration provider triggers a reload Then an exception occurs in the PostConfigureOAuth2IntrospectionOptions because dotnet tries to PostConfigure an unnamed options instance (which is of course not configured) and the message is "You must either set Authority or IntrospectionEndpoint"

Here's my repro (on LinqPad):

async Task Main()
{
    var configurationProvider = new MyConfigurationProvider();
    var builder = WebApplication.CreateBuilder();
    ((IConfigurationBuilder)builder.Configuration).Add(configurationProvider);
    builder.Services
        .AddAuthentication()
        .AddOAuth2Introspection();

    builder.Services
        .AddOptions<OAuth2IntrospectionOptions>(OAuth2IntrospectionDefaults.AuthenticationScheme)
        .BindConfiguration("IdentityServer");

    var app = builder.Build();

    var monitor = app.Services.GetRequiredService<IOptionsMonitor<OAuth2IntrospectionOptions>>();
    monitor.Get("Bearer").Dump();

    configurationProvider.NotifyReload(); // <-- exception occurs here
}

public class MyConfigurationProvider : ConfigurationProvider, IConfigurationSource
{
    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return this;
    }

    public override void Load()
    {
        this.Data.Clear();
        this.Data.Add("IdentityServer:Authority", "http://dummy");
    }

    public void NotifyReload()
    {
        this.OnReload();
    }
}

My PR fixes this behavior by registering a named PostConfigureOAuth2IntrospectionOptions.

NatMarchand commented 1 year ago

Hello there ! Is there anything I can do to help you about this MR ? :)

brockallen commented 1 year ago

Are you seeing this under .NET 6 or .NET Core 3.1?

NatMarchand commented 1 year ago

The code above was tested on LinqPad with dotnet 7 but we also have issues with our apps running on dotnet 6

brockallen commented 1 year ago

I'd like to understand better why it's invoked without a name/scheme only when the source reloads, as opposed to normal startup (first time). Can you find out?