{"id":2826,"date":"2014-05-11T21:04:08","date_gmt":"2014-05-12T04:04:08","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2826"},"modified":"2014-05-11T21:13:30","modified_gmt":"2014-05-12T04:13:30","slug":"owin-protocol-middleware-cookies-and-reference-mode-sessions-we-need-your-feedback","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2014\/05\/11\/owin-protocol-middleware-cookies-and-reference-mode-sessions-we-need-your-feedback\/","title":{"rendered":"OWIN Protocol Middleware, Cookies and Reference Mode Sessions: We Need Your Feedback!"},"content":{"rendered":"<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/05\/image6.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/05\/image_thumb6.png\" alt=\"image\" width=\"387\" height=\"480\" border=\"0\" \/><\/a><\/p>\n<p>As <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/04\/22\/authentication-protocols-web-ux-and-web-api\/\">you know<\/a>, development stacks implementing web sign in protocols traditionally handle sessions by tracking the content of the initial token in form of a session cookie. That is not the only way in which it could be done, and I do think it will change in the future, but for the time being that\u2019s the mainstream technique.<\/p>\n<p>Tokens can sometimes get quite big, especially when you add multi value claims to them (groups, roles). At the same time, the total allowance per domain can be quite restrictive: for example, Safari won\u2019t send more than 4K of cookies per domain.<\/p>\n<p>WIF had a mechanism for helping to deal with big cookies, the IsReferenceMode (IsSessionMode in WIF1.0) flag which allowed you to use the cookie to persist a session identifier and maintain the actual content of the session server side. I described the technique <a href=\"https:\/\/www.cloudidentity.com\/blog\/2010\/05\/26\/your-fedauth-cookies-on-a-diet-issessionmode-true\/\">here<\/a> (four years ago!!! Where did that time go?).<\/p>\n<p>Given the importance of the scenario, we wanted to ensure that the functionality is available also in the new OWIN middleware for WS-Federation and OpenId Connect \u2013 and in fact for any module that needs it.<br \/>\nChris and Brent mulled over the problem a bit, then came out with an elegant solution to the problem. The cookie middleware now features a pluggable store interface, that you can use for customizing how an AuthenticationTicket is preserved across calls. If you want to provide an alternative store for your authentication tickets, all you need to do is implementing that interface and passing an instance to the cookie middleware at initialization time.<\/p>\n<p>Here there\u2019s the interface:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">interface<\/span> IAuthenticationSessionStore\r\n{\r\n    Task RemoveAsync(<span class=\"kwrd\">string<\/span> key);\r\n    Task RenewAsync(<span class=\"kwrd\">string<\/span> key, AuthenticationTicket ticket);\r\n    Task&lt;AuthenticationTicket&gt; RetrieveAsync(<span class=\"kwrd\">string<\/span> key);\r\n    Task&lt;<span class=\"kwrd\">string<\/span>&gt; StoreAsync(AuthenticationTicket ticket);\r\n}\r\n<\/pre>\n<p>Pretty straightforward, right? Upon first receiving a valid token, the pipeline hands you the corresponding AuthenticationTicket in StoreAsync: you can decide which key to use for identifying it (as long as it is a string) and how\/where to save the AuthenticaticationTicket bits. The cookie middleware will take care of saving the key in the session cookie, and hand it over to you via RetrieveAsync the next time it sees the session cookie again.<\/p>\n<p>To give you an idea of how to take advantage of this feature, under the watchful eyes of Brent and Chris I wrote a na\u00efve IAuthenticationSessionStore implementation based on the Entity Framework. You can find the corresponding GIST <a href=\"https:\/\/gist.github.com\/vibronet\/90d4646c273930ff12d4\">here<\/a>. It is very straightforward, hence I left it comment-free <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/05\/wlEmoticon-smile3.png\" alt=\"Smile\" \/><br \/>\nUsing it is very simple, you just pass a new store instance to the cookie middleware initialization routine.<\/p>\n<pre class=\"csharpcode\">app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);\r\nIDataProtector dataProtector = app.CreateDataProtector(<span class=\"kwrd\">typeof<\/span>(NaiveEFAuthSessionStore).FullName, <span class=\"str\">\"MyEntropy\"<\/span>, <span class=\"str\">\"v1\"<\/span>);\r\napp.UseCookieAuthentication(\r\n    <span class=\"kwrd\">new<\/span> CookieAuthenticationOptions() \r\n    { \r\n       SessionStore = <span class=\"kwrd\">new<\/span> NaiveEFAuthSessionStore(<span class=\"kwrd\">new<\/span> TicketDataFormat(dataProtector)) \r\n    });\r\n\r\napp.UseWsFederationAuthentication(\r\n    <span class=\"kwrd\">new<\/span> WsFederationAuthenticationOptions\r\n    {\r\n        Wtrealm = realm,\r\n        MetadataAddress = metadata                                      \r\n    });\r\n<\/pre>\n<p>The data protector parameter is just an artifact of this implementation and how it protects the AuthenticationTicket in the db \u2013 you can use anything that fits your scenario.<\/p>\n<p>Note, in order to use this feature you need to use the NuGets from the nightly builds &#8211; you can use the feed in <a href=\"http:\/\/www.myget.org\/f\/azureadwebstacknightly\/\">http:\/\/www.myget.org\/f\/azureadwebstacknightly\/<\/a>. For example, for the sample code above I used the package Microsoft.Owin.Security.Cookies version 3.0.0-beta2-30508-029-dev.<\/p>\n<h2>We Need Feedback!<\/h2>\n<p>This is where you come into play. This is a super important feature, and one that has multiple moving parts. We really need as much real world validation as we can get.\u00a0 If you can give it a spin and let us know if that works for you, that would be fantastic!<\/p>\n<p>Feel free to hit me though <a href=\"https:\/\/www.cloudidentity.com\/blog\/contact\/\">this contact form<\/a>, to come to find me in person if you are <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/05\/07\/see-you-at-teched-in-houston\/\">coming to TechEd<\/a>, or hang out at the <a href=\"https:\/\/jabbr.net\/#\/rooms\/owin\">OWIN Jabbr<\/a>\u2026 the more feedback we get, the sooner we\u2019ll ship <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/05\/wlEmoticon-winkingsmile1.png\" alt=\"Winking smile\" \/><\/p>\n<p>Thanks in advance!!!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As you know, development stacks implementing web sign in protocols traditionally handle sessions by tracking the content of the initial token in form of a session cookie. That is not the only way in which it could be done, and I do think it will change in the future, but for the time&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2823,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2826","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2826","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=2826"}],"version-history":[{"count":3,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2826\/revisions"}],"predecessor-version":[{"id":2829,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2826\/revisions\/2829"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2823"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}