New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adapt RFC 6265 in path handling for cookies #39250
Conversation
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/ncl |
Thank you, this is amazing! Looking forward to the other side of the PR too, but will try this when it would be in a nightly build. |
/CC @geoffkizer @wfurt |
src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs
Outdated
Show resolved
Hide resolved
This change basically looks fine to me (a couple minor issues above). But I'd still like to understand what exact scenarios are changing behavior, and whether we think these are at all common or not. |
Re additional issues not addressed here:
This is just allowing domains without a leading dot, right? This seems pretty simple to do, so is there any reason this wouldn't make it for 5.0?
Can you explain what's necessary to do here? |
@geoffkizer thanks!
The two cases I see:
It looks like both cases should be very uncommon.
It's more about the Version attribute actually. Since RFC 6265 deprecated it, normally we should remove all logic depending on it (including all code dealing with As alternative, we may decide to keep that logic for now, and handle removing of Version in 3rd PR later, or maybe open a separate issue for Version. |
What customer benefit is there to removing the Version logic? It doesn't seem to me like this is going to help users much (unless I'm missing something). |
Yeah, I agree. I would vote to just go ahead and make these changes. As long as we also get the domain change in for 5.0 (which seems like it should be easy to do), I think we will be in a fine place for 5.0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor feedback above.
LGTM in general, minor feedback above. Would be good to get a review from @Tratcher as well. |
After doing more experiments and reading further in RFC 6265, I've got more concerned about the change, marking the PR as WIP until those concerns are resolved. I realized that clients are still required to path-match the request URL when accepting cookies as per section 5.4:
According to this, now I'm afraid that @Tratcher's findings in #25226 (comment) are probably inaccurate:
It looks like Chrome+Edge does not accept a cookie with a more specific path |
Hahh. We only use Chrome / Edge, so we considered that the 'expected truth'. Based on the RFC too, Firefox seems to tbe the odd one out as the other two seems to follow it more to the text. |
Yeah but this is bad news for your use case isn't it? If we decide to implement the strict RFC-conform solution Chrome does, your authentication logic will keep failing since the cookies are set with the path /cc @javiercn |
This scenario does work today in all browsers. HttpClient is the only place we've had trouble with it. |
@Tratcher this is either not true, or I'm missing an important detail. The following app prints Notes:
|
See this scenario from the original issue: #26141 (comment) These OpenIdConnect cookies work in all browsers (or I would have been canned by now). Here's an updated version of your sample that more closely reflects the OIDC scenario: public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async ctx =>
{
if (!ctx.Request.Cookies.ContainsKey("LoginInvoked"))
{
ctx.Response.Redirect("/login/user");
}
else
{
if (ctx.Request.Cookies.ContainsKey("LoggedIn"))
{
await ctx.Response.WriteAsync($"WORKS");
}
else
{
await ctx.Response.WriteAsync($"COOKIE MISSING LoggedIn");
}
}
});
endpoints.MapGet("/login/user", async ctx =>
{
ctx.Response.Cookies.Append("LoginInvoked", "true", new CookieOptions() { Path = "/" });
ctx.Response.Cookies.Append("LoggingIn", "true", new CookieOptions() { Path = "/return" });
ctx.Response.Redirect("/return");
});
endpoints.MapGet("/return", async ctx =>
{
if (!ctx.Request.Cookies.ContainsKey("LoggingIn"))
{
await ctx.Response.WriteAsync($"COOKIE MISSING LoggingIn");
return;
}
ctx.Response.Cookies.Append("LoggedIn", "true", new CookieOptions() { Path = "/" });
ctx.Response.Redirect("/");
});
});
} It's the |
@Tratcher thank you for making the use case clear, it helped a lot! This case should indeed work with the new RFC. |
@geoffkizer I want to add a few more tests based on the login scenarios before removing the draft mark. Regarding the removal of the Version property: |
That section is about sending request cookies, not about accepting response cookies. Our issues have been on accepting, not sending. |
Had to push several changes to @ManickaP any chance you can review that particular file? |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HttpClientHandlerTest.Cookies.cs changes looks good, minor questions.
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs
Outdated
Show resolved
Hide resolved
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
@antonfirsov you're hitting #39056 in outerloop (among others), please disregard this one, it's known and in my pipeline. |
# Conflicts: # src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs
@antonfirsov this is labeled breaking change. Can you please open an issue with https://github.com/dotnet/docs/issues/new?template=dotnet-breaking-change.md I don't see one |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
Resolves "Path related issues" of dotnet#26141 (described in dotnet#21440, dotnet#22372 and dotnet#25226) by adapting RFC 6265 for path management: - Removes the restriction for the Path attribute (it's no longer expected to prefix the request path) - Introduces the default-path calculation and path matching algorithms as defined in section 5.1.4 of the new RFC - Adds integration tests for HttpClient based on user scenarios described in the issues
Docs merged, so will remove "needs-breaking-change-doc-created" label |
This PR resolves the "Path related issues" in #26141 by adapting RFC 6265 for path management.
HttpClient
based on user scenarios described in the issuesThe work is mostly based on @ism's analysis in #21440 (comment). This is a behavioral breaking change compared to previous versions of .NET.
This PR does not:
I plan to add those changes in follow-up PR-s. I believe that the improved path management by it's own can unblock many users.
/cc @psmulovics @Tratcher
EDIT
Marked as draft because of the concerns in #39250 (comment)