aspnet / AspNetKatana

Microsoft's OWIN implementation, the Katana project
Apache License 2.0
959 stars 331 forks source link

Use SystemWebCookieManager by default #485

Closed Tratcher closed 1 year ago

Tratcher commented 1 year ago

This mitigates https://github.com/aspnet/AspNetKatana/wiki/System.Web-response-cookie-integration-issues for most users by defaulting to the SystemWeb cookies collection when available.

@kevinchalet thoughts?

kevinchalet commented 1 year ago

Wooooot, I was really tempted to open a ticket to suggest doing that when I posted https://github.com/dotnet/aspnetcore/issues/45278#issuecomment-1331247216 2 weeks ago 😅

The idea is great, but the layering - having Microsoft.Owin depend on System.Web - is sadly far from ideal.

I'd suggest opting for a different approach, designed after what already exists for IDataProtector/IDataProtectionProvider:

It's a bit more code, but it solves the layering problem very nicely.

kevinchalet commented 1 year ago

Oh, and since you're making my wildest dreams come true, what about making ThrowForPartialCookies false by default? 🤣

Tratcher commented 1 year ago

having Microsoft.Owin depend on System.Web - is sadly far from ideal.

Yeah, that's what put me off this approach for so long. Ultimately though, this is full framework so that dependency doesn't really mean much, it's all there on disk regardless. Worst case an extra assembly gets loaded at runtime for self-host apps. I'm less concerned about that since Katana is disproportionately used on System.Web.

Oh, and since you're making my wildest dreams come true, what about making ThrowForPartialCookies false by default? 🤣

Sure :-)

kevinchalet commented 1 year ago

Worst case an extra assembly gets loaded at runtime for self-host apps. I'm less concerned about that since Katana is disproportionately used on System.Web.

It's likely not unreasonable, but System.Web is still a heavy dependency (2/3MB IIRC?) that self-hosters would want to avoid, so if there's a way to avoid that, it's worth giving it a try.

The IDataProtector approach isn't too complicated and doesn't have this con. Would you like me to give it a try? 😄

Tratcher commented 1 year ago

The IDataProtector approach isn't too complicated and doesn't have this con. Would you like me to give it a try? 😄

Ok, have fun

Tratcher commented 1 year ago

It's likely not unreasonable, but System.Web is still a heavy dependency (2/3MB IIRC?) that self-hosters would want to avoid, so if there's a way to avoid that, it's worth giving it a try.

Ha, C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Web.dll is 5mb! And that doesn't include transitive dependencies.

Tratcher commented 1 year ago

Would this be a factory that returns a ICookieManager? Maybe with an option for chunking?

kevinchalet commented 1 year ago

Not gonna lie, setting up that repo was quite a challenge 😅

NU1603: Katana.Sandbox.WebServer dépend de Microsoft.TemplateEngine.Tasks (>= 7.0.100-preview.2.22075.3), mais Microsoft.TemplateEngine.Tasks 7.0.100-preview.2.22075.3 est introuvable. Une meilleure correspondance approximative de Microsoft.TemplateEngine.Tasks 7.0.100-preview.2.22153.5 a été résolue.
NU1101: Package RichCodeNav.EnvVarDump introuvable. Aucun package associé à cet ID n'existe dans la ou les sources suivantes : dotnet-eng, dotnet-public, dotnet-tools

Anyway, I gave it a try and here's the result: https://github.com/kevinchalet/AspNetKatana/commit/6c14fc2820cc22440655c3670d5fb50a28ebcd1c

It's very crude ATM but if it's an approach you like, it can be polished. Two things to note:

Tratcher commented 1 year ago

Yeah, switching to the new build infrastructure left some rough edges 😁. I'm tempted to remove those sandbox projects.

kevinchalet commented 1 year ago

I'm tempted to remove those sandbox projects.

Or convert them to SDK-style projects using CZEMacLeod's MSBuild.SDK.SystemWeb? 😄

The result is incredible: https://github.com/openiddict/openiddict-core/blob/dev/sandbox/OpenIddict.Sandbox.AspNet.Client/OpenIddict.Sandbox.AspNet.Client.csproj (that project even builds on macOS/Linux thanks to the .NET Framework reference assemblies package, mind blowing... :trollface:)

kevinchalet commented 1 year ago

Copying these comments here so they don't disappear once the branch will be removed.

image

I made the same experiment but without the loosely-typed tuples: https://github.com/kevinchalet/AspNetKatana/commit/500ca4779cf21579671989c4440eb63d10ff42e5

Unsurprisingly, it's much less "OWINy" - it had its own charm :trollface: - but it simplifies things a lot 🤣

Tratcher commented 1 year ago

Very nice. Want to send a PR?

kevinchalet commented 1 year ago

Very nice. Want to send a PR?

Yeah, I'll do that.

Note: one of the two concerns vanished when removing the loosely-typed OWINisms, but the other one remains. Should we do something to avoid a behavior change?

  • There's a small behavior change in the OAuth 1.0/2.0/OIDC middleware, where the cookie manager is no longer set in the options constructor but from the middleware (like what the cookies middleware does). It's unlikely folks expect the *Options.CookieManager property to be non-null before calling app.Use*Authentication() but if it's a breaking change you want to avoid, a special "default" marker instance could be used to detect whether the cookie manager was replaced by the user.
Tratcher commented 1 year ago

I'm not concerned about anyone reading that property. Did you have any examples of that in the aspnet-contrib libs?

kevinchalet commented 1 year ago

Opened: https://github.com/aspnet/AspNetKatana/pull/486.

Did you have any examples of that in the aspnet-contrib libs?

Nope. The only - unusual? - pattern I can think of would be this one:

var options = new OpenIdConnectAuthenticationOptions();
options.CookieManager = new MyCookieManagerWrapperThatDoesSameSiteStuff(options.CookieManager);

app.UseOpenIdConnectAuthentication(options);
Tratcher commented 1 year ago

Oh, and since you're making my wildest dreams come true, what about making ThrowForPartialCookies false by default? 🤣

This is the only part of this PR left. Want to include that in your other PR, or send a separate one for it?

kevinchalet commented 1 year ago

This is the only part of this PR left. Want to include that in your other PR, or send a separate one for it?

Done: https://github.com/aspnet/AspNetKatana/pull/488

Many generations of poor people DOSed by ThrowForPartialCookies will thank you for accepting this change 😄