GCN-B-7072e626c679

GCN-B-7072e626c679: Failed to start GoCloudNative.BFF. Registering the same options type is not supported.

GCN-B-66b217e55cd6

GCN-G-66b217e55cd6: Failed to start GoCloudNative.BFF. Registering multiple identity providers of the same type is not supported.

The GoCloudNative.Authentication.BFF is built with extensibility in mind. We offer standard implementations for common identity providers. But we also want to allow integration with other identity providers.

Integrating with identityproviders is done by implementing the IIdentityProvider interface and registring it. To register it, you must provide a unique configuration object. This object is meant for configuration values and must be of a unique type per implementation of IIdentityProvider.

How to reproduce the error

To reproduce the error, there there need to be at least two implementations of the IIdentityProvider interface which are registered with the same configuration object.

Example:

The IIdentityProvider implementations:

public class FooIdentityProvider : IIdentityProvider
{
    // ...
}

public class BarIdentityProvider : IIdentityProvider
{
    // ...
}

public FooConfig 
{
    // ...
}

The exception is raised in program.cs:

var builder = WebApplication.CreateBuilder(args);

var config1 = builder.Configuration
    .GetSection("Foo")
    .Get<FooConfig>();

var config2 = builder.Configuration
    .GetSection("Bar")
    .Get<FooConfig>();

builder.Services.AddSecurityBff(o =>
{
    o.RegisterIdentityProvider<FooIdentityProvider, FooConfig>(config1, "foo");

    o.RegisterIdentityProvider<BarIdentityProvider, FooConfig>(config2, "bar"); 
    // This causes the error. You cannot use a config of the same type for
    // two different types of identity providers.
}

Another way to cause the issue is by configuring one of GoCloudNative.Authentication.Bff’s identity providers and use the config of it for your custom identity provider. For example:

var builder = WebApplication.CreateBuilder(args);

var config1 = builder.Configuration
    .GetSection("Foo")
    .Get<OpenIdConnectConfig>();

builder.Services.AddSecurityBff(o =>
{
    o.ConfigureOpenIdConnect(builder.Configuration.GetSection("Oidc"));

    o.RegisterIdentityProvider<FooIdentityProvider, OpenIdConnectConfig>(config1, "foo");
    // This causes the error. You are registering a config of type `OpenIdConnectConfig` 
    // here for the second time. This is not supported
}

Solution

Create a dedicated config class for every custom IIdentityProvider. Like so:

The IIdentityProvider implementations:

public class FooIdentityProvider : IIdentityProvider
{
    // ...
}

public FooConfig 
{
    // ...
}

public class BarIdentityProvider : IIdentityProvider
{
    // ...
}

public BarConfig 
{
    // ...
}

The program.cs:

var builder = WebApplication.CreateBuilder(args);

var config1 = builder.Configuration
    .GetSection("Foo")
    .Get<FooConfig>();

var config2 = builder.Configuration
    .GetSection("Bar")
    .Get<BarConfig>();

builder.Services.AddSecurityBff(o =>
{
    o.RegisterIdentityProvider<FooIdentityProvider, FooConfig>(config1, "foo");
    o.RegisterIdentityProvider<BarIdentityProvider, BarConfig>(config2, "bar"); 
}