Skip to content
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

Mitigation of wrong cookie value separator #451

Merged
merged 8 commits into from
Oct 13, 2020

Conversation

ManickaP
Copy link
Member

@ManickaP ManickaP commented Oct 2, 2020

HttpClient wrongly uses comma (,) as a separator for cookie header values: dotnet/runtime#42856. As well as Kestrel probably doesn't merge cookie header frames for HTTP/2: dotnet/aspnetcore#26461.

This PR mitigates this by collecting all cookie headers while copying them. And concatenating them manually with semi-colon (;) before adding it as a single header to the destination request.

Fixes #437

Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good start. Most of my comments are about simplifying the logic and tests.

src/ReverseProxy/Service/Proxy/HttpProxy.cs Outdated Show resolved Hide resolved
test/ReverseProxy.FunctionalTests/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.FunctionalTests/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.FunctionalTests/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.FunctionalTests/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.FunctionalTests/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.Tests/Service/Proxy/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.Tests/Service/Proxy/HttpProxyTests.cs Outdated Show resolved Hide resolved
test/ReverseProxy.Tests/Service/Proxy/HttpProxyTests.cs Outdated Show resolved Hide resolved
@ManickaP ManickaP force-pushed the mapichov/437_cookie_separator branch from 6b227ba to 65708d0 Compare October 8, 2020 11:41
@ManickaP ManickaP force-pushed the mapichov/437_cookie_separator branch from 65708d0 to 3b590b5 Compare October 8, 2020 11:47
@ManickaP ManickaP requested a review from Tratcher October 8, 2020 11:48
Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix looks good. Some minor comments left on the tests.

src/ReverseProxy/Service/Proxy/HttpProxy.cs Outdated Show resolved Hide resolved
@@ -430,6 +430,13 @@ private static void CopyRequestHeaders(HttpContext context, HttpRequestMessage d
// as long as they appear in one (and only one, otherwise they would be duplicated).
static void AddHeader(HttpRequestMessage request, string headerName, StringValues value)
{
// HttpClient wrongly uses comma (",") instead of semi-colon (";") as a separator for Cookie headers.
// To mitigate this, we concatenate them manually and put them back as a single header value.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// To mitigate this, we concatenate them manually and put them back as a single header value.
// To mitigate this, we concatenate them manually and put them back as a single header value.
// A multi-header cookie header is invalid, but we get one because of
// https://github.com/dotnet/aspnetcore/issues/26461

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this change in your PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my bad, should be there now.

test/ReverseProxy.FunctionalTests/HttpProxyCookieTests.cs Outdated Show resolved Hide resolved
Comment on lines 158 to 159
}
public class HttpProxyCookieTests_Http1 : HttpProxyCookieTests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
public class HttpProxyCookieTests_Http1 : HttpProxyCookieTests
}
public class HttpProxyCookieTests_Http1 : HttpProxyCookieTests

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines 150 to 153
// Ensure that CookieA is the first and CookieB the last.
Assert.True(context.Request.Headers.TryGetValue(HeaderNames.Cookie, out var headerValues));
Assert.StartsWith(CookieA, headerValues);
Assert.EndsWith(CookieB, headerValues);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Careful what you're asserting here, you're expecting different results for HTTP/1 and HTTP/2.

headerValues is a StringValues, but you're passing it to StartsWith which takes a string. There's an implicit converter from StringValues to string which concatenates with commas (just like the original bug). Rather than using StartsWith, you want to check the count and value of each StringValues entry to make sure it's what you expect. E.g. Count should be 1 for HTTP/1 and 2 for HTTP/2.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added different set of asserts per context.Request.Protocol.

test/ReverseProxy.FunctionalTests/HttpProxyCookieTests.cs Outdated Show resolved Hide resolved
@ManickaP ManickaP requested a review from Tratcher October 9, 2020 18:18
@ManickaP ManickaP marked this pull request as ready for review October 9, 2020 18:18
{
public override HttpProtocols HttpProtocol => HttpProtocols.Http1;

// Using simple TcpClient since HttpClient will always concatenate cookies with comma separator.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Using simple TcpClient since HttpClient will always concatenate cookies with comma separator.

{
using var client = new HttpClient();
using var message = new HttpRequestMessage(HttpMethod.Get, proxyHostUri);
message.Headers.Add(HeaderNames.Cookie, $"{Cookies}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
message.Headers.Add(HeaderNames.Cookie, $"{Cookies}");
message.Headers.Add(HeaderNames.Cookie, Cookies);

@Tratcher Tratcher added this to the 1.0.0-preview6 milestone Oct 13, 2020
@ManickaP ManickaP merged commit 6311df4 into microsoft:master Oct 13, 2020
@ManickaP ManickaP deleted the mapichov/437_cookie_separator branch October 13, 2020 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Question/Bug] Cookie value separator changed to comma?
2 participants