Hello,
We have the need to dynamically load authentication providers upon request and we wonder how we should do it in the best possible way.
Our scenario is a bit weird because of some legacy third party systems but I´ll try to explain it:
- Our api acts as a component in our legacy system
- Our legacy system authenticates users using OpenId
- Our legacy system is basically a separate cluster per customer (and thus a separate identity provider per customer)
Our new system holds configuration on which of these legacy identityproviders it trusts. So this is a dynamically changing list (we add and remove trusted tenants).
We have tried to get the following to work:
- When a request comes to /auth/dynamicprovider.{tenantid}
- If the tenant oauth config is not loaded, we load it (ie load on first request or on config update)
- Then we start the OAuth sequence for the request
To add to the complexity, our app is running in a clustered environment so different ServiceStack nodes can have different OAuth providers loaded.
Our problems comes to the reloading part. We get errors like:
Could not register Request ‘ServiceStack.Authenticate’ with service ‘ServiceStack.Auth.AuthenticateService’ as it has already been assigned to another service.
When trying to reload our new providerlist. We do this in a feature with these two methods:
RemoveAuthFeatureIncludingPlugins(); AddAuthFeaturePlugin(authFeature);
Which looks like this:
private void AddAuthFeaturePlugin(IPlugin authFeature)
{
// Reload plugin if it´s already loaded to refresh it´s settings
// Reload the plugin
Log.Information("Reloading the AuthFeature plugin");
// Add new auth feature
_appHost.LoadPlugin(authFeature);
}
private void RemoveAuthFeatureIncludingPlugins()
{
Log.Information("Removing old AuthFeatures and connected plugins");
// Remove all authfeature instances
_appHost.Plugins
.Where(p => p is AuthFeature)
.Cast<AuthFeature>()
.ToList().ForEach(authFeature =>
{
// Remove plugins that belong to the authfeature
authFeature.RegisterPlugins.ForEach(p => _appHost.Plugins.Remove(p));
_appHost.Plugins.Remove(authFeature);
}
);
}
We get into a situation now with occasional 401s and can´t really determine the cause, but as far as I understand it´s quite a twisted scenario we´re trying to pull off. So any suggestions on alternate approaches are appreciated. Or if we´re missing something blantantly stupid in order to get this reloadning of the authfeatre to work (or more correct, to be able too add and remove authproviders dynamically).