State provider to replace HttpContext Session usage

Nov 1, 2013 at 1:22 AM
Edited Nov 1, 2013 at 1:23 AM
Hi,

I've created a State provider in my fork which is being used to replace the hard coded HttpContext session usage. In our use case we wanted to remove the requirement of ASP.NET sessions for ease of scaling reasons.

I've pushed two implementations:

SessionStateService

Works the same as previously with standard ASP.NET session. To enable, add the following web.config entry:
<saml2>
 <state stateServiceFactory="SAML2.State.SessionStateServiceFactory, SAML2" />
</saml2>
CacheStateService

Uses System.Web.Cache as a backing store. A cache key prefix is stored in an encrypted cookie, which is used to build the full cache key for Get/Set etc. To enable, add the following web.config setting:
<saml2>
<state stateServiceFactory="SAML2.State.CacheStateServiceFactory, SAML2" cacheExpiryMinutes="120" />
</saml2>
  • cacheExpiryMinutes = cache lifetime
I've kept to the same provider pattern you had already created, so things should be pretty consistent. There is already an outstanding pull request from my fork so haven't been able to add one for these changes.

Hopefully you will find this useful - I also have a Memcached implementation if you think it is worth sharing (in a separate project due to other dependencies that are introduced).

Cheers
Coordinator
Nov 12, 2013 at 4:09 AM
Edited Nov 12, 2013 at 4:43 AM
I'm open to the extension. Let me go ahead and approve your other pull request and then you can submit this as an enhancement that I can bring over.

Question: What do you see as an advantage for using cache over session in these cases? You cite scaling reasons, but I'm wondering where exactly I would want cache over session for these.

Basically, I'm fine with adding the abstraction, I'm just trying to decide if I want to provide the cache provider out of the box, or allow for an extension project to be written to handle that. I have kind of tried to provide one default implementation for things, but allow for the extension point for those who might have extra needs.
Nov 12, 2013 at 5:08 AM
Hey - thanks, I will do.

We have session state off in our production environment, so I basically needed a non session-based alternative. I have provided a System.Web.Cache implementation in my fork (which we use in dev), but in production have a Memcached implementation to allow for shared state across our instances.

I realise the argument can be made that session can be scaled in a similar fashion, but for us the other non-session implementation better fit our environment.

I'm able to make available the Memcached version if you think it might be useful, it's in a different project as it introduces a dependency for the Memcached client.

Just wanted to offer/give something back as this project has been very useful for us :)
Coordinator
Nov 12, 2013 at 5:16 AM
Edited Nov 12, 2013 at 5:23 AM
Yeah, that was kind of my argument... session seems the right tool for the job, as it were, given that cache is shared and thus you have to implement a key tracking mechanism (e.g. either by sticking that key in a cookie or in another session variable... of course if you do the latter you might as well use session in the first place...).

While I think the use case you have may be a little more specialized than I want to handle in the core, I'm certainly open to adding an abstraction around the state storage as you have to allow for extension for situations like yours. Let me pull your fork and take a look through your implementation and do some cleanup, and I'll add it into the core.

If you would like to provide your cache based or memcached implementation in a codeplex project, of course you can do that. I'm just trying to stick to the "one blessed way in core" kind of methodology.

Edit: Actually, I could see an argument for a COOKIE based storage mechanism for this... I think someone actually submitted a similar request upstream in OIOSAML.NET a while back, but this could be a good time and place to implement that... If I do end up doing that, I will reconsider adding the cache implementation as well.
Dec 4, 2013 at 3:46 PM
Just to add my two cents. I also am in an environment where session state is turned off. I took a look at @daynew's fork but in the end I made a separate change to handle what I needed by just using HttpContext.Current.Items. For the most part session was being used to pass state around between components that most likely did not need to be persisted across different HTTP requests.

I'm not submitting a PR for this for the following reasons:
  1. @dwaynew approached the problem in a far more robust way (I didn't use it mainly because writing a provider for HttpContext.Current.Items seemed like more work than what I did).
  2. I did have to slightly lower security in the CheckReplayAttack code - storing the expected InResponseTo in a user-specific session that persists across requests makes sense there. My alternative was a hashtable that stores all the expected requests. It's not bad, but not as good as the original code.
  3. Signon actions are configurable, so I don't know what other Actions other users of this library might be reliant on session.
Mainly for #3, I did setup the code so it will use sessions if they're turned on and will fall back to HttpContext.Current.Items if session isn't available. This also helps out with issue #2, but it could create confusion if the implementation changes based on the app configuration.

If you're interested at all in that approach, they are in my nosession feature branch: https://saml2.codeplex.com/SourceControl/network/forks/etlerch/saml2?branch=nosession. If you would like I'm happy to submit a PR, but I do think mine is the lesser solution.
Coordinator
Dec 12, 2013 at 6:47 PM
I'm going to roll this in with a few changes. I'm not sure how much I like the cache key generation stuff or the cookie name dwayne chose, but for the most part his implementation is sound and those are really nitpicking points.

The one thing I did do was remove Context on all of his calls and allowed the singleton instance to maintain it's HttpContext itself.

The code is up there now for review. If you have comments or suggestions, they are welcome.