Skip to content
This repository has been archived by the owner on Jan 24, 2021. It is now read-only.

Automatically decode cookie values in Cookies dictionary #1390

Merged
merged 13 commits into from
Oct 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public void Should_not_have_content_type_header_for_not_modified_responses()
}
};

A.CallTo(() => fakeEngine.HandleRequest(A<Request>.Ignored, A<Func<NancyContext, NancyContext>>.Ignored, A<CancellationToken>.Ignored))
A.CallTo(() => fakeEngine.HandleRequest(A<Request>.Ignored, A<Func<NancyContext, NancyContext>>.Ignored, A<CancellationToken>.Ignored))
.Returns(TaskHelpers.GetCompletedTask(context));
A.CallTo(() => fakeBootstrapper.GetEngine()).Returns(fakeEngine);

Expand Down
2 changes: 1 addition & 1 deletion src/Nancy.Testing.Tests/BrowserFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ public void Should_add_forms_authentication_cookie_to_the_request()
});

var cookie = response.Cookies.Single(c => c.Name == FormsAuthentication.FormsAuthenticationCookieName);
var cookieValue = HttpUtility.UrlDecode(cookie.Value);
var cookieValue = cookie.Value;

//Then
cookieValue.ShouldEqual(cookieContents);
Expand Down
36 changes: 36 additions & 0 deletions src/Nancy.Tests.Functional/Modules/CookieModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;

namespace Nancy.Tests.Functional.Modules
{
using Nancy.Cookies;

public class CookieModule : NancyModule
{
public CookieModule()
{
Get["/setcookie"] = _ =>
{
const string value = "HakLqr1OEdi+kQ/s92Rzz9hV1w/vzGZKqWeMQRHRJlwhbbgP87UELJZlYDfbVVLo";

var cookie = new NancyCookie("testcookie", value);

var response = new Response();
response.WithCookie(cookie);
response.StatusCode = HttpStatusCode.OK;

return response;
};

Get["/getcookie"] = _ =>
{
const string value = "HakLqr1OEdi+kQ/s92Rzz9hV1w/vzGZKqWeMQRHRJlwhbbgP87UELJZlYDfbVVLo";

var cookie = Context.Request.Cookies["testcookie"];

return String.Equals(cookie, value) ?
HttpStatusCode.OK :
HttpStatusCode.InternalServerError;
};
}
}
}
2 changes: 2 additions & 0 deletions src/Nancy.Tests.Functional/Nancy.Tests.Functional.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Modules\AbsoluteUrlTestModule.cs" />
<Compile Include="Modules\CookieModule.cs" />
<Compile Include="Modules\PerRouteAuthModule.cs" />
<Compile Include="Modules\RazorWithTracingTestModule.cs" />
<Compile Include="Modules\JsonpTestModule.cs" />
Expand All @@ -95,6 +96,7 @@
<Compile Include="Tests\BasicRouteInvocationsFixture.cs" />
<Compile Include="Modules\SerializeTestModule.cs" />
<Compile Include="Tests\ContentNegotiationFixture.cs" />
<Compile Include="Tests\CookieFixture.cs" />
<Compile Include="Tests\MethodRewriteFixture.cs" />
<Compile Include="Tests\PerRouteAuthFixture.cs" />
<Compile Include="Tests\RouteConstraintTests.cs" />
Expand Down
23 changes: 23 additions & 0 deletions src/Nancy.Tests.Functional/Tests/CookieFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Nancy.Tests.Functional.Tests
{
using Modules;

using Testing;
using Xunit;

public class CookieFixture
{
[Fact]
public void Cookie_should_decode_value_correctly()
{
// Given
var browser = new Browser(with => with.Module<CookieModule>());

// When
var result = browser.Get("/setcookie").Then.Get("/getcookie");

// Then
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Nancy.Cryptography;
using Nancy.Culture;
using Nancy.Diagnostics;
using Nancy.Helpers;
using Nancy.Localization;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
Expand Down Expand Up @@ -127,7 +128,7 @@ public void Should_return_main_page_with_valid_auth_cookie()
// When
var result = browser.Get(diagsConfig.Path + "/interactive/providers/", with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password"));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("password")));
});

// Then should see our fake provider and not the default testing provider
Expand Down
13 changes: 7 additions & 6 deletions src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Nancy.Cookies;
using Nancy.Cryptography;
using Nancy.Diagnostics;
using Nancy.Helpers;
using Nancy.Testing;
using Xunit;

Expand Down Expand Up @@ -108,7 +109,7 @@ public void Should_return_main_page_with_valid_auth_cookie()
// When
var result = browser.Get(diagsConfig.Path, with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password"));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("password")));
});

// Then
Expand All @@ -133,7 +134,7 @@ public void Should_return_login_page_with_expired_auth_cookie()
// When
var result = browser.Get(diagsConfig.Path, with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password", DateTime.Now.AddMinutes(-10)));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("password", DateTime.Now.AddMinutes(-10))));
});

// Then
Expand All @@ -158,7 +159,7 @@ public void Should_return_login_page_with_auth_cookie_with_incorrect_password()
// When
var result = browser.Get(diagsConfig.Path, with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("wrongPassword"));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("wrongPassword")));
});

// Then
Expand Down Expand Up @@ -236,7 +237,7 @@ public void Should_use_rolling_expiry_for_auth_cookie()
// When
var result = browser.Get(diagsConfig.Path, with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password", expiryDate));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("password", expiryDate)));
});

// Then
Expand All @@ -263,12 +264,12 @@ public void Should_return_diagnostic_example()
// When querying the list of interactive providers
var result = browser.Get(diagsConfig.Path + "/interactive/providers/", with =>
{
with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password"));
with.Cookie(DiagsCookieName, HttpUtility.UrlEncode(this.GetSessionCookieValue("password")));
});

// Then we should see the fake testing provider and not the Nancy provided testing example
result.Body.AsString().ShouldNotContain("Fake testing provider");
result.Body.AsString().Contains("Testing Diagnostic Provider");
result.Body.AsString().ShouldContain("Testing Diagnostic Provider");
}

private string GetSessionCookieValue(string password, DateTime? expiry = null)
Expand Down
3 changes: 2 additions & 1 deletion src/Nancy.Tests/Unit/RequestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Nancy.Tests.Unit
using System.Linq;
using System.Text;
using FakeItEasy;
using Nancy.Helpers;
using Nancy.IO;
using Xunit;
using Xunit.Extensions;
Expand Down Expand Up @@ -542,7 +543,7 @@ public void Should_split_cookie_in_two_parts_only()
var cookieData = "Y+M3rcC/7ssXvHTx9pwCbwQVV4g=sp0hUZVApYgGbKZIU4bvXbBCVl9fhSEssEXSGdrt4jVag6PO1oed8lSd+EJD1nzWx4OTTCTZKjYRWeHE97QVND4jJIl+DuKRgJnSl3hWI5gdgGjcxqCSTvMOMGmW3NHLVyKpajGD8tq1DXhXMyXHjTzrCAYl8TGzwyJJGx/gd7VMJeRbAy9JdHOxEUlCKUnPneWN6q+/ITFryAa5hAdfcjXmh4Fgym75whKOMkWO+yM2icdsciX0ShcvnEQ/bXcTHTya6d7dJVfZl7qQ8AgIQv8ucQHxD3NxIvHNPBwms2ClaPds0HG5N+7pu7eMSFZjUHpDrrCnFvYN+JDiG3GMpf98LuCCvxemvipJo2MUkY4J1LvaDFoWA5tIxAfItZJkSIW2d8JPDwFk8OHJy8zhyn8AjD2JFqWaUZr4y9KZOtgI0V0Qlq0mS3mDSlLn29xapgoPHBvykwQjR6TwF2pBLpStsfZa/tXbEv2mc3VO3CnErIA1lEfKNqn9C/Dw6hqW";
var headers = new Dictionary<string, IEnumerable<string>>();
var cookies = new List<string>();
cookies.Add(string.Format("{0}={1}", cookieName, cookieData));
cookies.Add(string.Format("{0}={1}", cookieName, HttpUtility.UrlEncode(cookieData)));
headers.Add("cookie", cookies);
var newUrl = new Url
{
Expand Down
10 changes: 5 additions & 5 deletions src/Nancy.Tests/Unit/Sessions/CookieBasedSessionsFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void Should_save_the_session_cookie()
response.Cookies.Count.ShouldEqual(1);
var cookie = response.Cookies.First();
cookie.Name.ShouldEqual(this.cookieStore.CookieName);
cookie.Value.ShouldEqual("encrypted=key1=val1;key2=val2;");
cookie.Value.ShouldEqual("encrypted%3dkey1%3dval1%3bkey2%3dval2%3b");
cookie.Expires.ShouldBeNull();
cookie.Path.ShouldBeNull();
cookie.Domain.ShouldBeNull();
Expand Down Expand Up @@ -111,7 +111,7 @@ public void Should_saves_url_safe_keys_and_values()

cookieStore.Save(session, response);

response.Cookies.First().Value.ShouldEqual("encryptedkey+1=val%3d1;");
response.Cookies.First().Value.ShouldEqual("encryptedkey%2b1%3dval%253d1%3b");
}

[Fact]
Expand Down Expand Up @@ -169,8 +169,8 @@ public void Should_load_a_multi_valued_session()
[Fact]
public void Should_load_properly_decode_the_url_safe_session()
{
var request = CreateRequest("encryptedkey+1=val%3d1;");
A.CallTo(() => this.fakeEncryptionProvider.Decrypt("encryptedkey+1=val%3d1;")).Returns("key+1=val%3d1;");
var request = CreateRequest(HttpUtility.UrlEncode("encryptedkey+1=val%3D1;"));
A.CallTo(() => this.fakeEncryptionProvider.Decrypt("encryptedkey+1=val%3D1;")).Returns("key+1=val%3D1;");

var session = cookieStore.Load(request);

Expand Down Expand Up @@ -308,7 +308,7 @@ public void Should_be_able_to_load_an_object_previously_saved_to_session()
session["testObject"] = payload;
store.Save(session, response);
var request = new Request("GET", "/", "http");
request.Cookies.Add(Helpers.HttpUtility.UrlEncode(response.Cookies.First().Name), Helpers.HttpUtility.UrlEncode(response.Cookies.First().Value));
request.Cookies.Add(response.Cookies.First().Name, response.Cookies.First().Value);

var result = store.Load(request);

Expand Down
3 changes: 2 additions & 1 deletion src/Nancy/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Nancy

using IO;
using Nancy.Extensions;
using Nancy.Helpers;
using Session;

/// <summary>
Expand Down Expand Up @@ -192,7 +193,7 @@ private IDictionary<string, string> GetCookieData()
}
else
{
cookieValue = parts[1];
cookieValue = HttpUtility.UrlDecode(parts[1]);
}

cookieDictionary[cookieName] = cookieValue;
Expand Down
2 changes: 1 addition & 1 deletion src/Nancy/Session/CookieBasedSessions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void Save(ISession session, Response response)
var cryptographyConfiguration = this.currentConfiguration.CryptographyConfiguration;
var encryptedData = cryptographyConfiguration.EncryptionProvider.Encrypt(sb.ToString());
var hmacBytes = cryptographyConfiguration.HmacProvider.GenerateHmac(encryptedData);
var cookieData = String.Format("{0}{1}", Convert.ToBase64String(hmacBytes), encryptedData);
var cookieData = HttpUtility.UrlEncode(String.Format("{0}{1}", Convert.ToBase64String(hmacBytes), encryptedData));

var cookie = new NancyCookie(this.currentConfiguration.CookieName, cookieData, true)
{
Expand Down