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

Commit

Permalink
Add SameSite support for NancyCookies
Browse files Browse the repository at this point in the history
SameSite property will accept Lax, Strict and None values.

Fix #3002
  • Loading branch information
Ali Bahrami committed Mar 10, 2020
1 parent 11ac0fe commit 60e7596
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
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)
}

}
}
}

0 comments on commit 60e7596

Please sign in to comment.