Core 3.0.0 throws key was not found in the key ring exception when SamlServiceProvider.ReceiveSsoAsync()

We have a Service Provider that was created in .net Core 3.1 using ComponentSpace .net core version 3.0.0

Got ComponentSpace working before in .net core but now it’s throwing an exception when
await _samlServiceProvider.ReceiveSsoAsync()
is called in our ServiceProvider from the Identity Provider.

We get the error message
The key{SOMEGUID LIKE fe0c5f73-807f-438f-82de-e316cf0427d5} was not found in the key ring.

Here is the stack trace - it is thrown directly from the ComponentSpace code
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)\n at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)\n at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)\n at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector protector, String protectedData)\n at ComponentSpace.Saml2.Session.CookieSsoSessionStore.DecodeCookieValueT(String encodedCookieValue)\n at ComponentSpace.Saml2.Session.CookieSsoSessionStore.GetCookieValue(

We are not doing anything with Data Protection APIs in our code - only ComponentSpace is using the Data Protection API. We just provide an implementation of IDistributedCache

In case it helps we have this in our
services.TryAddSingleton<IDistributedCache, MyDistributedCache>();

And MyDistributedCache has the following code (which calls an IDistributedCache implementation that stores data in Redis)

public class MyDistributedCache : IDistributedCache
{
private readonly ICacheRepository _cacheRepository;

public MyDistributedCache(ICacheRepository cacheRepository)
{
_cacheRepository = cacheRepository;
}

public byte[] Get(string key)
{
if (!_cacheRepository.TryGet(key, out byte[] value))
value = null;
return value;
}

public async Task<byte[]> GetAsync(string key, CancellationToken token = default)
{
var (found, value) = await _cacheRepository.TryGetAsync<byte[]>(key);
return found ? value : null;
}

public void Refresh(string key)
{
var value = Get(key);
Set(key, value, new DistributedCacheEntryOptions());
}

public async Task RefreshAsync(string key, CancellationToken token = default)
{
var value = await GetAsync(key, token);
await SetAsync(key, value, new DistributedCacheEntryOptions(), token);
}

public void Remove(string key)
{
_cacheRepository.Remove(key);
}

public async Task RemoveAsync(string key, CancellationToken token = default)
{
await _cacheRepository.RemoveAsync(key);
}

public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
{
_cacheRepository.TryAdd(key, value);
}

public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default)
{
await _cacheRepository.TryAddAsync(key, value);
}

Read the web farm guide and it said as long as IDistributedCache can be resolved everything should work.

It seems like this was working earlier - what should we do to fix this issue?

The CookieSsoSessionStore stores the SAML session state in the saml-session cookie value. The cookie value is protected using IDataProtectionProvider.

The CookieSsoSessionStore doesn’t make use of the IDistributedCache.

Did you want to store the SAML session state in the saml-session cookie itself (ie use CookieSsoSessionStore)?

Or did you want to store the SAML session state in your IDistributedCache implementation?

[quote]
ComponentSpace - 7/13/2020
The CookieSsoSessionStore stores the SAML session state in the saml-session cookie value. The cookie value is protected using IDataProtectionProvider.

The CookieSsoSessionStore doesn't make use of the IDistributedCache.

Did you want to store the SAML session state in the saml-session cookie itself (ie use CookieSsoSessionStore)?

Or did you want to store the SAML session state in your IDistributedCache implementation?

[/quote]

I don't care where the saml session is stored - I prefer to just use the default.
My problem is that the default method of storing the cookiesessionstore with no changes to configuration is throwing an exception in my deployment - is there anything that needs to be configured with IDataProtectionProvider that I'm missing and is the reason why this is throwing this exception?
[quote]
ComponentSpace - 7/13/2020
The CookieSsoSessionStore stores the SAML session state in the saml-session cookie value. The cookie value is protected using IDataProtectionProvider.

The CookieSsoSessionStore doesn't make use of the IDistributedCache.

Did you want to store the SAML session state in the saml-session cookie itself (ie use CookieSsoSessionStore)?

Or did you want to store the SAML session state in your IDistributedCache implementation?

[/quote]

I don't care where the saml session is stored - I prefer to just use the default.
My problem is that the default method of storing the cookiesessionstore with no changes to configuration is throwing an exception in my deployment - is there anything that needs to be configured with IDataProtectionProvider that I'm missing and is the reason why this is throwing this exception?[/quote]
This is the area where it is failing

Got ComponentSpace working before in .net core but now it's throwing an exception when
await _samlServiceProvider.ReceiveSsoAsync()
is called in our ServiceProvider from the Identity Provider.
We get the error message
The key{SOMEGUID LIKE fe0c5f73-807f-438f-82de-e316cf0427d5} was not found in the key ring.
Here is the stack trace - it is thrown directly from the ComponentSpace code
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)\n at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)\n at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)\n at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector protector, String protectedData)\n at ComponentSpace.Saml2.Session.CookieSsoSessionStore.DecodeCookieValueT(String encodedCookieValue)\n at ComponentSpace.Saml2.Session.CookieSsoSessionStore.GetCookieValue(

I wasn’t able to reproduce the issue. I used .NET Core 3.1 and SAML 3.0.0.

I added the following to the ExampleServiceProvider’s start-up.


// Add SAML SSO services.
services.AddSaml(Configuration.GetSection(“SAML”));

// Use a separate cookie name to avoid issues with the ExampleIdentityProvider
// which isn’t using the CookieSsoSessionStore.
services.Configure(options =>
{
options.CookieName = “my-saml-session”;
});

services.AddScoped<ISsoSessionStore, CookieSsoSessionStore>();



Can you reproduce the issue using the ExampleServiceProvider?

Are you using the default data protection setup?