TResponse
TResponse

Reputation: 4125

Asp.Net Core 2.1 Request exlusing client side cookies

I have a problem where cookies set in the website using javascript are not being passed to controllers in the Request. Any cookies set in C# are present.

In my Startup.cs I have set the following:

ConfigureServices:

services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => false;// must be false otherwise only essential cookies will be allowed
    options.MinimumSameSitePolicy = SameSiteMode.None;              
});

Configure:

app.UseCookiePolicy(new CookiePolicyOptions
{
    HttpOnly = HttpOnlyPolicy.None
});

when inspecting the cookies in the browser the one I want - "ClientTimeZone" is present as can be seen in this image:

enter image description here

but in the controller when looking at the Request that cookie is not present:

enter image description here

The JavaScript code I use to store cookies are as follows:

setCookie: function (name, value, days)
    {
        var expires = "";
        if (days)
        {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = "; expires=" + date.toUTCString();
        }
        document.cookie = name + "=" + (value || "") + expires + ";";
    },

I have also tried adding path=/ but no luck.

Any suggestions as to why the cookie does not persist to the server?

Thanks,

Upvotes: 1

Views: 1511

Answers (1)

Michael Gagne
Michael Gagne

Reputation: 345

This is due to spaces in your cookie value (and in my case, Json). .NET Core is using RFC-6265. Allowed characters are alphanumerics plus ~!@#$%^&*()-_+[]{}|. Space, comma, semi-colon, backslash, and quotes are not allowed.

The simplest fix is to use Uri encoding/decoding.

Javascript to set cookie value:

document.cookie = 'ClientTimeZone=' + encodeURIComponent("New Zealand Time") + ';path=/';

C# to read it:

var timeZone = System.Net.WebUtility.UrlDecode(Request.Cookies["ClientTimeZone"]);

The source of the issue is when parsing header values into cookies:

Microsoft.Net.Http.Headers.HttpHeaderParser
{
    protected virtual bool TryParseValues(IList<string> values, bool strict, out IList<T> parsedValues)
}

Eventually hits the following method, which exits as soon as it hits a disallowed character:

Microsoft.Net.Http.Headers.CookieHeaderValue
{
    internal static StringSegment GetCookieValue(StringSegment input, ref int offset)
}

Essentially, even though the cookie is sent in the request header, any cookie that doesn't parse correctly is silently ignored and never included in the IRequestCookieCollection Request.Cookies.

Upvotes: 3

Related Questions