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

Add SameSite support for NancyCookies #3006

Closed
wants to merge 1 commit into from
Closed
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
7 changes: 6 additions & 1 deletion src/Nancy/Cookies/INancyCookie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,10 @@ public interface INancyCookie
/// Whether the cookie is secure (i.e. HTTPS only)
/// </summary>
bool Secure { get; }

/// <summary>
/// Wheather the cookie is same site
/// </summary>
SameSite? SameSite { get; }
}
}
}
22 changes: 17 additions & 5 deletions src/Nancy/Cookies/NancyCookie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public NancyCookie(string name, string value)
/// <param name="value">The value of the cookie.</param>
/// <param name="expires">The expiration date of the cookie. Can be <see langword="null" /> if it should expire at the end of the session.</param>
public NancyCookie(string name, string value, DateTime expires)
: this(name, value, false, false, expires)
: this(name, value, false, false, expires, null)
{
}

Expand All @@ -42,7 +42,7 @@ public NancyCookie(string name, string value, DateTime expires)
/// <param name="value">The value of the cookie.</param>
/// <param name="httpOnly">Whether the cookie is http only.</param>
public NancyCookie(string name, string value, bool httpOnly)
: this(name, value, httpOnly, false, null)
: this(name, value, httpOnly, false, null, null)
{
}

Expand All @@ -55,7 +55,7 @@ public NancyCookie(string name, string value, bool httpOnly)
/// <param name="httpOnly">Whether the cookie is http only.</param>
/// <param name="secure">Whether the cookie is secure (i.e. HTTPS only).</param>
public NancyCookie(string name, string value, bool httpOnly, bool secure)
: this(name, value, httpOnly, secure, null)
: this(name, value, httpOnly, secure, null, null)
{
}

Expand All @@ -68,13 +68,15 @@ public NancyCookie(string name, string value, bool httpOnly, bool secure)
/// <param name="httpOnly">Whether the cookie is http only.</param>
/// <param name="secure">Whether the cookie is secure (i.e. HTTPS only).</param>
/// <param name="expires">The expiration date of the cookie. Can be <see langword="null" /> if it should expire at the end of the session.</param>
public NancyCookie(string name, string value, bool httpOnly, bool secure, DateTime? expires)
/// <param name="sameSite">The same site attribute of the cookie. Can be <see langword="null" />.</param>
public NancyCookie(string name, string value, bool httpOnly, bool secure, DateTime? expires, SameSite? sameSite = null)
{
this.Name = name;
this.Value = value;
this.HttpOnly = httpOnly;
this.Secure = secure;
this.Expires = expires;
this.SameSite = sameSite;
}

/// <summary>
Expand Down Expand Up @@ -135,6 +137,11 @@ public string EncodedValue
/// </summary>
public bool Secure { get; private set; }

/// <summary>
/// Wheather the cookie is same site
/// </summary>
public SameSite? SameSite { get; set; }

/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
Expand Down Expand Up @@ -169,7 +176,12 @@ public override string ToString()
sb.Append("; HttpOnly");
}

if(SameSite.HasValue)
{
sb.Append("; samesite=").Append(SameSite.ToString());
}

return sb.ToString();
}
}
}
}
29 changes: 29 additions & 0 deletions src/Nancy/Cookies/SameSite.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Nancy.Cookies
{
/// <summary>
/// Represents the SameSite for NancyCookie
/// </summary>
public enum SameSite
{
/// <summary>
/// If the value is invalid, the cookie will only be sent along with
/// "same-site" requests. If the value is "Lax", the cookie will be
/// sent with "same-site" requests, and with "cross-site" top-level navigations
/// </summary>
Lax = 0,

/// <summary>
/// If you set SameSite to Strict, your cookie will only be sent in a
/// first-party context. In user terms, the cookie will only be sent
/// if the site for the cookie matches the site currently shown in
/// the browser's URL bar.
/// </summary>
Strict,

/// <summary>
/// Cookies with SameSite=None must also specify Secure,
/// meaning they require a secure context.
/// </summary>
None
}
}
12 changes: 11 additions & 1 deletion test/Nancy.Tests/Unit/NancyCookieFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ public void Should_encode_value_if_necessary()
result.ShouldEqual("Value+with+spaces");
}

[Fact]
public void Should_add_same_site_if_set()
{
// When
var cookie = new NancyCookie("leto", "worm") { SameSite = SameSite.Lax }.ToString();

// Then
cookie.ShouldEqual("leto=worm; path=/; samesite=Lax");
}

public static string GetInvariantAbbreviatedMonthName(DateTime dateTime)
{
return CultureInfo.InvariantCulture.DateTimeFormat.AbbreviatedMonthNames[dateTime.Month - 1];
Expand All @@ -173,4 +183,4 @@ public static string GetInvariantAbbreviatedWeekdayName(DateTime dateTime)
}

}
}
}