The SAML Assertion is being replayed

i am using the .net core 3. with componentspace version 3.0.0
my app is a service provider and I am connecting to the samltest.id identity provider

I am getting this exception thrown
The SAML assertion with ID _1e04c5e39a5b8ef843c641db5ac5192f is being replayed.

when the following code is running
ComponentSpace.Saml2.Exceptions.SamlProtocolException: The SAML assertion with ID _1e04c5e39a5b8ef843c641db5ac5192f is being replayed.
at ComponentSpace.Saml2.SamlServiceProvider.CheckForAssertionReplayAsync(SamlAssertion samlAssertion)
at ComponentSpace.Saml2.SamlServiceProvider.ProcessSamlAssertion(SamlAssertion samlAssertion)
at ComponentSpace.Saml2.SamlServiceProvider.ProcessSamlResponseAsync(XmlElement samlResponseElement, String relayState)
at ComponentSpace.Saml2.SamlServiceProvider.ReceiveSsoAsync()

This seems to always happen the first time I am trying to connect with samltest.id - but the second time it does not get that error. How do I get around this error

I had a IDistributedCache implementation that was returning byte[0] instead of null when there was no data - changing it to return null - will that fix this?

Yes, it should. We check for a null return.

I see a similar, but not the same issue.
The message is ‘The SAML assertion is being replayed.’ But without id specified.

It started to happen after Redis storage was implemented. I took the example from solution ExamplesVS2019 which comes with the library.
Attached log trace.
also attached is the code for RedisSessionStore

i also saw thread https://stackoverflow.com/questions/58101264/the-saml-assertion-with-id-the-id-is-being-replayed
it’s similar to my configs. Server in US -6 time zone, the user in EU +2 timezone. But it shouldn’t be an issue, as it is written there.

i also checked traffic by fiddler. And there are no replications/duplicates. Only one call to SP from IdP (okta).

from stachoverflow.
[quote]
We keep a cache of previous SAML assertion IDs so we can detect possible replay attacks. Every SAML assertion has a unique ID so you should never see the same ID again. Each time we receive an assertion we check it against this cache. We throw this exception if the ID is in the cache. Under normal circumstances you should not see this type of error.
[/quote]

So, the problem is that redis contains previous keys? What I can see under debug, RedisSsoSessionStore->Delete never called. Not sure why.

Thanks for the log. It doesn’t show any obvious issues.

The code you attached is for the SSO session store rather than the ID cache. It’s the ID cache where SAML assertion IDs are stored to detect replay attacks.

I suspect there’s an issue with the ID cache implementation. I suggest setting a breakpoint to see what the Add method is returning. It should return true if the ID doesn’t already exist in the cache. If it returns false, we’ll throw the exception you’re seeing.

There is no delete method in this interface. Instead, an expiry date/time is specified when an ID is added. The cache should remove the expired entries. Even if this wasn’t working, you wouldn’t get the exception you’re seeing as each ID is unique. However, the cache would eventually fill with expired IDs.

Yep. Found the problem in RedisIdCache. Thanks.

You’re welcome.