Running multiple instances of Identity server in docker cluster Running multiple instances of Identity server in docker cluster docker docker

Running multiple instances of Identity server in docker cluster


The usual issue I've seen with clients is that they've put their AddDataProtection registration before AddIdentityServer.

AddIdentityServer also calls AddDataProtection with the default settings, which unfortunately will override whatever registrations you previously made.

So short answer: you need to put AddDataProtection after AddIdentityServer in your ConfigureServices method.


I struggeled with this for days trying to implement a shared docker volume but it didn't work even when encrypting the keys witha certificate. So I ended up using the database -as suggested by @mackie.

Here is some code for inspiration:

 X509Certificate2  cert = X509CertificateHelper.GetCertificateFromFile(options.Certificate.FilePath, options.Certificate.Passphrase); builder.AddSingleton<IXmlRepository, MongoXmlRepository>(); var sp = builder.BuildServiceProvider(); builder.AddSingleton<IXmlRepository, MongoXmlRepository>(); builder.AddDataProtection()        .SetApplicationName(Assembly.GetExecutingAssembly().FullName)        .AddKeyManagementOptions(o =>                {                    o.XmlRepository = sp.GetService<IXmlRepository>();                })        .ProtectKeysWithCertificate(cert)        .SetDefaultKeyLifetime(TimeSpan.FromDays(options.LifeTimeInDays));

MongoXmlRepository is just a class implementing the IXmlRepository interface:

/// <summary>/// Implementation of the IXmlRepository, used by the DataProtection Service/// </summary>public class MongoXmlRepository : CrudRepository<MongoXElement, string>, IXmlRepository{    public MongoXmlRepository(ILoggerFactory loggerFactory,        DatabaseRegistry databaseRegistry)        : base(loggerFactory, databaseRegistry)    {    }    public IReadOnlyCollection<XElement> GetAllElements()    {        try        {            var asyncCursor = this.Collection                .Find(Builders<MongoXElement>.Filter.Empty);            var entities = asyncCursor.ToList();            var xml = entities.Select(e => XElement.Parse(e.Xml)).ToList();            return xml;        }        catch (Exception e)        {            var errMessage = $"MongoXmlRepositoryError on {this.GetType()}:GetAllElements()";            this.Logger.LogError(errMessage, e);            throw new RepositoryException(errMessage, e);        }    }    public async void StoreElement(XElement element, string friendlyName)    {        var key = new MongoXElement        {            Xml = element.ToString(SaveOptions.DisableFormatting)        };        await this.InsertAsync(key);    }}

The implementation may differ depending on your store, in this case MongoDb was used.